Skip to content

fix(deploy,verify,launcher): mechanism-hardening-2 bundle (#490 #491 #489-B) - #513

Merged
monkey1sai merged 16 commits into
mainfrom
fix/mechanism-hardening-2-bundle
Aug 12, 2026
Merged

fix(deploy,verify,launcher): mechanism-hardening-2 bundle (#490 #491 #489-B)#513
monkey1sai merged 16 commits into
mainfrom
fix/mechanism-hardening-2-bundle

Conversation

@monkey1sai

@monkey1sai monkey1sai commented Aug 12, 2026

Copy link
Copy Markdown
Owner

fix(deploy,verify,launcher): mechanism-hardening-2 bundle

Closes #490, closes #491#489 為 part-of。PR #513 review 後續修正納入同一 branch,避免在 canonical Linux fixpoint 前拆出另一個 deploy mechanism bundle。

變更摘要

補齊 .env.web-plane.host-kit.exampleKIT_CONTROL_URL= repo 樣板佔位,並修正 deploy 明示環境檔優先權與 process-tree 子程序列舉失敗的 fail-closed 行為。

修改原因

PR #513 的交叉審查證實兩個仍可重現的 P2:Phase 2 會覆寫 operator 明示的 -EnvFile;Windows CIM 或 Linux procfs 列舉失敗會被誤當成「沒有子程序」。兩者都可能讓部署在錯誤權威或未清乾淨的程序樹上繼續。

主要變更

  • .env.web-plane.host-kit.example 保留空值 placeholder,不寫入真實機密。
  • scripts/deploy.ps1 只在自動使用 .example fallback 時 repoint canonical env;明示 -EnvFile 保持不變。
  • scripts/lib/platform/platform-adapter.ps1 將成功空列舉與 CIM/procfs 讀取或解析失敗分開。
  • scripts/lib/host-native-launcher.ps1 對列舉失敗附 parent PID 並 fail closed。
  • 新增 explicit/fallback 雙向 deploy regression,以及 Windows/Linux enumeration fault regression。

變更分類

Item Result
Change lane G
Behavior contract changed yes
Requirement source issue #489, #490, #491 and PR #513 review findings

AI Coding Governance

Item Result
Linked issue #489, #490, #491
Requirement source issue #489 / #490 / #491 and PR #513 review findings
CODEOWNERS / owner review exact-head review pending
GitNexus evidence risk_level=UNKNOWN:GitNexus 1.6.9 exact-worktree index可執行 compare detect-changes,但 PowerShell symbol impact 對 Stop-HostNativeProcessTreeAndWaitGet-PlatformChildProcessIds 均 target-not-found;以直接 source、tests 與獨立 reviewer交叉裁決
Browser E2E evidence not applicable — no frontend product path changed
Agent workflow changed? no
Required checks expected agent-governance, CI affected jobs, PR metadata diagnostic, CODEOWNER exact-head approval

Deploy Path Verification

Item Result
Affects runtime / docker / Kit / viewer / ports / env? yes — deploy env authority selection、Kit control resolution與 host-native timeout cleanup
Canonical deploy path updated? yes — scripts/deploy.ps1scripts/lib/host-native-launcher.ps1scripts/lib/platform/platform-adapter.ps1
Deploy dry-run command pwsh -NoProfile -NonInteractive -File scripts/tests/test-deploy-dryrun.ps1(exact head exit 0)
Verify command pwsh -NoProfile -NonInteractive -File scripts/tests/test-verify-all.ps1(exact head exit 0)

Windows On-Demand Verification

Item Result
Windows verification tier deploy_dryrun
Windows verification evidence 於 exact reviewed head e4cd51d 在 Windows 實跑 test-deploy-dryrun.ps1test-deploy-governance-static.ps1test-platform-adapter.ps1test-host-native-launcher.ps1test-verify-all.ps1 與 PR review agent required checks,全部 exit 0;Windows PowerShell 5.1 targeted enumeration fail-closed probe 亦通過。Exact-head CI run:https://github.com/monkey1sai/AI-BIM-governance/actions/runs/31587458547(最終狀態以 PR checks 為準)。

Self-Referential Bootstrap

Item Result
Self-referential bootstrap yes
Bootstrap ledger entry mechanism-hardening-2
Bootstrap reason canonical Linux transport 只從 freshly fetched origin/main 重建並拒絕 unmerged revision;本 branch 變更 deploy resolver、platform adapter 與 process-tree terminator,只能在 merge 後以 mainline fixpoint 產生 canonical evidence

驗證方式

  • PowerShell 7:deploy governance static、deploy dry-run、platform adapter、host-native launcher、verify-all、bootstrap、agent governance、secret scan、rebuild transaction 與 PR review agent required checks 全部通過。
  • Windows PowerShell 5.1:rebuild transaction gate與 targeted enumeration fail-closed probe 通過。
  • Linux:targeted procfs fail-closed probe通過;CI platform adapter (linux) 已通過。
  • git diff --check 通過;latest origin/main merge 結果為 Already up to date,沒有衝突。
  • Exact-head CI:https://github.com/monkey1sai/AI-BIM-governance/actions/runs/31587458547。

風險與影響

正常的空 child set 仍可通過;只有無法可靠列舉時改為 fail closed。未修改 API、資料結構或真實 .env 值;新增/確認的環境變數契約為 repo 樣板 KIT_CONTROL_URL=。跨 orphan reparent 的強 containment 仍需 launch-time Job Object/process group,追蹤於 #522(Refs #517)。

回滾方式

若只撤回本輪 P2 修正,revert e4cd51db4f1f6d88c6aa0b1d73b8bb29b7e205a4;若撤回整個 bundle,於 merge 後 revert 對應 merge commit。

後續建議

monkey1sai and others added 3 commits August 12, 2026 12:02
The Phase 1 audit sealed $resolvedKitControlUrl and the Kit Manager runtime
signature before the Phase 2 ".env / .env.example missing-key merge" ran. That
merge can both append a missing KIT_CONTROL_URL and repoint $resolvedEnvFile
from the .example to the real env file, so a run that repaired the file still
started the host-native Kit Manager with the stale pre-merge value and then
persisted a signature describing the repaired state — a blocked
runtime-control state that reads as configured on the next run.

Pure relocation, not duplication: both assignments move down to immediately
after the env merge and volume fix. Nothing between the old and new positions
reads either variable, so the exactly-once AST guarantee asserted by
test-deploy-governance-static.ps1 is preserved. $resolvedAllowedStageHosts is
deliberately left where it is.

test-deploy-governance-static.ps1 gains index-ordering assertions that pin the
resolve, the signature build and the child launch after the merge marker.

Known delta: -DryRun exits before Phase 2, so it no longer validates
KIT_CONTROL_URL. The value it used to validate was the pre-merge one read from
whichever file the audit resolved, which is the stale read this change removes.

Refs #490

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
$expectedKitControlUrl was read verbatim from kit-manager-api.params.json and
only string-compared against the /health payload's kit_control_url. The
signature checks cover port and revision equality, which prove checkout
identity and nothing about URL policy, and the local-address assertion was
applied to host_native_bind_host and the conversion health host but never to
this URL. A REMOTE origin agreed between a drifted signature and a drifted
service therefore passed silently.

Assert-DeploymentKitControlUrlIsLocal now runs beside the two existing asserts
inside the same -not $PlanOnly guard. It deliberately re-implements the rule
from Resolve-HostNativeKitControlUrl rather than importing it — the verifier is
an independent layer, exactly as Assert-DeploymentHostNativeBindIsLocal
re-implements Test-HostNativeLocalAddress. Empty stays allowed as the honest
unconfigured state, localhost is accepted because the launcher canonicalises it
through, and non-literal hosts are refused without DNS resolution so the
verifier cannot be rebound.

test-verify-all.ps1 gains a locality accept/reject matrix, subprocess rejection
cases for a remote and a credentialed control URL, acceptance runs for
127.0.0.1 and localhost, an AST assertion that the verifier never calls the
launcher resolver, and a paired case proving that a matching-but-remote health
payload satisfies the identity comparison on its own.

Refs #491

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kill($true), WaitForExit and HasExited all describe the SAME Process object.
Microsoft documents that they can report completion while descendants are still
running, and the old catch additionally swallowed the tree-kill exception
whenever the parent had already exited — precisely the case where orphaned
grandchildren survive. The CAD hardener and the Kit Manager import probe use
this helper to prove a timed-out tree is gone before releasing the trust
boundary they hold, so the postcondition was false where it mattered most.

Second defect in the same helper: Process.Kill([bool]) does not exist on .NET
Framework, so under Windows PowerShell 5.1 the tree kill ALWAYS threw into that
catch and the helper silently degraded to parent-only termination.

The helper now snapshots the descendant PID set through
Get-PlatformChildProcessIds before terminating (afterwards the parent/child
links are gone and orphans are re-parented), guards the tree kill behind an
overload probe with the enumerated-PID fallback Stop-HostNativeService already
uses, and waits for the parent AND every snapshotted descendant inside one
bounded budget. Anything still alive throws instead of reporting success.
Descendant liveness is judged on process identity, not the bare PID, so a
recycled PID reads as "our descendant is gone" rather than failing a caller
closed on an unrelated process.

test-host-native-launcher.ps1 gains a dynamic hung-fixture case proving both
recorded PIDs exited inside the bounded window, a negative case with an
injected unkillable descendant proving the helper fails closed, and
source-shape assertions pinning the overload guard.

This commit also registers the bundle's single open ledger entry
`mechanism-hardening-2`, covering the three verification-mechanism paths this
pull request changes (#490 deploy.ps1, #491 verify-all.ps1, #489
host-native-launcher.ps1). One entry, one canonical Linux rebuild at fixpoint,
instead of three serialised debts for one hardening round.

Refs #489

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings August 12, 2026 04:06
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR validates local Kit control URLs, resolves Kit configuration after environment repair, hardens host-native process-tree termination, adds regression coverage, and records self-referential bootstrap evidence with an open fixpoint.

Changes

Mechanism hardening

Layer / File(s) Summary
Kit URL validation and deployment wiring
scripts/verify-all.ps1, scripts/deploy.ps1, scripts/tests/test-verify-all.ps1, scripts/tests/test-deploy-governance-static.ps1
Deployment validation accepts empty or local HTTP origins and rejects malformed, credential-bearing, nonlocal, or DNS-based URLs. Deployment resolves the final URL and runtime signature after environment repair.
Process-tree termination and regression coverage
scripts/lib/host-native-launcher.ps1, scripts/tests/test-host-native-launcher.ps1
Process termination snapshots descendant identities, supports tree-kill and PID fallback paths, handles exited parents, and verifies cleanup within a shared timeout.
Bootstrap ledger and verification evidence
scripts/self-referential-bootstrap-ledger.json, docs/evidence/mechanism-hardening-2/self-referential-bootstrap/README.md, docs/evidence/mechanism-hardening-2/self-referential-bootstrap/verification.txt
The PR adds an open mechanism-hardening ledger entry and documents verification results, limitations, evidence references, and post-merge fixpoint steps.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DeployScript
  participant EnvironmentFile
  participant URLValidator
  participant KitManager
  DeployScript->>EnvironmentFile: repair and read final values
  DeployScript->>URLValidator: validate Kit control URL
  URLValidator-->>DeployScript: accept local origin or reject
  DeployScript->>KitManager: start with resolved URL and runtime signature
Loading
sequenceDiagram
  participant Terminator
  participant ProcessAdapter
  participant ParentProcess
  participant DescendantProcesses
  Terminator->>ProcessAdapter: snapshot descendants and identities
  ProcessAdapter-->>Terminator: return process tree
  Terminator->>ParentProcess: terminate parent
  Terminator->>DescendantProcesses: terminate descendants
  Terminator->>ProcessAdapter: verify original identities exited
Loading

Possibly related PRs

Suggested reviewers: monkey1sai-blip

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the deploy, verification, and launcher hardening bundle and references the related issues.
Description check ✅ Passed The description directly explains the deployment, URL validation, process-tree termination, testing, and bootstrap changes.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/mechanism-hardening-2-bundle

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (3)
scripts/tests/test-verify-all.ps1 (1)

547-560: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a positive assertion to the acceptance run.

Both assertions are negative. If the Deployment run failed before the locality check (for example on a missing required artifact), the output would contain neither message and the case would pass without exercising Assert-DeploymentKitControlUrlIsLocal. Add one positive marker that proves the run reached the health targets, for example the kit manager health execution line or the health failure text.

♻️ Proposed additional assertion
         $acceptedResult = Invoke-VerificationExecution -RepoRoot $deploymentRoot -AdditionalArguments $executionArguments
+        Assert-True ($acceptedResult.Output -match 'kit manager health') "deployment execution reaches the Kit Manager target for '$acceptedKitControlUrl'"
         Assert-True ($acceptedResult.Output -notmatch 'loopback or an address assigned to this host') "deployment execution accepts local Kit control URL '$acceptedKitControlUrl'"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/tests/test-verify-all.ps1` around lines 547 - 560, Add a positive
assertion in the acceptance loop around Invoke-VerificationExecution to require
the expected Kit Manager health-check marker, such as the health execution line
or health failure text. Keep the existing negative locality and URL-shape
assertions, ensuring each acceptedKitControlUrl case proves execution reached
the health-target stage rather than passing prematurely.
scripts/tests/test-deploy-governance-static.ps1 (1)

467-470: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Guard $kitManagerStartIndex against -1 like the other two indices.

If the Start-HostNativeKitManager call text changes, IndexOf returns -1 and the test reports an ordering violation instead of a missing call. Lines 452 and 455 already separate these two failures. Keep the diagnostics consistent.

♻️ Proposed fix
 $kitManagerStartIndex = $deploy.IndexOf('Start-HostNativeKitManager -RepoRoot $RepoRoot -Port 8010 -KitControlUrl $resolvedKitControlUrl')
+if ($kitManagerStartIndex -lt 0) {
+    throw 'deploy.ps1 must start the host-native Kit Manager with the resolved control authority'
+}
 if ($kitManagerStartIndex -le $kitManagerSignatureIndex) {
     throw 'deploy.ps1 must start the host-native Kit Manager with the post-merge control authority'
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/tests/test-deploy-governance-static.ps1` around lines 467 - 470,
Update the assertion around $kitManagerStartIndex to handle an IndexOf result of
-1 separately from the ordering check, matching the existing guards for the
other indices. Report a missing Start-HostNativeKitManager call when absent, and
retain the current post-merge ordering diagnostic when the call exists but
appears too early.
scripts/tests/test-host-native-launcher.ps1 (1)

743-795: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add a case for a parent that has already exited.

The matrix covers a live tree and a surviving descendant. It does not cover the early return at host-native-launcher.ps1 Line 573. In that path the helper returns before it snapshots or terminates descendants, so the current tests cannot detect the orphan gap described on the launcher change. Add a case that starts the fixture, kills only the parent, and then calls Stop-HostNativeProcessTreeAndWait with an injected ChildPidLookup that still reports the child.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/tests/test-host-native-launcher.ps1` around lines 743 - 795, Add a
test case covering an already-exited parent: start the tree fixture, terminate
only its parent, then invoke Stop-HostNativeProcessTreeAndWait with injected
ChildPidLookup and related test doubles that still expose the child. Assert the
helper processes the reported descendant rather than returning early, and retain
bounded cleanup and failure assertions consistent with the existing survivor
case.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/evidence/mechanism-hardening-2/self-referential-bootstrap/README.md`:
- Line 28: Update the self-referential-bootstrap evidence metadata to record the
exact reviewed head commit and the clean-worktree result used for the run. Add
these values to both README.md and verification.txt as needed, preserving the
existing baseline commit and PASS results while making the evidence traceable to
the reviewed revision.

In
`@docs/evidence/mechanism-hardening-2/self-referential-bootstrap/verification.txt`:
- Around line 7-22: Update the PASS result records in the verification artifact
to include either the resolved command that executed or a direct reference to
the immutable command-map revision used for each command ID. Preserve the
existing explicit NOT_RUN records and ensure every PASS entry is traceable to
the validation command actually executed.

In `@scripts/deploy.ps1`:
- Around line 1387-1406: Preserve KIT_CONTROL_URL validation during -DryRun by
ensuring malformed or remote values are rejected with operator feedback before
the dry-run exit, while keeping the URL out of output. Add coverage in
test-deploy-dryrun.ps1 for these rejection cases, or explicitly document the
changed dry-run contract if validation is intentionally skipped.

In `@scripts/lib/host-native-launcher.ps1`:
- Around line 573-590: Update scripts/lib/host-native-launcher.ps1 lines 573-590
in Stop-HostNativeProcessTreeAndWait to snapshot descendants before checking
whether the parent has exited, then terminate and verify that snapshot even for
an already-exited parent. Add a regression case in
scripts/tests/test-host-native-launcher.ps1 lines 743-795 that kills only the
parent, injects ChildPidLookup to continue reporting the child, and asserts the
helper either fails closed or removes the child.

In `@scripts/self-referential-bootstrap-ledger.json`:
- Around line 164-181: Add executable definitions for test-deploy-dryrun and
test-deploy-env-fallback, then register both in the immutable command map and
ordered command_ids with equivalent mapped coverage before recomputing
contract_sha256. Define test-stop-all-single-pid and add its command-map entry
only once its executable source exists.

---

Nitpick comments:
In `@scripts/tests/test-deploy-governance-static.ps1`:
- Around line 467-470: Update the assertion around $kitManagerStartIndex to
handle an IndexOf result of -1 separately from the ordering check, matching the
existing guards for the other indices. Report a missing
Start-HostNativeKitManager call when absent, and retain the current post-merge
ordering diagnostic when the call exists but appears too early.

In `@scripts/tests/test-host-native-launcher.ps1`:
- Around line 743-795: Add a test case covering an already-exited parent: start
the tree fixture, terminate only its parent, then invoke
Stop-HostNativeProcessTreeAndWait with injected ChildPidLookup and related test
doubles that still expose the child. Assert the helper processes the reported
descendant rather than returning early, and retain bounded cleanup and failure
assertions consistent with the existing survivor case.

In `@scripts/tests/test-verify-all.ps1`:
- Around line 547-560: Add a positive assertion in the acceptance loop around
Invoke-VerificationExecution to require the expected Kit Manager health-check
marker, such as the health execution line or health failure text. Keep the
existing negative locality and URL-shape assertions, ensuring each
acceptedKitControlUrl case proves execution reached the health-target stage
rather than passing prematurely.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2e706f7e-26de-494f-93b3-067cd5c5bb6a

📥 Commits

Reviewing files that changed from the base of the PR and between 23786f7 and 1099e83.

📒 Files selected for processing (9)
  • docs/evidence/mechanism-hardening-2/self-referential-bootstrap/README.md
  • docs/evidence/mechanism-hardening-2/self-referential-bootstrap/verification.txt
  • scripts/deploy.ps1
  • scripts/lib/host-native-launcher.ps1
  • scripts/self-referential-bootstrap-ledger.json
  • scripts/tests/test-deploy-governance-static.ps1
  • scripts/tests/test-host-native-launcher.ps1
  • scripts/tests/test-verify-all.ps1
  • scripts/verify-all.ps1

Comment thread docs/evidence/mechanism-hardening-2/self-referential-bootstrap/README.md Outdated
Comment thread scripts/deploy.ps1
Comment thread scripts/lib/host-native-launcher.ps1 Outdated
Comment thread scripts/self-referential-bootstrap-ledger.json

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR bundles three post-merge findings from the PR #484 Codex tri-adversarial ship-gate, each touching a classified verification-mechanism path, under a single self-referential bootstrap ledger entry (mechanism-hardening-2) so the fixpoint costs one canonical Linux rebuild instead of three.

Changes:

  • #490 (deploy.ps1): Relocated $resolvedKitControlUrl and $kitManagerRuntimeSignature to after the Phase 2 .env missing-key merge and volume fix, so a run that repairs KIT_CONTROL_URL no longer launches the Kit Manager with the stale pre-merge value or persists a signature that falsely claims it is configured. Verified nothing between the old and new positions reads either variable.
  • #491 (verify-all.ps1): Added Assert-DeploymentKitControlUrlIsLocal, an independent origin-only + loopback/local-interface locality check for the recorded Kit control URL, faithfully re-implementing the launcher's Test-HostNativeLocalAddress/Resolve-HostNativeKitControlUrl rule rather than importing it.
  • #489 (host-native-launcher.ps1): Rewrote Stop-HostNativeProcessTreeAndWait to snapshot the descendant PID set before the kill, guard the Kill([bool]) tree overload behind a probe with an enumerated-PID fallback for PS 5.1/.NET Framework, and fail closed via an identity-based bounded wait on every descendant.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
scripts/deploy.ps1 Moves Kit control URL and Kit Manager signature resolution to after the env merge/volume fix (fix #490).
scripts/verify-all.ps1 Adds and applies the independent Kit control URL locality assertion (fix #491).
scripts/lib/host-native-launcher.ps1 Hardens the process-tree terminator with descendant snapshot, overload-guarded kill, and fail-closed wait (fix #489).
scripts/tests/test-deploy-governance-static.ps1 Static assertions that the resolve/signature/start ordering follows the env merge.
scripts/tests/test-verify-all.ps1 Accept/reject matrix and paired "agreed remote origin" regression for the locality assertion.
scripts/tests/test-host-native-launcher.ps1 Runtime containment regressions: full descendant cleanup and fail-closed on a surviving descendant.
scripts/self-referential-bootstrap-ledger.json New mechanism-hardening-2 open bootstrap ledger entry with verification contract.
docs/evidence/.../README.md Bootstrap scope, limits, and fixpoint obligation note.
docs/evidence/.../verification.txt Recorded local mechanism-suite results and canonical-rebuild deferral.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1099e836bc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/deploy.ps1
Comment thread scripts/lib/host-native-launcher.ps1 Outdated
Comment thread scripts/deploy.ps1
Comment thread scripts/lib/host-native-launcher.ps1 Outdated
Comment thread scripts/tests/test-host-native-launcher.ps1

@codex-tri-adversarial-bot codex-tri-adversarial-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Codex Tri-Adversarial Bot

Automated tri-adversarial ship-gate (L0 terra triage / L1 tier-routed lens fanout / L2 refute-by-default / L3 sol apex — Codex models).
Mapped event: REQUEST_CHANGES


Codex Tri-Adversarial ship-gate — PR #513

  • Repo head: fix/mechanism-hardening-2-bundle @ 1099e83
  • Base: main @ 23786f7
  • Files changed: 9
  • Engine: four-model tri-adversarial gate on Codex — L0 triage gpt-5.6-terra/low; L1 lens finders routed gpt-5.6-terra/low → gpt-5.6-luna/medium → gpt-5.5/xhigh (security floor gpt-5.5); L2 refute-by-default gpt-5.5/xhigh, top-tier findings refuted by gpt-5.6-sol/xhigh (every refutation cross-model); L3 apex gpt-5.6-sol/max. 誠實聲明:層級與 Claude 三層 gate 同構(terra≈haiku、luna≈sonnet、gpt-5.5≈opus、sol≈fable),但模型池是 Codex 的,非 Anthropic 的。

Verdict

NO-SHIP

  • 阻擋門檻 severity: critical, high
  • mapped GitHub event: REQUEST_CHANGES

Difficulty & routing

  • overall: high (source: terra-triage)
  • lens tiers: correctness→gpt-5.5, security→gpt-5.5, simplification→gpt-5.6-luna, test-gap→gpt-5.5

Layer stats

  • L1: raw=11 deduped=11 finder_failures=0
  • L2: confirmed=5 refuted=3 unverified=0
  • L3 final: 4

Findings (final, after apex)

[high] Pre-entry parent exit bypasses descendant containment

  • id: L1-COR-001 lens: correctness file: scripts/lib/host-native-launcher.ps1 line: Stop-HostNativeProcessTreeAndWait
  • provenance: finder=gpt-5.5 refuter=gpt-5.6-sol (cross-model-guard) L2=confirmed
  • evidence: The function returns immediately on if ($Process.HasExited) { return }, before $ChildPidLookup, identity capture, termination, or survivor verification executes.
  • why: The parent can exit between the caller's liveness decision and helper entry while descendants remain alive. The helper then reports success despite its stated trust-boundary containment postcondition, preserving the principal edge case this PR intends to fix.
  • proposed fix: Do not treat an exited parent as successful containment. Use containment established before launch or a trustworthy pre-exit descendant record; otherwise fail closed when descendant termination cannot be proven.

[medium] Fallback termination can kill a recycled descendant PID

  • id: L1-COR-002 lens: correctness file: scripts/lib/host-native-launcher.ps1 line: Stop-HostNativeProcessTreeAndWait
  • provenance: finder=gpt-5.5 refuter=gpt-5.6-sol (cross-model-guard) L2=confirmed
  • evidence: Although $descendantIdentities[$childProcessId] is captured, both fallback loops invoke $StopProcessFn with only $descendantIds[$i]; identity matching occurs only later during survivor polling.
  • why: A snapshotted descendant can exit and its PID can be reused before Stop-Process -Id resolves it. The helper can then terminate an unrelated process and subsequently regard the original descendant as gone. Severity is reduced from high to medium because this requires a narrow PID-reuse race, though the consequence remains destructive.
  • proposed fix: Make termination identity-safe: retain and terminate the same process handle captured for the descendant, or have the stop primitive atomically verify the expected identity before terminating and treat identity mismatch as the original process already gone.

[medium] Fallback containment misses descendants created after its snapshot

  • id: L1-SEC-002 lens: security file: scripts/lib/host-native-launcher.ps1 line: Stop-HostNativeProcessTreeAndWait
  • provenance: finder=gpt-5.5 refuter=gpt-5.6-sol (cross-model-guard) L2=confirmed
  • evidence: $ChildPidLookup builds one fixed $descendantIds snapshot. On runtimes without Kill(bool), both termination and survivor verification operate only on that fixed list and never enumerate again.
  • why: A snapshotted process can create another child after its own lookup and before it is killed. Windows parent termination does not automatically terminate that new child, which is absent from both the stop loop and success check, allowing containment to report success across the stated trust boundary.
  • proposed fix: Prefer an OS containment primitive such as a Windows Job Object established at launch. If enumeration remains as fallback, use a bounded fixed-point containment strategy that prevents or detects concurrent descendant creation and fails closed when quiescence cannot be proven.

[medium] No behavioral test forces the no-Kill(bool) fallback

  • id: L1-TG-003 lens: test-gap file: scripts/tests/test-host-native-launcher.ps1
  • provenance: finder=gpt-5.5 refuter=gpt-5.6-sol (cross-model-guard) L2=confirmed
  • evidence: The dynamic tests derive capability from the current runtime, while the fallback is only checked through source-string/order assertions. The fixture also uses ProcessStartInfo.ArgumentList, preventing it from directly supplying Windows PowerShell 5.1 coverage.
  • why: On PowerShell 7 the tests exercise Kill($true), so incorrect fallback PID stopping, ordering, or parent termination can pass. This is material because Windows PowerShell 5.1 compatibility is an explicit purpose of the change and the fallback contains the two retained races.
  • proposed fix: Inject the tree-kill capability decision and force it false in a behavioral test, or add a PowerShell 5.1-compatible fixture. Assert identity-safe deepest-first descendant handling, parent termination, bounded waiting, and fail-closed survivor behavior.

Killed (did not survive L2/L3)

  • L1-TG-001 [medium] Post-merge KIT_CONTROL_URL behavior is only pinned by source order, not executable behavior — The diff describes a pure ordering relocation; it does not change the env merge, Get-DeployEnvValue, launcher API, or signature construction. The static regression test directly fails on the pre-fix layout and pins the single resolution after the merge, signature construction after resolution, and
  • SIMP-001 [low] Use queue/set primitives for descendant traversal — The micro-optimization is technically true in isolation, but the finding overstates the practical issue and misstates the timeout impact. In the diff, descendant enumeration happens before $budget = [System.Diagnostics.Stopwatch]::StartNew(), so the cited queue bookkeeping does not consume the des
  • SIMP-002 [low] Extract duplicated descendant-stop fallback — The finding identifies a real textual duplicate, but does not survive as a PR-gate issue. The two identical deepest-first loops are in intentionally different control-flow contexts: one is the .NET Framework fallback when Kill(bool) is unavailable, and the other is recovery after a failed tree kil
  • L1-SEC-001 [medium] Process-tree helper still succeeds when parent exited before entry — The early if ($Process.HasExited) { return } bypasses descendant discovery and verification entirely. A parent can exit between a caller’s timeout check and helper entry while independently running descendants survive. The later catch only covers exit after snapshotting begins, and both added dyna

Summary

NO-SHIP: the helper still silently succeeds when the parent exits before entry, leaving its core containment guarantee unproven. The legacy fallback also has bare-PID and post-snapshot-spawn races, and no behavioral test forces that branch. Fix the containment design and add explicit fallback coverage before merge.

Agent calls

  • 14/14 ok, engine wall-clock 773.2s

VERDICT

NO-SHIP

VERDICT: NO-SHIP

monkey1sai and others added 2 commits August 12, 2026 13:04
The PR #513 Codex tri-adversarial ship-gate returned NO-SHIP on four
findings against Stop-HostNativeProcessTreeAndWait, and four PR review
threads named the same defects.

L1-COR-001 (high): `if ($Process.HasExited) { return }` ran before the
descendant snapshot, so a parent that lost the race between the caller's
liveness decision and this helper took the entire sweep with it while its
descendants kept running. Neither OS cascades termination, so an exited
parent now excuses the parent kill/wait only - the snapshot, the
termination and the survivor proof still run.

L1-COR-002: both fallback loops stopped snapshotted descendants by bare
PID. A PID recycled between enumeration and the stop meant terminating an
unrelated host process while the survivor poll still read "our descendant
is gone". Every stop is now identity-revalidated immediately before it
fires, and a changed incarnation is treated as already gone.

L1-SEC-002: one fixed snapshot is not containment - a snapshotted process
can spawn another child before it dies, and that child was in neither the
stop list nor the success check. Containment is now a bounded fixed point
that re-enumerates, terminates and verifies until a pass finds nothing new
and nothing alive, and fails closed at the deadline. Re-enumeration
expands only from roots that are still the incarnation we recorded; the
parent stays a root because this call holds its Process handle.

L1-TG-003: the tree-kill capability decision is injectable, so the .NET
Framework / Windows PowerShell 5.1 fallback is driven as behaviour from a
PowerShell 7 run instead of by source-string order alone.

Six behavioural cases cover it: an already-exited parent with a real
orphaned descendant, the same shape failing closed, an identity-gated stop
on a recycled PID, a forced no-Kill(bool) fallback over a real three-level
chain (deepest-first, parent terminated, every PID proven gone), a
post-snapshot spawn, and the fallback's own fail-closed path.

Two more findings from the same review round:

- `deploy.ps1 -DryRun` stopped adjudicating KIT_CONTROL_URL when the
  authoritative resolution moved after the Phase 2 missing-key merge. That
  merge only appends an absent key with a default and can never repair an
  existing value, so an unusable authority is now a Phase 1 hard fail,
  reported without echoing the URL, with the authoritative post-merge
  resolution left where it is.
- scripts/tests/test-host-native-launcher.ps1 ran in no workflow, so these
  regressions gated nothing. It now runs in the required
  rebuild-test-deploy job, PowerShell 7 only: the dynamic fixtures use
  ProcessStartInfo.ArgumentList, which .NET Framework does not have.

Refs #489.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…reviewed head

The PR #513 review threads found this bundle's evidence unbindable: it
recorded only the baseline commit, so no reader could tie the PASS results
to the code under review, and the PASS lines carried bare command ids with
no invocation or command-map reference.

The record now splits into the two rounds that produced it, pins the
reviewed head commit `110c657` with the clean-worktree result observed at
it, names the immutable command map that resolves the ids, and writes the
resolved invocation inline for the three ids that map does not carry.

That third point also corrects a partial disclosure: the earlier note
covered `test-deploy-dryrun` and `test-deploy-env-fallback` but omitted
`test-stop-all-single-pid`, which is in the same position. All three have
executable sources under scripts/tests/ and pass; none is a
verification-contract command id. Promoting them into the contract would
enlarge this entry's fixpoint obligation, so that decision is left to the
ledger owner rather than taken inside a review-fix round.

Refs #489.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
monkey1sai added a commit that referenced this pull request Aug 12, 2026
ci.yml is a classified verification-mechanism path (design gate
infrastructure, Lane G minimum + self-referential bootstrap scope); wiring
test-measure-session-baseline.ps1 into CI from this measurement-harness PR
would collide with the open mechanism-hardening-2 ledger entry owned by
PR #513. The wiring moves to a follow-up alongside issue #516 (CI coverage
for the streaming pytest suite) after fixpoint closure.

Refs #516

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 26f056dbac

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/lib/host-native-launcher.ps1
Comment thread scripts/lib/host-native-launcher.ps1
Comment thread scripts/self-referential-bootstrap-ledger.json
Comment thread scripts/lib/host-native-launcher.ps1 Outdated
@monkey1sai

Copy link
Copy Markdown
Owner Author

Thread PRRT_kwDOSPoer86Yc2f4(P1:.env.web-plane.host-kit.exampleKIT_CONTROL_URL)—— 有效、保持 unresolved、owner 待辦

查證屬實:KIT_CONTROL_URL 只出現在 7 個檔案,example 樣板不在其中 → missing-key merge 永遠補不出這個 key(重排的另一半理由——merge 可把 resolvedEnvFile 從 .example 改指真實 .env——仍成立,重排本身正確)。

修法需改 .env* 檔,依治理規則 agent 不讀不改不繞道,交 owner:請在 .env.web-plane.host-kit.example 加一行空值佔位 KIT_CONTROL_URL=(空值=誠實 blocked state,新的 Phase 1 驗證接受)。加完後可通知 agent 讓 test-rebuild-test-deploy 的 rebuild 案例改用真實樣板。此 thread 留給 owner 加完後自行 resolve,或投票時以 --allow-unresolved 明示略過。

@codex-tri-adversarial-bot codex-tri-adversarial-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Codex Tri-Adversarial Bot

Automated tri-adversarial ship-gate (L0 terra triage / L1 tier-routed lens fanout / L2 refute-by-default / L3 sol apex — Codex models).
Mapped event: REQUEST_CHANGES


Codex Tri-Adversarial ship-gate — PR #513

  • Repo head: fix/mechanism-hardening-2-bundle @ 26f056d
  • Base: main @ 23786f7
  • Files changed: 12
  • Engine: four-model tri-adversarial gate on Codex — L0 triage gpt-5.6-terra/low; L1 lens finders routed gpt-5.6-terra/low → gpt-5.6-luna/medium → gpt-5.5/xhigh (security floor gpt-5.5); L2 refute-by-default gpt-5.5/xhigh, top-tier findings refuted by gpt-5.6-sol/xhigh (every refutation cross-model); L3 apex gpt-5.6-sol/max. 誠實聲明:層級與 Claude 三層 gate 同構(terra≈haiku、luna≈sonnet、gpt-5.5≈opus、sol≈fable),但模型池是 Codex 的,非 Anthropic 的。

Verdict

NO-SHIP

  • 阻擋門檻 severity: critical, high
  • mapped GitHub event: REQUEST_CHANGES

Difficulty & routing

  • overall: critical (source: terra-triage)
  • lens tiers: correctness→gpt-5.5, security→gpt-5.5, simplification→gpt-5.5, test-gap→gpt-5.5

Layer stats

  • L1: raw=11 deduped=11 finder_failures=0
  • L2: confirmed=4 refuted=4 unverified=0
  • L3 final: 3

Findings (final, after apex)

[high] Linux/POSIX already-exited parent path cannot discover re-parented descendants

  • id: L1-COR-001 lens: correctness file: scripts/lib/host-native-launcher.ps1
  • provenance: finder=gpt-5.5 refuter=gpt-5.6-sol (cross-model-guard) L2=confirmed
  • evidence: The default $ChildPidLookup only calls Get-PlatformChildProcessIds for a supplied parent PID, and both discovery passes seed solely from $parentProcessId. The added exited-parent test instead injects $orphanChildId, explicitly noting that the re-parented child is no longer reachable through the dead parent's PPID link. No production call site or helper contract in the diff supplies such a pre-entry record.
  • why: After a parent exits on Linux/POSIX, its children are re-parented. The default initial and fixed-point lookups can therefore both return empty; because $parentAlreadyExited skips parent termination, the helper observes an empty clean pass and reports success while the orphan remains alive. Windows may retain the recorded creator PID, so the finding is platform-limited, but it still breaks the helper's fail-closed containment contract on a supported path.
  • proposed fix: Capture descendant identities before the parent may exit and pass that snapshot into the helper, or use an OS containment primitive such as a process group/job. If an already-exited parent has no reliable snapshot, fail closed. Add a Linux production-default test without an injected orphan lookup.

[high] Process-tree containment can succeed at timeout without a clean pass

  • id: L1-SEC-001 lens: security file: scripts/lib/host-native-launcher.ps1
  • provenance: finder=gpt-5.5 refuter=gpt-5.6-sol (cross-model-guard) L2=confirmed
  • evidence: The loop first breaks cleanly only when both $survivors.Count and $newDescendantIds.Count are zero, but its next branch breaks merely because the deadline expired. The post-loop failure condition checks only whether $survivors.Count is greater than zero.
  • why: A deadline pass can discover and stop a descendant, leaving zero recorded survivors but a nonzero new-descendant count. The deadline branch then exits without a confirming clean pass, and the post-loop check returns success. A child spawned after that final enumeration remains outside the recorded set, invalidating the containment proof before the trust boundary is released.
  • proposed fix: Record whether a clean pass was observed. Return only after a pass reports both no survivors and no newly discovered descendants; reaching the deadline first must throw even when the current survivor set is empty.

[medium] Timeout budget can be exceeded before descendant containment completes

  • id: L1-COR-002 lens: correctness file: scripts/lib/host-native-launcher.ps1
  • provenance: finder=gpt-5.5 refuter=gpt-5.6-sol (cross-model-guard) L2=confirmed
  • evidence: The initial descendant discovery occurs before $budget starts. After termination work begins, WaitForExit still receives the full $TimeoutMs; if the parent exits near that limit, the helper then performs descendant lookup, stop, and identity probes before checking elapsed time.
  • why: TimeoutMs is described as one bounded cleanup budget, but discovery, termination, the nearly full parent wait, and at least one subsequent containment pass are not constrained by one remaining-time calculation. Slow platform operations can therefore make the helper exceed the advertised bound significantly.
  • proposed fix: Start the deadline before initial discovery, calculate the remaining time before WaitForExit and every containment pass, pass only the remainder to bounded operations, and fail before starting more work once the budget is exhausted.

Killed (did not survive L2/L3)

  • L1-SEC-003 [medium] Kit control URL policy accepts arbitrary local ports and host NICs — The diff supports a configurable local-origin policy, not a fixed-port/loopback-only policy. The verifier intentionally mirrors Resolve-HostNativeKitControlUrl, while KIT_CONTROL_URL is configuration resolved from the environment. Nothing shown establishes port 49101 as mandatory rather than a d
  • L1-SIM-001 [medium] Test-only injection hooks make the process terminator API awkward — The diff does not establish that this helper is a public API or that production callers pass these optional parameters. Existing calls remain unchanged and receive production defaults. Four seams have concrete behavioral purposes: child discovery, PID-identity revalidation, simulated stop behavior,
  • L1-SEC-004 [low] Dry-run preflight logs raw KIT_CONTROL_URL parse errors — The finding is hypothetical, not supported by a current leak path. It shows that deploy.ps1 logs the resolver’s exception, but identifies no reachable resolver exception containing the rejected URL, credentials, or token. The diff states those messages do not echo the URL and adds a dry-run assertio
  • L1-SIM-002 [low] Repeated process-fixture setup in one test file is heavy duplication — The claimed duplication is overstated. Startup mechanics, readiness polling, and timeout behavior are already centralized in Start-TreeFixtureProcess; sandbox cleanup is centralized in the outer finally. The remaining three-line setup keeps each scenario’s distinct name, source, and PID file exp
  • L1-SEC-002 [high] Exited-parent path still cannot find re-parented descendants by default — 最強反證只適用 Windows:ParentProcessId 可在建立者退出後仍保留原 PID,因此 Windows 預設 lookup 可能成功。Microsoft 文件 但此 helper 明顯跨平台,而 Linux 會把 orphan re-parent 至 init/subreaper。Linux 文件 在該路徑上,

Summary

Three unique defects remain in Stop-HostNativeProcessTreeAndWait: POSIX orphan discovery can still return false success, deadline expiry can succeed without a clean fixed-point pass, and TimeoutMs is not an end-to-end budget. The first two undermine the stated fail-closed containment boundary and should block merge; the budget accounting should be corrected in the same helper. L1-SEC-002 was killed only because it duplicates L1-COR-001.

Agent calls

  • 14/14 ok, engine wall-clock 870.4s

VERDICT

NO-SHIP

VERDICT: NO-SHIP

monkey1sai and others added 2 commits August 12, 2026 13:50
…spend one budget

Second Codex tri-adversarial round on PR #513 returned NO-SHIP on three more
findings against Stop-HostNativeProcessTreeAndWait. All three are real; none
was refuted.

L1-COR-001 (high): the exited-parent sweep added in 110c657 is only sound where
the OS keeps the creator PID on an orphan. Windows does - measured here, a
killed parent's PID still resolves its orphaned child and its conhost through
Win32_Process.ParentProcessId, and the PID cannot be recycled while this call
holds the exited process handle. Linux does not: the kernel re-parents orphans
to init or the nearest subreaper, so both discovery passes return empty, and an
empty pass was being read as containment. That platform fact now lives in
Test-OrphanRediscoverySupported alongside the other platform primitives, and it
is the same conclusion the converter containment work reached in #509, which
had to own a job object / process group established at launch rather than trust
a PPID link.

Where rediscovery is unsupported and the parent had already exited on entry,
the helper now fails closed and says so: containment is not provable via PPID
on this platform, and the authoritative boundary is the caller. A new
-KnownDescendantProcessIds parameter is the escape hatch - a descendant record
captured before the parent could exit replaces the link discovery lost, and the
helper then contains and proves that set normally.

L1-SEC-001 (high): the loop broke cleanly only when survivors AND newly
discovered descendants were both zero, but the deadline branch broke on time
alone and the post-loop check only tested survivors. A deadline pass that
discovered a descendant and successfully stopped it therefore left zero
survivors and returned success, with no fixed point ever reached. Success now
requires a recorded clean pass; reaching the deadline without one throws.

L1-COR-002 (medium): TimeoutMs was not one budget. The stopwatch started after
discovery and the parent wait still received the full allowance. It now starts
before discovery, the parent wait receives only the remainder, and no further
containment pass begins on an exhausted budget.

Verified against the previous implementation to confirm these are real, not
theoretical: the churn scenario returned SUCCESS after discovering twelve
descendants, and the slow-discovery scenario spent 2786ms against an advertised
1500ms bound. Both now fail closed and stay inside the budget.

Four new behavioural cases: production defaults against an already-exited
parent asserting whichever branch this platform is on (no injected lookup), the
POSIX fail-closed path driven from a Windows run via the injected capability
gate, the pre-exit record proving containment on that same simulated platform,
and one case each for the clean-pass requirement and the end-to-end budget.

The gated deployment static test's three pinned literals are unchanged; the
parent wait keeps `$Process.WaitForExit($TimeoutMs)` honest by living in a
nested helper whose own TimeoutMs parameter IS the remaining allowance.

Refs #489.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ed basis

Binds the second ship-gate round to its reviewed head d634530 with the
clean-worktree result observed at it, and records what was actually measured
rather than argued:

- Windows orphan rediscovery is SUPPORTED. A killed fixture parent's PID still
  resolved its orphaned python child and its conhost through
  Win32_Process.ParentProcessId, and the production-default sweep contained and
  proved both. That is the platform fact Test-OrphanRediscoverySupported
  encodes, and the reason the POSIX branch has to fail closed instead.
- Both behavioural regressions were reproduced against the previous
  implementation before fixing: the clean-pass scenario returned SUCCESS after
  discovering twelve descendants, and the slow-discovery scenario spent 2786 ms
  against an advertised 1500 ms bound.

The POSIX branch of the platform gate is proven on this host through the
injected capability decision only; no canonical Linux session was opened, so it
has never run on a real re-parenting kernel. That is recorded as an explicit
NOT_RUN rather than folded into the PASS list.

Refs #489.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 834ef5d832

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/lib/host-native-launcher.ps1
Comment thread scripts/verify-all.ps1

@codex-tri-adversarial-bot codex-tri-adversarial-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Codex Tri-Adversarial Bot

Automated tri-adversarial ship-gate (L0 terra triage / L1 tier-routed lens fanout / L2 refute-by-default / L3 sol apex — Codex models).
Mapped event: REQUEST_CHANGES


Codex Tri-Adversarial ship-gate — PR #513

  • Repo head: fix/mechanism-hardening-2-bundle @ 834ef5d
  • Base: main @ 23786f7
  • Files changed: 13
  • Engine: four-model tri-adversarial gate on Codex — L0 triage gpt-5.6-terra/low; L1 lens finders routed gpt-5.6-terra/low → gpt-5.6-luna/medium → gpt-5.5/xhigh (security floor gpt-5.5); L2 refute-by-default gpt-5.5/xhigh, top-tier findings refuted by gpt-5.6-sol/xhigh (every refutation cross-model); L3 apex gpt-5.6-sol/max. 誠實聲明:層級與 Claude 三層 gate 同構(terra≈haiku、luna≈sonnet、gpt-5.5≈opus、sol≈fable),但模型池是 Codex 的,非 Anthropic 的。

Verdict

NO-SHIP

  • 阻擋門檻 severity: critical, high
  • mapped GitHub event: REQUEST_CHANGES

Difficulty & routing

  • overall: critical (source: terra-triage)
  • lens tiers: correctness→gpt-5.5, security→gpt-5.5, simplification→gpt-5.5, test-gap→gpt-5.5

Layer stats

  • L1: raw=12 deduped=12 finder_failures=0
  • L2: confirmed=3 refuted=5 unverified=0
  • L3 final: 3

Findings (final, after apex)

[high] Known descendant escape hatch captures only PIDs, so PID reuse can kill the wrong process

  • id: L1-COR-001 lens: correctness file: scripts/lib/host-native-launcher.ps1 line: ~577
  • provenance: finder=gpt-5.5 refuter=gpt-5.6-sol (cross-model-guard) L2=confirmed
  • evidence: KnownDescendantProcessIds carries only integers. The helper later establishes each seed's reference identity with $descendantIdentities[$seededId] = (& $IdentityProbeFn $seededId), uses that PID as an enumeration root, and may pass it to $StopFn. If the recorded descendant exits and its PID is reused before this first probe, the unrelated process becomes the reference incarnation, passes subsequent identity revalidation, and is terminated. Holding the parent Process handle does not protect descendant PIDs, and the recycled-PID test only covers reuse after an in-function snapshot.
  • why: KEEP at high severity. This escape hatch is explicitly presented as the safe pre-exit record for platforms that re-parent orphans, yet it can terminate an unrelated host process and cause data loss. Although no production caller is shown in this diff, the newly documented contract itself is unsafe and the fail-closed error directs callers toward it.
  • proposed fix: Accept caller-captured descendant identity records containing PID and birth identity, not bare PIDs. Validate the recorded identity before using a seed as an enumeration root and again before stopping it; fail closed when only an unverifiable PID is available.

[high] Fixed-point loop can miss descendants spawned after enumeration but before their parent is stopped

  • id: L1-COR-002 lens: correctness file: scripts/lib/host-native-launcher.ps1 line: ~770
  • provenance: finder=gpt-5.5 refuter=gpt-5.6-sol (cross-model-guard) L2=confirmed
  • evidence: In one pass, Update-DescendantSnapshot can enumerate live descendant D and observe no child. D can then spawn C before Stop-DescendantSnapshot kills D. C is absent from $newDescendantIds, D disappears from $survivors, and the condition $survivors.Count -eq 0 -and $newDescendantIds.Count -eq 0 records a clean pass. No later pass queries D, so C remains outside the containment set. The late-spawn and churn tests do not place the spawn in this enumerate-to-stop window.
  • why: KEEP at high severity. The helper can report its containment postcondition while a descendant remains alive, allowing callers to release the trust boundary prematurely. This is a deterministic check-then-act race, not merely insufficient retry duration.
  • proposed fix: Establish containment at launch with an OS-owned boundary such as a Windows job object or POSIX process group and terminate/query that boundary. If such a boundary is unavailable, do not claim containment; also add an injected regression test that creates a child after D's lookup but immediately before D's stop.

[medium] Orphan rediscovery test uses the implementation as its oracle

  • id: L1-TG-002 lens: test-gap file: scripts/tests/test-host-native-launcher.ps1 line: diff hunk +794
  • provenance: finder=gpt-5.5 refuter=gpt-5.6-sol (cross-model-guard) L2=confirmed
  • evidence: Production obtains the capability decision from Test-OrphanRediscoverySupported, and the test calls the same function to choose its expected branch. If the Windows mapping regresses to false, production throws not provable via PPID, the test selects that failure branch, and cleanup terminates the orphan; the test therefore passes. The diff contains no independent executable assertion of the platform mapping.
  • why: KEEP at medium severity. The integration test exercises both outcome shapes but cannot detect a regression in the policy that selects them, so supported Windows containment could silently become a fail-closed operational failure.
  • proposed fix: Add host-independent assertions that Test-OrphanRediscoverySupported -Platform 'windows' is true and -Platform 'linux' is false. Keep the production-default orphan test separate as an integration check.

Killed (did not survive L2/L3)

  • L1-TG-001 [high] Linux orphan-rediscovery branch is changed but not exercised on a real Linux kernel — The narrow coverage fact is true: no real-Linux execution was recorded. But the finding overstates it as a high-severity gap and misidentifies what the proposed test would cover. The changed Linux behavior is deliberately fail-closed and is behaviorally tested through `OrphanRediscoveryProbeFn { $fa
  • L1-COR-003 [medium] Dry-run validates KIT_CONTROL_URL from the pre-merge env source, not the authoritative post-merge source — The diff proves exact-value/source divergence, but not a divergent validation result. Phase 2 is append-only and never rewrites an existing KIT_CONTROL_URL, so any existing malformed/non-local value rejected by dry-run remains invalid post-merge. The remaining case is a missing key: pre-merge empty
  • L1-SIMP-001 [medium] Process-tree helper is accumulating a large injectable test harness in its public API — The finding depends on an unsupported premise: the diff does not establish that this library helper is a supported public API. The injected parameters are optional and have production defaults, so normal callers still supply only Process, TimeoutMs, and when necessary KnownDescendantProcessIds
  • L1-SIMP-002 [medium] Containment logic is buried in one oversized function with nested helper definitions — The structure is large but cohesive: the nested helpers isolate three focused operations—discovery, identity-gated stopping, and budgeted parent waiting—while keeping implementation-only commands out of the namespace of a dot-sourced PowerShell script. Moving them to top-level functions would enlarg
  • L1-TG-003 [medium] Simulated POSIX no-record case has no live orphan descendant — The claimed gap is not material to the behavior under test. The simulated POSIX no-record path throws before descendant discovery whenever the parent is already exited, no known descendant IDs exist, and orphan rediscovery is unsupported. Therefore, whether an unobservable child actually exists cann

Summary

KEEP all three survivors at their original severities: two high-severity containment defects and one medium test gap. Before merge, replace bare seeded PIDs with caller-captured identities, move containment to an OS-owned launch boundary that closes the enumerate/stop race, and add independent Windows/Linux platform-mapping assertions.

Agent calls

  • 14/14 ok, engine wall-clock 705.6s

VERDICT

NO-SHIP

VERDICT: NO-SHIP

@monkey1sai

Copy link
Copy Markdown
Owner Author

方向裁決記錄(coordinator,依 owner 常設授權):codex tri-gate 三輪 NO-SHIP 的 HIGH findings(escape-hatch PID reuse、enumeration/stop race、上輪的 reparent 縱深)同根同源——PPID-walk 設計撐不起「不可逃脫 containment」的主張。裁決=縮小主張:撤除未被任何 caller 使用的 -KnownDescendantProcessIds、helper 契約明文降級為 bounded best-effort sweep+可證明性誠實回報(Windows 可證明/POSIX fail-closed),「不可逃脫」讓給 launch-time OS 邊界(Job Object/process group at launch,另立 follow-up issue 隨 #517 族追蹤)。第四次 gate 作為本方向的驗收跑;超出三輪上限的理由=方向轉折而非同題研磨。

monkey1sai and others added 4 commits August 12, 2026 14:11
…prove

Three ship-gate rounds all landed HIGH findings on the same thing: the helper
was documented and used as if it delivered inescapable containment, while every
mechanism it has rides the OS parent/child link, which is advisory. Patching the
next escape window would have invited a fourth. This narrows the claim instead.

The contract is now stated in the function itself: a bounded best-effort SWEEP
with a fail-closed provability report. It enumerates what it can reach,
terminates deepest-first with identity revalidation, re-enumerates to a fixed
point, and throws whenever it cannot prove the set it knows about is gone.
It is explicitly NOT an escape-proof boundary - only an OS boundary established
at LAUNCH (Windows Job Object, POSIX process group / cgroup) can be that, which
is #517 and the Start-HostNativeService follow-up. A caller gets "this sweep
proved what it could see, or it threw", never "nothing survived".

Removed -KnownDescendantProcessIds. It was the escape hatch that let the helper
keep claiming provable containment on a re-parenting platform, neither
production caller passed it, and its existence blurred exactly the line this
round is drawing. The POSIX already-exited-parent path stays a fail-closed
throw, and the message now states the narrowed contract and names the launch-
time boundary and #517 rather than offering a parameter as the answer.

The gate's remaining HIGH - a descendant spawned between enumeration and the
stop that follows it - is REFUTED by measurement, not argument. A real
three-level fixture whose grandchild is hidden from the snapshot (running the
whole time, so it stands in for one spawned a moment after enumeration), with
the tree-kill capability forced off so .NET cannot do the containment for us:
the helper stopped the snapshot, killed the parent last, and pass 1 re-walked
every snapshot member it had just killed, rediscovered the grandchild through
its dead parent's link, stopped it, and pass 2 came back clean. All three PIDs
gone, no throw. That is now a regression test. The lookup sequence it asserts on
is the mechanism: [P, D, P, D, conhost, G, P].

The residual that survives that refutation is documented rather than papered
over, because closing it would make things worse: a descendant discovered AND
stopped inside one pass drops out of the expansion roots, so a child it spawned
in that sub-window is not rediscovered. Expanding from dead PIDs every pass
would trade this fail-open gap for a fail-dangerous one - a recycled PID would
contribute an unrelated process's children to the kill set.

Also: the orphan-rediscovery test no longer asks Test-OrphanRediscoverySupported
which branch to expect, which was the implementation grading its own homework.
It reads the raw OS record instead - Win32_Process.ParentProcessId on Windows,
/proc/<pid>/stat field 4 on Linux - and asserts the helper agrees with it.

The gated deployment static test's three pinned literals are unchanged.

Refs #489, #517.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…l it leaves

Binds the narrowed-claim round to its reviewed head 3044e78 with the clean
worktree observed at it, and keeps the three kinds of statement apart instead of
flattening them into one PASS list:

- MEASURED: a descendant hidden from the snapshot but running throughout was
  rediscovered, stopped and proven gone by the re-enumerating fixed point, with
  the tree kill forced off so .NET could not do the work. That refutes the gate's
  remaining HIGH and is now a regression case.
- ANALYSIS-NOT-MEASURED: the sub-window that survives it - a descendant
  discovered and stopped inside one pass leaves the expansion roots, so a child
  it spawned in that window is not rediscovered. Left open deliberately, because
  expanding from dead PIDs would trade a fail-open gap for a fail-dangerous one.
- CONTRACT: the helper is a bounded best-effort sweep with a fail-closed
  provability report, not an escape-proof boundary, and -KnownDescendantProcessIds
  is gone.

The POSIX leg of the platform gate is still NOT_RUN on a real re-parenting
kernel; it remains proven only through the injected capability decision.

Refs #489, #517.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…sai/AI-BIM-governance into worktree-agent-ae9e47109793a96a9

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6454db96ca

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/self-referential-bootstrap-ledger.json
Comment thread scripts/tests/test-host-native-launcher.ps1
Comment thread scripts/verification-manifest.json

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5ad1058726

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/lib/host-native-launcher.ps1
Comment thread scripts/lib/host-native-launcher.ps1

@codex-tri-adversarial-bot codex-tri-adversarial-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Codex Tri-Adversarial Bot

Automated tri-adversarial ship-gate (L0 terra triage / L1 tier-routed lens fanout / L2 refute-by-default / L3 sol apex — Codex models).
Mapped event: COMMENT


Codex Tri-Adversarial ship-gate — PR #513

  • Repo head: fix/mechanism-hardening-2-bundle @ 5ad1058
  • Base: main @ 4187102
  • Files changed: 13
  • Engine: four-model tri-adversarial gate on Codex — L0 triage gpt-5.6-terra/low; L1 lens finders routed gpt-5.6-terra/low → gpt-5.6-luna/medium → gpt-5.5/xhigh (security floor gpt-5.5); L2 refute-by-default gpt-5.5/xhigh, top-tier findings refuted by gpt-5.6-sol/xhigh (every refutation cross-model); L3 apex gpt-5.6-sol/max. 誠實聲明:層級與 Claude 三層 gate 同構(terra≈haiku、luna≈sonnet、gpt-5.5≈opus、sol≈fable),但模型池是 Codex 的,非 Anthropic 的。

Verdict

SHIP

  • 阻擋門檻 severity: critical, high
  • mapped GitHub event: COMMENT
  • ℹ️ 判定為 SHIP,但刻意不送 APPROVE:GitHub App 的 approving review 不計入 required_approving_review_count(2026-07-31 實測)。本報告是證據,approving 那一票請由真人帳號投。

Difficulty & routing

  • overall: critical (source: terra-triage)
  • lens tiers: correctness→gpt-5.5, security→gpt-5.5, simplification→gpt-5.5, test-gap→gpt-5.5

Layer stats

  • L1: raw=7 deduped=7 finder_failures=0
  • L2: confirmed=3 refuted=4 unverified=0
  • L3 final: 3

Findings (final, after apex)

[medium] Windows PowerShell 5.1 fallback is still not exercised on the real runtime

  • id: L1-TG-001 lens: test-gap file: .github/workflows/ci.yml
  • provenance: finder=gpt-5.5 refuter=gpt-5.6-sol (cross-model-guard) L2=confirmed
  • evidence: KEEP. The new launcher gate runs only with pwsh, and its comment explicitly says the dynamic fixtures cannot run on Windows PowerShell 5.1 because ProcessStartInfo.ArgumentList is unavailable. Injecting TreeKillCapabilityProbeFn { $false } exercises fallback control flow under PowerShell 7, but no shown test invokes the helper under .NET Framework.
  • why: Loading deploy.ps1 through powershell.exe can catch parsing failures, but dry-run exits before process-tree cleanup. Runtime-specific reflection, binding, process, and cmdlet behavior in the compatibility path therefore remains ungated.
  • proposed fix: Add a focused Windows PowerShell 5.1-compatible fallback test, or split the fixtures so powershell.exe invokes the real capability probe and fallback cleanup path.

[medium] POSIX orphan gate is only injected, not tested on Linux

  • id: L1-TG-002 lens: test-gap file: docs/evidence/mechanism-hardening-2/self-referential-bootstrap/verification.txt
  • provenance: finder=gpt-5.5 refuter=gpt-5.6-sol (cross-model-guard) L2=confirmed
  • evidence: KEEP. The evidence explicitly records the real Linux platform-gate leg as NOT_RUN; the POSIX branch is exercised only by injecting OrphanRediscoveryProbeFn { $false }. The workflow change adds the launcher suite only to the Windows rebuild-test-deploy job, leaving the production /proc and PPID path ungated on Linux.
  • why: The injected test verifies branch logic but cannot validate Get-PlatformName, raw /proc behavior, process identity integration, or the production default probe on a re-parenting kernel. This is material because the helper intentionally changes behavior for an already-exited parent on Linux.
  • proposed fix: Run test-host-native-launcher.ps1 on a Linux CI runner and retain the production-default already-exited-parent case without an injected orphan capability result.

[low] Runtime helper carries a long PR-history narrative instead of a compact contract

  • id: L1-SIM-002 lens: simplification file: scripts/lib/host-native-launcher.ps1
  • provenance: finder=gpt-5.5 refuter=gpt-5.6-sol (cross-model-guard) L2=confirmed
  • evidence: KEEP. The helper comment contains eight numbered historical defects, review-round and issue references, measurement narrative, and a residual-analysis section in addition to its durable behavioral contract. Much of that chronology is already preserved in the accompanying evidence documents.
  • why: The contract, invariants, platform limitation, and residual risk merit proximity to this safety-sensitive code, but the review history makes the implementation harder to scan and creates duplicate documentation that can drift.
  • proposed fix: Keep a concise contract, core invariants, platform caveat, residual limitation, and documentation link beside the function; move the round-by-round defect history and measurements to the evidence or design note.

Killed (did not survive L2/L3)

  • L1-TG-003 [high] Documented residual escape window has no adversarial test or gating follow-up — Finding 過度陳述。精確 residual 的 adversarial fixture 確實不存在,但它已被明確排除在 helper 契約之外:程式稱其為 bounded best-effort sweep、禁止以 silent return 宣稱「nothing survived」,並明言 trust boundary 必須由 launch-time Job Object/process group/cgroup 提供。後續 #517 不只被標註為 residual owner,CI 納管的測試還斷言錯誤訊息必須包含 narrowed contract、`established at
  • L1-SIM-001 [medium] Safety-critical helper exposes a test-harness API surface — The diff proves test seams exist, but not that this is a public or externally reachable API. This is a repo-local PowerShell helper; no module export, untrusted parameter binding, or production caller supplying these delegates is shown. All knobs have safe production defaults, while the injected imp
  • L1-SEC-001 [low] No security findings from the provided diff — The full diff itself supports a security finding outside the URL guard. The final Stop-HostNativeProcessTreeAndWait implementation explicitly documents a KNOWN RESIDUAL: a descendant discovered and stopped during one pass can spawn a child in that interval; because the stopped descendant drops o
  • L1-SIM-003 [low] Evidence documents duplicate the same multi-round status in two files — The files serve distinct roles: README is a short human-readable scope, rationale, and round summary; verification.txt is the detailed per-round audit record with exact heads, scopes, PASS/NOT_RUN entries, measurements, and limits. Repeating reviewed-head bindings and high-level conclusions is neces

Summary

All three survivors remain at their original severities: two medium test gaps and one low-priority simplification. Add real Windows PowerShell 5.1 and Linux launcher legs to close the material gaps; shorten the helper’s historical commentary opportunistically. No critical or high-severity survivor remains.

Agent calls

  • 13/13 ok, engine wall-clock 523.6s

VERDICT

SHIP

VERDICT: SHIP

@monkey1sai
monkey1sai dismissed codex-tri-adversarial-bot[bot]’s stale review August 12, 2026 06:39

Superseded: the round-2 NO-SHIP findings (escape-hatch PID reuse, clean-pass gap, budget accounting) were fixed in d634530/3044e78 and the fourth gate run at head 5ad1058 returned SHIP (review 4913480756 → COMMENT posted with the SHIP report; remaining findings are documented medium/low limits in the evidence). Dismissed by coordinator per owner standing authorization.

@monkey1sai-blip monkey1sai-blip left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved by monkey1sai-blip (the reviewer account pinned by the repo's merge governance).

Submitted through scripts/blip_review.py — a scripted approval carrying the operator's authority, pinned to head 5ad10587263f2e8fdf4a35f823322949aa0bb539. This is the mechanism the GitHub App cannot satisfy: an App's approving review does not count toward required_approving_review_count.

monkey1sai and others added 3 commits August 12, 2026 14:47
…ening-2 entry

Round-3 added Test-OrphanRediscoverySupported to
scripts/lib/platform/platform-adapter.ps1, which is a classified
verification-mechanism path; the bundle's ledger entry must declare every
mechanism path its diff touches. test-self-referential-bootstrap all green.

Refs #489

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 10ae377c63

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/lib/host-native-launcher.ps1 Outdated
Comment thread scripts/deploy.ps1
@monkey1sai
monkey1sai merged commit daf551e into main Aug 12, 2026
55 of 60 checks passed
@monkey1sai
monkey1sai deleted the fix/mechanism-hardening-2-bundle branch August 12, 2026 10:59
monkey1sai added a commit that referenced this pull request Aug 12, 2026
…baseline 1.1) (#511)

* feat(scripts): add GPU session baseline measurement harness (gpu-session-baseline-and-idle-reclaim 1.1)

Add scripts/measure-session-baseline.ps1 (root CLI) and
scripts/lib/measure-session-baseline.ps1 (testable core) implementing task
1.1 of openspec/changes/gpu-session-baseline-and-idle-reclaim: a read-only
harness that captures nvidia-smi GPU inventory (VRAM/utilization, consumer
RTX classification, MIG availability), a GET-only WebRTC/coordinator health
probe (/health, /api/runtime/status), and the environment fingerprint
required by the gpu-session-baseline spec (GPU model, driver version, Kit
version from kit-sdk.packman.xml, fixture hash+size).

The harness never opens a WebRTC session or creates/joins/closes a review
session, so TTFF and session-creation success rate cannot be honestly
measured locally; those fields are null with measured:false and an explicit
reason unless supplied by a caller (e.g. a future task 1.3 soak run), never
fabricated. Every other unmeasurable signal (no nvidia-smi, no GPU rows,
insufficient OS permission on the compute-apps VRAM column, coordinator
unreachable) degrades the same way instead of throwing or guessing.

Registered in scripts/script-registry.json as a measurement-harness (not
deploy.ps1/verify-all.ps1: it measures, it does not deploy or gate; not
scripts/lib alone: it is the operator-invoked CLI entry; not scripts/tests:
it produces a JSON report, not a pass/fail check).

Add scripts/tests/test-measure-session-baseline.ps1: unit tests for GPU line
parsing/consumer-RTX/MIG classification, fail-safe behavior with nvidia-smi
entirely absent, report schema shape, script-registry.json consistency, and
a real CLI smoke test (both -OutputPath and the default
artifacts/gpu-baseline/<timestamp>.json path). Verified on pwsh 7.5.4 and
Windows PowerShell 5.1 (powershell.exe), invoke-powershell-static.ps1, and
scripts/tests/test-agent-governance-check.ps1 (45/45 green).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(openspec): tick gpu-session-baseline-and-idle-reclaim task 1.1

Mark tasks.md 1.1 done (measure-session-baseline.ps1 harness landed) and
sync openspec/lifecycle-ledger.json: task_ledger completed 0->1,
current_slice points at the 1.2 env-fingerprint gate as the next slice,
last_verified refreshed, subject_commit rebound to 405e2b6 (the commit that
landed the harness + tests + registry entry), evidence_refs extended to the
new script and test paths.

Verified: node scripts/tests/verify-openspec-repository-lifecycle.mjs
--repo-root . (openspec/changes, lifecycle-ledger.json and
docs/plans/NOW.md agree -- NOW.md's projection is id+status only, and
status stays "active", so it needed no edit); node --test
scripts/tests/test-openspec-machine-truth.mjs (24/24) and
scripts/tests/test-ai-coding-metrics.mjs (13/13); pwsh
scripts/tests/test-agent-governance-check.ps1 (45/45 embedded
repository-lifecycle subtests green).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(scripts): honest gpu-baseline measurements — real binding enum, per-role lease counts, validated inputs, untick 1.1 (review)

* fix(scripts): declare gpu fingerprint scope — multi-GPU host is first_gpu_only, per-GPU fingerprint deferred to 1.2 (review)

* fix(scripts): harden GPU baseline harness per PR #511 review

Addresses the valid findings from the 13 unresolved review threads on
scripts/measure-session-baseline.ps1 (gpu-session-baseline-and-idle-reclaim
task 1.1/1.2), keeping the "measured:false, never fabricate" contract intact:

- Get-SafeProperty: fix a PowerShell pipeline-unroll bug where `return
  $value` on an empty array collapsed to $null, making an observed empty
  kit_instance_bindings/viewer_leases indistinguishable from "unmeasured".
- Get-WebRtcHealthProbe: count non-terminal KitInstanceBinding statuses
  (allocated/starting/ready/draining) instead of a literal status='active'
  that the real coordinator API never emits; count active primary/spectator
  viewer_leases by role (the actual 1-primary-plus-k-spectator cardinality)
  instead of sessions.active_count; clarify that `reachable` reflects only
  coordinator /health liveness, not independent WebRTC/signaling reachability.
- Get-SessionVramWatermark: only claim a clean measured total when exactly
  one Kit GPU process is observed and fully readable; multi-process or
  partially-readable readouts are surfaced only as the informational
  unscoped_total_kit_vram_mb, never as a fabricated measured:true total.
- Get-EnvironmentFingerprint: fail closed (measured:false) on a multi-GPU
  host instead of blindly binding the fingerprint to gpus[0].
- Get-KitVersionFingerprint: carry an explicit source/caveat noting this is
  the checkout's declared dependency version, not a live-process read.
- Get-SessionBaselineReport: range-validate caller-supplied -TtffMs /
  -SessionCreationSuccessRate (reject negative/out-of-range instead of
  recording as measured); resolve host.hostname via the cross-platform Dns
  API with HOSTNAME/COMPUTERNAME fallback so Linux deployment targets don't
  silently null out host identity.
- Root wrapper: derive the default -OutputPath from the report's own
  collision-resistant run_id instead of a bare second-resolution timestamp.
- CI: run test-measure-session-baseline.ps1 (PS7 + Windows PowerShell 5.1)
  as part of the required `powershell-static` job, mirroring the existing
  test-spec-to-done-port-helper.ps1 pattern -- neither `root-contracts`
  (pytest) nor the PSScriptAnalyzer-only `powershell-static` gate command
  previously executed this suite.

The lifecycle-ledger subject-ancestry finding (PRRT_kwDOSPoer86YcZ4d) was
independently verified as already resolved at current HEAD and needed no
change; see PR reply for evidence.

Verified: pwsh + Windows PowerShell 5.1 test-measure-session-baseline.ps1,
invoke-powershell-static.ps1, and node --test test-openspec-machine-truth.mjs
(24/24) all green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(scripts): carry a live-build staleness caveat on kit_version (PR #511 review)

Get-KitVersionFingerprint reads bim-streaming-server/tools/deps/kit-sdk.packman.xml
-- the checkout's DECLARED kit-kernel dependency version -- not a value read
from the live Kit process. If the checkout is updated without a
rebuild/restart, this can be stale relative to the session actually being
measured, and no local mechanism exists to introspect a running Kit.exe's
build identity to close that gap. Surface a `source` ('checkout_packman_declared')
and an explicit `caveat` string alongside the existing value/measured/reason
shape (both on the raw fingerprint and propagated through
Get-EnvironmentFingerprint's kit_version field) so downstream SLO-writers
know what this field does and does not attest to, rather than silently
trusting checkout state as if it were live-process state.

This was the one review thread not already covered by the concurrent fixes
landed in 37e3247/2eee19b on this branch (real KitInstanceBinding status
enum, per-role viewer lease counts, VRAM attribution transparency,
TTFF/success-rate validation, hostname fallback, GPU fingerprint scope
disclosure, collision-resistant default filename, task 1.1 unticked); this
commit reconciles with that work rather than duplicating it.

Verified: pwsh + Windows PowerShell 5.1 test-measure-session-baseline.ps1,
invoke-powershell-static.ps1, and node --test test-openspec-machine-truth.mjs
(24/24) all green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(scripts): fold GPU-attribution gap into complete, fix MIG-gating and test cleanup (PR #511 review round 2)

Three round-2 findings on the GPU baseline harness:

- Get-EnvironmentFingerprint: gpu_fingerprint_scope='first_gpu_only' (a
  multi-GPU host) was disclosure-only -- `complete` was computed from the
  five base fields before the scope was known, so a report that has
  admittedly NOT attributed every relevant GPU could still report
  complete:true and silently suppress the wrapper's "SHALL NOT be used to
  set SLOs or admission parameters" warning. `complete` now also requires
  gpu_fingerprint_scope != 'first_gpu_only'.
- Get-GpuInventorySnapshot: software_queue_required was gated on
  consumer_grade_all AND NOT mig_available_any. On a non-consumer, non-MIG
  fleet (e.g. a lone RTX A6000, which Test-ConsumerRtxGpuName excludes but
  which does not support MIG at all), that reported
  software_queue_required=false with no MIG route in fact available.
  Software queuing is now required whenever MIG is unavailable, regardless
  of consumer/professional classification.
- test-measure-session-baseline.ps1: the default-OutputPath cleanup deleted
  every new file under artifacts/gpu-baseline/, not just the one this test
  produced -- a concurrent harness invocation sharing the checkout would
  have its evidence collaterally deleted. Now deletes only
  "$($defaultReport.run_id).json".

Also strengthened Assert-ReportSchemaShape's `complete` expectation and
added regression tests for the professional/no-MIG inventory shape and the
multi-GPU complete=false path.

Verified: pwsh + Windows PowerShell 5.1 test-measure-session-baseline.ps1,
invoke-powershell-static.ps1, and node --test test-openspec-machine-truth.mjs
(24/24) all green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* revert(ci): defer harness CI wiring until the open mechanism debt closes

ci.yml is a classified verification-mechanism path (design gate
infrastructure, Lane G minimum + self-referential bootstrap scope); wiring
test-measure-session-baseline.ps1 into CI from this measurement-harness PR
would collide with the open mechanism-hardening-2 ledger entry owned by
PR #513. The wiring moves to a follow-up alongside issue #516 (CI coverage
for the streaming pytest suite) after fixpoint closure.

Refs #516

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(scripts): gpu-baseline r2 - bootstrap registration, honest kit-version provenance, MIG-driven queue flag (review r2)

* fix(scripts): honest fixture provenance binding for baseline fingerprint (review r4, operator-delegated adjudication)

* fix(governance): revert harness bootstrap-layer per #520 ruling; rebind hifi row to #507 squash

一、撤除 bootstrap 層(依 #520 裁決=docs/agents/self-referential-bootstrap.md §2.1,PR #521):
量測 harness 的報告無任何 gate 機器消費者,不屬 mechanism surface,不入 ledger。
classifier 擴張+open entry gpu-session-baseline-harness+evidence 一併撤除,
scripts/lib/self-referential-bootstrap.ps1、scripts/tests/test-self-referential-bootstrap.ps1、
scripts/self-referential-bootstrap-ledger.json 還原為 origin/main 版本。
機械上這條路也是死路:base-pinned 裁決者以 base 版 classifier 驗證新 entry 宣告的
mechanism paths,同 PR 擴張 classifier 永遠無法讓自己的 entry 合法(實測兩輪
pr-metadata-contract-diagnostic 均以 not classified verification-mechanism paths 拒絕)。

二、rebind migrate-console-to-hifi-design row:#507 squash 後該 row 仍綁 pre-squash
commit af60c29(已被丟棄,CI checkout 抓不到)→ 全部後續 PR 的 machine-truth
test 25 紅。依 #482/#501/#512 慣例 rebind 到 landed squash 4187102。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(scripts): gpu-baseline r5 — unknown-runtime honesty, session-scoped lease counts, fixture overwrite guard (review r5)

PR #511 review r5, three of four threads:

1. PRRT_kwDOSPoer86YeUls — an unreachable/malformed /api/runtime/status left
   every observed count null, and the fixture-binding defaults coerced those
   nulls to 0, so an UNKNOWN runtime state was published under the
   'no_live_session_observed' (observed-idle) label with complete=true beside
   a declared fixture. Adds a distinct fixture_binding_scope='runtime_state_unknown'
   that withdraws completeness and names the failed probe (GET /api/runtime/status).
   A positive observation still outranks the unknown; an observed 0/0 idle host
   keeps its previous semantics.

2. PRRT_kwDOSPoer86YeUlw — per-role lease counts are summed across every
   sessions.items[] entry while total_kit_vram_mb is one host-wide sample, so a
   host serving 2+ sessions mixed multiple primaries/spectators against a single
   VRAM number. Takes the reviewer's reject option: the aggregate counts are kept
   (they are real observations) but session_scope='multi_session_aggregate' is
   published and the 1-primary+k-spectator watermark interpretation is marked
   measured=false with reason 'non-isolated multi-session snapshot; per-session
   VRAM attribution unavailable in this slice'. Exactly one active session yields
   session_scope='single_session' and keeps current semantics.

3. PRRT_kwDOSPoer86YeUly — -FixturePath and -OutputPath resolving to the same
   file made Set-Content truncate the fixture with the report, destroying the very
   artifact the report fingerprints. Canonicalises both ([System.IO.Path]::GetFullPath,
   case-insensitive only on Windows) and throws before any write.

PRRT_kwDOSPoer86YeUlo (P1, bootstrap mechanism-path regression) is NOT addressed
here and is moot as of 286bbac on this branch: per the #520 ruling the harness is
not a mechanism surface, and the three measure-session-baseline classifier patterns
the thread asked the test to pin were removed. Adding them to $expectedMechanismPaths
now would fail the suite; re-registering them would revert an owner ruling.

Verified on Windows: test-measure-session-baseline.ps1 (all groups pass),
test-self-referential-bootstrap.ps1 (all assertions pass),
Invoke-ScriptAnalyzer -Severity Error on the changed .ps1 files = 0.

* fix(scripts): gpu-baseline r6 — reject malformed runtime counts, require observed primary, finite TTFF (review r6)

- Get-SessionVramWatermark / Get-EnvironmentFingerprint: a non-null-but-
  unparseable observed_active_session_count / observed_kit_instance_binding_count
  (coordinator version skew, e.g. a string) was silently coerced to 0 via a
  try/catch default, relabeling an UNKNOWN runtime state as an OBSERVED zero.
  New ConvertTo-NonNegativeIntOrNull helper returns null instead of 0 on parse
  failure; both call sites now treat that null the same as a missing probe
  (new 'malformed_runtime_observation' session scope; runtime_state_unknown
  fixture-binding scope).
- Get-SessionVramWatermark: exactly one active session was enough to accept
  the "1 primary + k spectator" watermark interpretation even when zero
  primary viewers had joined (idle-but-created or spectator-only session).
  Now requires observed_primary_lease_count == 1.
- New-OptionalMeasurement TTFF validator only checked ">= 0", which
  +Infinity satisfies; now also rejects non-finite values.
- openspec/lifecycle-ledger.json: added scripts/lib/measure-session-baseline.ps1
  to the change's evidence_refs (the entire measurement implementation lives
  there; only the CLI wrapper and test were previously listed).

Addresses the three still-open findings from the chatgpt-codex-connector
review on c759057, plus the infinite-TTFF gap from an earlier round that
was never landed.

Co-authored-by: monkey1sai <26239865+monkey1sai@users.noreply.github.com>

* fix(scripts): gpu-baseline r7 — keep kit process-count fields in every report shape (review r7)

gpu-session-baseline-report/v1 的兩個早退路徑補齊 kit_process_count 與
kit_process_vram_unreadable_count:查詢失敗=null(未知非零)、查詢成功但無
Kit process=0(觀測到的真零),consumer 不再因 host 狀態拿到不同 shape。
測試補四條斷言鎖住兩態。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: monkey1sai <xshiujj@gmail.com>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
monkey1sai added a commit that referenced this pull request Aug 12, 2026
…nt (#529)

* fix(governance): close the mechanism-hardening-2 debt with its fixpoint

All 15 verification-contract commands were rerun with the post-merge
mechanism on main (daf551e, the #513 squash):

- commands 1-13 locally, in exact contract order, single uninterrupted pass,
  every process exit 0 (evidence table with per-command timestamps)
- command 14 canonical-linux-rebuild in pinned form from a fresh origin/main
  isolated worktree (no -IdentityFile, no -TargetId): deploy exit 0, tag
  deploy-20260812-639221315101291265-002 -> daf551e pushed
- command 15 canonical-linux-deployment-verify in pinned form against that
  new deployment: six checks passed, none failed, exit 0

Ledger entry status open -> closed with fixpoint reverified_at
2026-08-12T11:40:00Z and mechanism_commit daf551e. Gates:
test-self-referential-bootstrap and test-agent-governance-check all green.

Refs #489 #490 #491

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(governance): add the fixpoint attestation.json for mechanism-hardening-2

The evidence gate requires docs/evidence/<slug>/fixpoint/attestation.json
alongside the summary; added in the same schema as the
linux-test-deploy-verifier-hardening precedent (all 15 contract command ids
with exit_code 0, contract sha256 preserved, result pass) and linked from
the ledger entry's fixpoint evidence_refs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: monkey1sai-blip <monkey1sai@icloud.com>

* docs(evidence): resolve the stale reverified_at limit line

Gate finding L1-correctness-1: verification.txt still carried the
draft-era LIMIT saying the ledger timestamp was unset, contradicting its
own completion fields, the summary, and the closed ledger entry. Replaced
with an explicitly historical RESOLVED note.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Signed-off-by: monkey1sai-blip <monkey1sai@icloud.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: monkey1sai-blip <monkey1sai@icloud.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants