Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .agent/standards_manifesto.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ This document provides the immutable technical standards for all AI agents (Anth
## 6. Clean-Slate Repo Hygiene (The "Hygiene Rule")

- **Zero-Delta Mandate**: Every new Mission (initialized via `$MISSION`) MUST start with a 0-delta `main` branch. If "Big Numbers" (large uncommitted/unmerged diffs > 100 lines) exist, the agent MUST recommend a cleanup/merge before starting new work.
- **Autonomous Pull Request Handover (The Fresh PR Rule)**: When submitting code for bot audit or human review, agents MUST NEVER push to an existing open Pull Request (e.g., updating a dirty branch). Instead, agents MUST:
1. Checkout a completely new semantic branch (e.g., `build/955-audit-remediation`).
2. Push the new branch and open a BRAND NEW Pull Request targeting `main`.
3. Close any superseded or legacy PRs via the GitHub CLI, explicitly leaving a comment referencing the new clean PR.
_Why? Incrementally updating existing PRs can cause automated audit bots (Codex, Greptile, DeepSource) to miss context. A fresh PR triggers a 100% clean, full-file audit sweep._
- **Atomic Missions**: Every bug fix or feature MUST be its own branch and MUST be merged into `main` immediately upon verification (e.g. F5 compile in NT8). No "stacking" unrelated fixes in long-lived branches.
- **Binary & Log Purge**: Never commit `.exe`, `.log`, `.bak`, or legacy backup folders to source control. They should be stashed, deleted, or added to `.gitignore`.
- **Dashboard Cleanup**: Before ending a session, the agent MUST ensure all work is either Committed or the user has been guided to Merge. The goal is a +0/-0 dashboard between missions.
Expand Down Expand Up @@ -156,6 +161,15 @@ OnLineInfo ... status=open <- live untracked GTC order at broker

**Full discovery steps:** See `.agent/workflows/live-bug-triage.md` Section 0.

## 12. Claude Agent Operation Protocol (Usage Insights)

**Based on historical friction data, all agents MUST adhere to these execution constraints:**

- **The "Do Not Interrupt" Protocol:** Agents operating in standard execution mode should complete their logical batches and commit _autonomously_. Do not pause mid-task to ask for user check-ins unless explicitly blocked by a missing file or a hard compilation failure.
- **.NET 4.8 Hardening Hook:** Target framework is .NET 4.8. Do NOT use C# features unavailable in .NET 4.8 (e.g., range operators `[..]`, `Index`/`Range` types, default interface implementations). Always use `CultureInfo.InvariantCulture` for numeric parsing. This must be checked before every commit.
- **The "Missing Brief" Failsafe:** Before any phase starts, the Agent MUST verify that the referenced `implementation_plan.md` or `$MISSION` artifact exists on disk. If it does not, the Agent MUST halt and ask the user for the brief, rather than attempting to guess or reverse-engineer the plan via codebase searches.
- **Autonomy Rule (Default to Action):** Agents are empowered and EXPECTED to execute the full end-to-end lifecycle of a task autonomously. This includes branch creation, surgical implementation, local verification (compile/ASCII), git committing, pushing, and opening/updating PRs. Do not wait for manual approval to move from "Code Change" to "Git Push" if local verification (`deploy-sync.ps1`) passes.

---

> [!NOTE]
Expand Down
47 changes: 47 additions & 0 deletions .github/workflows/codex-audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Codex Pre-Triage PR Audit

on:
pull_request:
types: [opened, synchronize, reopened]
branches: [main, master]

permissions:
pull-requests: write
contents: read

jobs:
codex-audit:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install Aider (OpenAI CLI)
run: pip install aider-chat
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pip install aider-chat installs the latest version without pinning. This could cause unpredictable CI behavior if the aider-chat package releases a breaking change. Consider pinning to a specific version (e.g., pip install aider-chat==0.XX.Y).

Suggested change
run: pip install aider-chat
run: pip install aider-chat==0.68.0

Copilot uses AI. Check for mistakes.

- name: Run Codex Audit via OpenAI
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
# Use Aider in headless mode to execute the audit using GPT-4o
aider --model gpt-4o --no-auto-commits --yes-always --message "Execute audit mission: .agent/brain/codex_pr25_audit.md. Read the workflows and write the final P1/P2/P3 severity report safely to audit_output.md without modifying any source files." > audit_output.md
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded PR-specific audit file breaks all future runs

The Aider command hardcodes .agent/brain/codex_pr25_audit.md as the mission file. This file is specific to PR #25. On every subsequent PR this workflow runs against, Aider will either load stale PR-25 instructions or fail to find the file entirely, producing an irrelevant or erroneous audit comment.

Additionally, aider writes interactive initialization text, model confirmations, and token-cost summaries to stdout. Redirecting with > audit_output.md captures all of that noise alongside (or instead of) the actual audit output, so the PR comment will contain Aider's session chatter rather than a clean report.

Consider parameterizing the audit file path using the PR number or a generic default audit brief, and capturing only the written audit_output.md file (as the step already does in the fallback branch) rather than relying on stdout redirect:

aider --model gpt-4o --no-auto-commits --yes-always \
  --message "Execute audit mission: .agent/brain/generic_pr_audit.md. Write the final P1/P2/P3 severity report to audit_output.md without modifying any source files."

Comment on lines +34 to +35
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security concern: aider --yes-always auto-approves all file-modification proposals from the LLM. While --no-auto-commits prevents git commits, the LLM could still modify source files on disk during the run (the message "without modifying any source files" is just a prompt instruction, not enforced). Consider using Aider's --no-auto-commits together with --dry-run or a read-only checkout, or better yet, replace Aider with a pure read-only API call that cannot write files. Additionally, the aider output is redirected to audit_output.md via >, but Aider may write its actual report as a separate file or interleave terminal control characters, making the posted comment potentially garbled.

Suggested change
# Use Aider in headless mode to execute the audit using GPT-4o
aider --model gpt-4o --no-auto-commits --yes-always --message "Execute audit mission: .agent/brain/codex_pr25_audit.md. Read the workflows and write the final P1/P2/P3 severity report safely to audit_output.md without modifying any source files." > audit_output.md
# Use Aider in headless dry-run mode to execute the audit using GPT-4o without modifying any files
aider --model gpt-4o --no-auto-commits --dry-run --message "Execute audit mission: .agent/brain/codex_pr25_audit.md. Read the workflows and write the final P1/P2/P3 severity report safely to audit_output.md without modifying any source files." > audit_output.md

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Point audit workflow to an existing mission file

The workflow hardcodes .agent/brain/codex_pr25_audit.md in the Aider prompt, but that file is not present in this repository (repo-wide file search only finds .agent/workflows/multi_agent_audit.md), so the audit job cannot follow the intended mission brief and can produce inconsistent or generic review output. Update this path to a real checked-in mission document (or add the missing file).

Useful? React with 👍 / 👎.


- name: Post Audit Results to PR
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [ -f audit_output.md ]; then
gh pr comment ${{ github.event.pull_request.number }} --body-file audit_output.md
else
echo "Audit output file not found."
# Fallback if Aider stdout'd it instead
gh pr comment ${{ github.event.pull_request.number }} --body "The OpenAI audit finished, but the markdown file was not saved correctly. Please check action logs."
fi
Comment on lines +30 to +47
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

In GitHub Actions, do later steps run by default after a previous step fails, and are repository secrets available to pull_request workflows from forks?

💡 Result:

  • Do later steps run after a step fails (by default)? No. Steps effectively have an implicit condition of if: success(), so after a failure, subsequent steps are skipped unless you override that (e.g., with if: always() / if: failure() or by marking the failing step continue-on-error: true). [1]

  • Are repository secrets available to pull_request workflows from forks? No. For pull_request events from forked repositories, GitHub does not provide repository secrets (and the GITHUB_TOKEN is read-only). [2] [3]


Add if: always() to the PR comment step and mark the audit step with continue-on-error: true.

If the audit step fails, the PR comment step is skipped by default (GitHub Actions implicitly uses if: success() on each step). This causes the workflow to exit silently without notifying reviewers of the failure.

Additionally, the OPENAI_API_KEY secret will not be available when the workflow runs on pull requests from forked repositories, causing the audit to fail immediately with no way to post a failure notice to the PR without the fix.

Suggested hardening
       - name: Run Codex Audit via OpenAI
+        id: audit
+        continue-on-error: true
         env:
           OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
         run: |
           # Use Aider in headless mode to execute the audit using GPT-4o
           aider --model gpt-4o --no-auto-commits --yes-always --message "Execute audit mission: .agent/brain/codex_pr25_audit.md. Read the workflows and write the final P1/P2/P3 severity report safely to audit_output.md without modifying any source files." > audit_output.md

       - name: Post Audit Results to PR
+        if: always()
         env:
           GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          AUDIT_OUTCOME: ${{ steps.audit.outcome }}
         run: |
-          if [ -f audit_output.md ]; then
+          if [ -s audit_output.md ]; then
             gh pr comment ${{ github.event.pull_request.number }} --body-file audit_output.md
           else
-            echo "Audit output file not found."
-            # Fallback if Aider stdout'd it instead
-            gh pr comment ${{ github.event.pull_request.number }} --body "The OpenAI audit finished, but the markdown file was not saved correctly. Please check action logs."
+            gh pr comment ${{ github.event.pull_request.number }} --body "Codex audit ${AUDIT_OUTCOME}. Please check the workflow logs."
           fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Run Codex Audit via OpenAI
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
# Use Aider in headless mode to execute the audit using GPT-4o
aider --model gpt-4o --no-auto-commits --yes-always --message "Execute audit mission: .agent/brain/codex_pr25_audit.md. Read the workflows and write the final P1/P2/P3 severity report safely to audit_output.md without modifying any source files." > audit_output.md
- name: Post Audit Results to PR
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [ -f audit_output.md ]; then
gh pr comment ${{ github.event.pull_request.number }} --body-file audit_output.md
else
echo "Audit output file not found."
# Fallback if Aider stdout'd it instead
gh pr comment ${{ github.event.pull_request.number }} --body "The OpenAI audit finished, but the markdown file was not saved correctly. Please check action logs."
fi
- name: Run Codex Audit via OpenAI
id: audit
continue-on-error: true
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
# Use Aider in headless mode to execute the audit using GPT-4o
aider --model gpt-4o --no-auto-commits --yes-always --message "Execute audit mission: .agent/brain/codex_pr25_audit.md. Read the workflows and write the final P1/P2/P3 severity report safely to audit_output.md without modifying any source files." > audit_output.md
- name: Post Audit Results to PR
if: always()
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
AUDIT_OUTCOME: ${{ steps.audit.outcome }}
run: |
if [ -s audit_output.md ]; then
gh pr comment ${{ github.event.pull_request.number }} --body-file audit_output.md
else
gh pr comment ${{ github.event.pull_request.number }} --body "Codex audit ${AUDIT_OUTCOME}. Please check the workflow logs."
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/codex-audit.yml around lines 30 - 47, Update the workflow
so the "Run Codex Audit via OpenAI" step is allowed to fail without stopping the
job by adding continue-on-error: true to that step, and ensure the "Post Audit
Results to PR" step is always executed by adding if: always() to it; reference
the step names "Run Codex Audit via OpenAI" and "Post Audit Results to PR" when
locating the changes, and keep the existing env usage (OPENAI_API_KEY remains
for the audit step while GH_TOKEN stays for the PR comment) so that even if the
audit fails (or the API key is unavailable for forked PRs) the PR comment step
still runs to post a failure notice.

96 changes: 96 additions & 0 deletions .github/workflows/gemini-pr-audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
name: Gemini PR Auditor

on:
pull_request:
types: [opened, synchronize, reopened]

jobs:
gemini-audit:
name: Gemini 2.5 Pro (High) Auto-Auditor
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write

steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Extract PR diff
id: diff
run: |
git diff origin/${{ github.event.pull_request.base.ref }}...HEAD > pr.diff

- name: Authenticate to Google Cloud
id: auth
uses: google-github-actions/auth@v2
with:
credentials_json: "${{ secrets.GCP_CREDENTIALS }}"

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Install Vertex AI SDK
run: npm install @google-cloud/vertexai
Comment on lines +26 to +38
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's locate and read the actual workflow file
find . -name "gemini-pr-audit.yml" -type f 2>/dev/null | head -20

Repository: mkalhitti-cloud/universal-or-strategy

Length of output: 120


🏁 Script executed:

# Also check if the file path matches what was mentioned
ls -la .github/workflows/gemini-pr-audit.yml 2>/dev/null || echo "File not found at expected path"

Repository: mkalhitti-cloud/universal-or-strategy

Length of output: 167


🏁 Script executed:

# If found, read the complete workflow file with line numbers
if [ -f .github/workflows/gemini-pr-audit.yml ]; then
  wc -l .github/workflows/gemini-pr-audit.yml
  echo "---"
  cat -n .github/workflows/gemini-pr-audit.yml
fi

Repository: mkalhitti-cloud/universal-or-strategy

Length of output: 4309


🌐 Web query:

How does google-github-actions/auth@v2 handle credentials in GitHub Actions workflows

💡 Result:

google-github-actions/auth@v2 authenticates a workflow in one of two ways (you must choose exactly one): Workload Identity Federation (OIDC) via workload_identity_provider (optionally with service_account impersonation), or a long‑lived Service Account key via credentials_json. When using OIDC, the job must have permissions: id-token: write, and the action exchanges the GitHub OIDC JWT for a Google Cloud token (and, if configured, an impersonated service-account access token). [2]

How credentials are made available to later steps

  • Credentials file (ADC) (default behavior): with create_credentials_file: true (default), the action writes a generated credentials file into $GITHUB_WORKSPACE and exposes its path as the credentials_file_path output. This is designed to work with tools that use Application Default Credentials (ADC). The file is removed automatically at the end of the job by a post-step when cleanup_credentials: true (default). [1]
  • Environment variables (default behavior): with export_environment_variables: true (default), the action exports common project env vars (e.g., GOOGLE_CLOUD_PROJECT, GCLOUD_PROJECT, etc.). If a credentials file is created, it also exports ADC-related vars including:
    • GOOGLE_APPLICATION_CREDENTIALS
    • CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE
    • GOOGLE_GHA_CREDS_PATH [3]

Outputs / tokens

The action always outputs an auth_token, and can additionally output an access_token or id_token depending on configuration; it also outputs credentials_file_path when a file is created. [1]

Service Account key handling (credentials_json)

If you use credentials_json, you’re providing long-lived credentials that must be treated like a password (typically stored as a GitHub Secret and passed to the action). [4]

Sources: GitHub Marketplace listing for the action (inputs/outputs and env/file behavior) [1][3][4], GitHub Docs on OIDC + the action’s token exchange requirements [2].


🌐 Web query:

npm lifecycle scripts access to environment variables GitHub Actions secrets

💡 Result:

How npm lifecycle scripts can access GitHub Actions secrets

  1. Expose the secret as an environment variable in your workflow
    GitHub Actions secrets are available via the secrets context, but your step must pass them (commonly via env:) to the process that runs npm/Node. (docs.github.com)
# .github/workflows/ci.yml
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Install & test
        env:
          MY_API_KEY: ${{ secrets.MY_API_KEY }}
        run: |
          npm ci
          npm test
  1. Read it inside npm scripts
  • In Node code run by your scripts: process.env.MY_API_KEY (nodejs.org)
  • In shell commands inside package.json scripts: $MY_API_KEY (bash) / %MY_API_KEY% (cmd)
{
  "scripts": {
    "test": "node -e \"console.log(!!process.env.MY_API_KEY)\""
  }
}
  1. Remember npm also injects its own script-related env vars
    When npm runs lifecycle scripts, it sets helpful variables like npm_package_* and npm_lifecycle_event in the environment. (docs.npmjs.com)

Common “why is my secret empty?” cases

  • Workflows triggered by pull_request from forks don’t get secrets (and GITHUB_TOKEN is read-only). (github.blog)
  • Dependabot PR workflows also don’t get repository secrets by default. (github.blog)

Security note

If you map a secret into env:, that value is available to any code your step executes; GitHub recommends treating this as sensitive and defending against script-injection/untrusted-code scenarios. (securitylab.github.com)

Citations:


Avoid installing npm packages with lifecycle scripts after exposing GCP credentials.

Line 38 runs npm install without --ignore-scripts after Line 26–30 has loaded GCP credentials into GOOGLE_APPLICATION_CREDENTIALS. npm lifecycle scripts (preinstall, install, postinstall) inherit the environment and can exfiltrate this credential. Use npm install --ignore-scripts --no-save @google-cloud/vertexai@<pinned-version> to prevent script execution, or move the install step before authentication so scripts never have access to credentials.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/gemini-pr-audit.yml around lines 26 - 38, The "Install
Vertex AI SDK" step currently runs "npm install `@google-cloud/vertexai`" after
the "Authenticate to Google Cloud" (id: auth, uses:
google-github-actions/auth@v2) step which exposes
GOOGLE_APPLICATION_CREDENTIALS; change the install to avoid running lifecycle
scripts with credentials by either moving the "Install Vertex AI SDK" step to
before the "Authenticate to Google Cloud" step or modify the run command to use
a safe install: run npm install --ignore-scripts --no-save
`@google-cloud/vertexai`@<pinned-version> (pin a specific version) so no
preinstall/install/postinstall scripts inherit GCP creds; ensure the workflow no
longer executes npm scripts while GOOGLE_APPLICATION_CREDENTIALS is set.


- name: Run Vertex AI Audit and Post Comment
uses: actions/github-script@v7
env:
GCP_PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
GCP_REGION: us-central1
with:
script: |
const fs = require('fs');
const { VertexAI } = require('@google-cloud/vertexai');

const diffContent = fs.readFileSync('pr.diff', 'utf8');
let geminiMdContent = '';
try {
geminiMdContent = fs.readFileSync('GEMINI.md', 'utf8');
} catch (e) {
console.log('GEMINI.md not found in the root directory, proceeding without it.');
}

const prompt = `You are the Gemini CLI (Antigravity Auto-Auditor) acting as a PR reviewer.
Your task is to analyze the following PR diff strictly against our project's GEMINI.md standards (Zero-Trust IPC, FSM mutations, etc.).

Here are the GEMINI.md standards:
${geminiMdContent}

Here is the pull request diff:
${diffContent}

Provide a systematic review of the changes:
1. Evaluate strict adherence to the standards (e.g., FSM replace pattern vs cancel+submit, lock guards, headless UI rules).
2. Point out any violations of the standard with specific file and line context.
3. If the code is perfectly aligned, state that it passes the Zero-Regression Bot Audit.

Be thorough, precise, and uncompromising on the rules.`;
Comment on lines +50 to +72
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cd .github/workflows && wc -l gemini-pr-audit.yml

Repository: mkalhitti-cloud/universal-or-strategy

Length of output: 103


🏁 Script executed:

cat -n .github/workflows/gemini-pr-audit.yml

Repository: mkalhitti-cloud/universal-or-strategy

Length of output: 4264


🏁 Script executed:

rg "Vertex|vertex|API|model|token|limit" .github/workflows/gemini-pr-audit.yml -A 2

Repository: mkalhitti-cloud/universal-or-strategy

Length of output: 1027


🌐 Web query:

Gemini 3.1 Pro context window token limit size

💡 Result:

Gemini 3.1 Pro (gemini-3.1-pro-preview) supports a 1,048,576-token (≈1M) input context window (input token limit) and can generate up to 65,536 output tokens per request. [1][2]


🌐 Web query:

Google Vertex AI Gemini 3.1 Pro input token limit specifications

💡 Result:

On Vertex AI, the (preview) Gemini 3.1 Pro model endpoint gemini-3.1-pro-preview supports a maximum input token limit of 1,048,576 tokens (with 65,536 max output tokens). [2]

Google’s Vertex AI docs also note that gemini-3-pro-preview is being deprecated (Mar 26, 2026) and workflows should migrate to gemini-3.1-pro-preview; the Gemini 3 Pro preview page lists the same 1,048,576 max input tokens. [1]

Sources: [1] [2]


🏁 Script executed:

ls -lh GEMINI.md 2>/dev/null || echo "GEMINI.md not found"

Repository: mkalhitti-cloud/universal-or-strategy

Length of output: 139


🏁 Script executed:

if [ -f GEMINI.md ]; then wc -c GEMINI.md; else echo "File does not exist"; fi

Repository: mkalhitti-cloud/universal-or-strategy

Length of output: 95


Consider adding input size validation before sending to Vertex AI.

While Gemini 3.1 Pro supports a 1M-token context window (~4.2MB), the code currently inlines pr.diff and GEMINI.md without any size checks. For typical PRs this is not a practical concern, but adding explicit guards makes the pipeline more robust. Consider validating combined input size and either truncating, summarizing, or failing gracefully if a threshold is exceeded—this prevents edge cases where unusually large diffs could be silently truncated or degrade response quality.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/gemini-pr-audit.yml around lines 50 - 72, The prompt
currently inlines diffContent and geminiMdContent without size checks; add
explicit input-size validation after reading pr.diff and GEMINI.md by computing
their byte length (e.g., Buffer.byteLength) and comparing against a
MAX_PROMPT_BYTES constant (set to a safe threshold like 4MB/4.2MB or
token-derived limit). If the combined size exceeds the threshold, either (a)
truncate or summarize diffContent/geminiMdContent before building prompt, or (b)
log an error and fail the job gracefully; update the code around the
diffContent/geminiMdContent reads and the prompt construction (the variables
diffContent, geminiMdContent, and prompt) to enforce this behavior and include a
clear log message stating the action taken.


const vertex_ai = new VertexAI({project: process.env.GCP_PROJECT_ID, location: process.env.GCP_REGION});
// Gemini 2.5 Pro via Vertex AI
const generativeModel = vertex_ai.preview.getGenerativeModel({
model: 'gemini-2.5-pro',
});

let reviewText = '';
try {
const resp = await generativeModel.generateContent({
contents: [{role: 'user', parts: [{text: prompt}]}],
});
reviewText = resp.response.candidates[0].content.parts[0].text;
} catch (error) {
console.error("Error calling Vertex AI API:", error);
reviewText = "⚠️ **Vertex AI Audit Failed to Execute**: " + error.message;
}

await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: "### 🤖 Antigravity Auto-Auditor (Gemini 2.5 Pro via Vertex AI)\n\n" + reviewText
});
14 changes: 13 additions & 1 deletion src/V12_001.cs
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,19 @@ private void LoadConfig()
selectedTargetCount = activeCount;

Button modeBtn = GetModeButton(activeMode);
if (modeBtn != null) HighlightModeButton(modeBtn);
if (modeBtn != null)
{
HighlightModeButton(modeBtn);
}
else
{
// [Build 954]: Saved mode is deprecated/unrecognized -- normalize both vars to RMA baseline.
Print("[WARN][954] Unrecognized saved mode '" + activeMode + "' -- falling back to RMA.");
activeMode = "RMA";
selectedConfigMode = "RMA";
modeBtn = GetModeButton("RMA");
if (modeBtn != null) HighlightModeButton(modeBtn);
}
Comment on lines 787 to +800
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

The new unknown-mode fallback is effectively unreachable.

GetModeButton() falls back to modeOrbButton for unrecognized values, so modeBtn != null is still true for bad saved modes and the RMA recovery branch never runs once the buttons are initialized. That leaves the UI highlighted as ORB while selectedConfigMode stays invalid.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/V12_001.cs` around lines 785 - 798, GetModeButton currently returns
modeOrbButton as a fallback so the null-check never triggers; update the logic
to detect unrecognized saved modes instead of relying on null. Either (A) change
GetModeButton to return null for inputs it doesn't recognize, or (B) after
calling GetModeButton(activeMode) check whether activeMode is in the known modes
list (or whether the returned button equals modeOrbButton while activeMode !=
"ORB") and treat that as an unrecognized mode to run the RMA recovery branch
(reset activeMode and selectedConfigMode to "RMA" and then call
GetModeButton("RMA")/HighlightModeButton). Ensure you reference GetModeButton,
HighlightModeButton, activeMode and selectedConfigMode when applying the fix.


// Apply active mode+count settings to UI
ApplySettings(fullConfig.GetSettings(activeMode, activeCount));
Expand Down
12 changes: 8 additions & 4 deletions src/V12_002.Entries.Retest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ private void ExecuteRetestEntry(int contracts)
};
ApplyTargetLadderGuard(pos);

activePositions[entryName] = pos;
lock (stateLock) { activePositions[entryName] = pos; }

// Build 1102Y-V3 [MS-07]: Register Master expected BEFORE Limit entry.
int masterDeltaRetest = (direction == MarketPosition.Long) ? contracts : -contracts;
Expand All @@ -185,10 +185,12 @@ private void ExecuteRetestEntry(int contracts)
if (entryOrder == null)
{
AddExpectedPositionDeltaLocked(ExpKey(Account.Name), -masterDeltaRetest);
lock (stateLock) { activePositions.TryRemove(entryName, out _); } // [Build 956]: Clean pre-registered state on null submit.
Print("[ERROR][1102Y-V3] RETEST SubmitOrderUnmanaged NULL for " + entryName + " -- rolled back.");
return; // [Build 954]: Do not latch session or dispatch SIMA for a failed order.
}

entryOrders[entryName] = entryOrder;
lock (stateLock) { entryOrders[entryName] = entryOrder; }
Comment on lines 185 to +193
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description claims "No logic changes" but return statements are newly added

The PR description states: "No logic changes -- TryRemove + early return in null-submit rollback paths were already correct from Build 956."

However, the diff clearly shows both return lines being added (+) in this PR (lines 190 and 332). These are meaningful logic changes:

  • Before this PR: When SubmitOrderUnmanaged returned null, execution fell through the error print and continued to entryOrders[entryName] = entryOrder — writing a null order reference into entryOrders — and then set retestFiredThisSession = true, permanently suppressing all further RETEST entries for the session despite no order having been placed.
  • After this PR: Execution correctly returns early, preserving entryOrders integrity and not latching retestFiredThisSession.

The same issue and fix apply identically to ExecuteRetestManualEntry at line 332. These are critical correctness fixes and should be documented as such rather than described as "no logic changes."

Comment on lines 174 to +193
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Split lock window exposes partially-registered state to callbacks

The three lock(stateLock) blocks are acquired separately across the SubmitOrderUnmanaged call:

lock (stateLock) { activePositions[entryName] = pos; }   // Lock #1

Order entryOrder = SubmitOrderUnmanaged(...);              // Callbacks can fire here

lock (stateLock) { entryOrders[entryName] = entryOrder; } // Lock #3

Between Lock #1 and Lock #3, any callback that iterates activePositions will find entryName registered — but entryOrders.TryGetValue(entryName, ...) will return false since the order has not yet been written. Code paths in HandleOrderCancelled and similar callbacks that walk activePositions and cross-reference entryOrders will see an inconsistent view during this window.

This is the same pattern in both ExecuteRetestEntry (L174–L193) and ExecuteRetestManualEntry (L316–L334).

The window is structurally unavoidable because SubmitOrderUnmanaged cannot be called while holding stateLock (risk of deadlock via re-entrant callbacks), but the inconsistency should be documented or the callers guarded. Consider adding a null guard in HandleOrderCancelled and other callbacks when entryOrders.TryGetValue fails for a key that exists in activePositions to avoid acting on a partially-initialized entry.

retestFiredThisSession = true; // V12.1101E [B-2]: Arm latch -- no further RETEST entries this session

Print(string.Format("RETEST ENTRY ORDER: {0} {1}@{2:F2} | ATR: {3:F2}", signalName, contracts, entryPrice, currentATR));
Expand Down Expand Up @@ -311,7 +313,7 @@ private void ExecuteRetestManualEntry(double manualPrice, MarketPosition directi
};
ApplyTargetLadderGuard(pos);

activePositions[entryName] = pos;
lock (stateLock) { activePositions[entryName] = pos; }

// Build 1102Y-V3 [MS-08]: Register Master expected BEFORE Limit entry.
int masterDeltaRetestMnl = (direction == MarketPosition.Long) ? contracts : -contracts;
Expand All @@ -325,9 +327,11 @@ private void ExecuteRetestManualEntry(double manualPrice, MarketPosition directi
if (entryOrder == null)
{
AddExpectedPositionDeltaLocked(ExpKey(Account.Name), -masterDeltaRetestMnl);
lock (stateLock) { activePositions.TryRemove(entryName, out _); } // [Build 956]: Clean pre-registered state on null submit.
Print("[ERROR][1102Y-V3] RETEST_MANUAL SubmitOrderUnmanaged NULL for " + entryName + " -- rolled back.");
return; // [Build 956]: Do not assign null entryOrder or dispatch SIMA for a failed order.
}
entryOrders[entryName] = entryOrder;
lock (stateLock) { entryOrders[entryName] = entryOrder; }

Print(string.Format("V12.27 RETEST_MANUAL: {0} {1}@{2:F2} LIMIT | Stop: {3:F2} | RMA Targets",
direction, contracts, entryPrice, stopPrice));
Expand Down
27 changes: 17 additions & 10 deletions src/V12_002.Orders.Callbacks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -369,9 +369,12 @@ private bool HandleOrderCancelled(Order order)
{
if (kvp.Value.OldOrder == order && activePositions.TryGetValue(kvp.Key, out var pos))
{
if (pos.RemainingContracts > 0)
// Build 955: Snapshot qty under stateLock -- single atomic read for both check and use.
int _stopQty;
lock (stateLock) { _stopQty = pos.RemainingContracts; }
if (_stopQty > 0)
{
CreateNewStopOrder(kvp.Key, pos.RemainingContracts, kvp.Value.StopPrice, kvp.Value.Direction);
CreateNewStopOrder(kvp.Key, _stopQty, kvp.Value.StopPrice, kvp.Value.Direction);
// Build 950: Restore OCO-cascade-cancelled targets after stop replacement.
if (kvp.Value.BracketRestorationNeeded && kvp.Value.CapturedTargets != null)
{
Expand Down Expand Up @@ -598,18 +601,22 @@ private void HandleMatchedFollowerOrder(string matchedEntry, PositionInfo matche
if (_psr.Value.OldOrder == order)
{
PositionInfo _rPos;
if (activePositions.TryGetValue(_psr.Key, out _rPos) && _rPos.RemainingContracts > 0)
// Build 955: Move guard inside lock -- check and use same atomic snapshot.
if (activePositions.TryGetValue(_psr.Key, out _rPos))
{
int _rQty;
lock (stateLock) { _rQty = _rPos.RemainingContracts; }
CreateNewStopOrder(_psr.Key, _rQty, _psr.Value.StopPrice, _psr.Value.Direction);
if (_psr.Value.BracketRestorationNeeded && _psr.Value.CapturedTargets != null)
if (_rQty > 0)
{
TargetSnapshot[] _snap = _psr.Value.CapturedTargets;
string _rKey = _psr.Key;
TriggerCustomEvent(o => RestoreCascadedTargets(_rKey, _snap), null);
}
}
CreateNewStopOrder(_psr.Key, _rQty, _psr.Value.StopPrice, _psr.Value.Direction);
if (_psr.Value.BracketRestorationNeeded && _psr.Value.CapturedTargets != null)
{
TargetSnapshot[] _snap = _psr.Value.CapturedTargets;
string _rKey = _psr.Key;
TriggerCustomEvent(o => RestoreCascadedTargets(_rKey, _snap), null);
}
} // if (_rQty > 0)
} // if (activePositions.TryGetValue)
if (pendingStopReplacements.TryRemove(_psr.Key, out _))
Interlocked.Decrement(ref pendingReplacementCount);
return;
Expand Down
Loading
Loading