Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
1bb7a5e
fix(deploy): resolve Kit control URL after the .env missing-key merge
monkey1sai Aug 12, 2026
5839760
fix(verify): assert Kit control URL locality in the Deployment profile
monkey1sai Aug 12, 2026
1099e83
fix(launcher): contain descendants in Stop-HostNativeProcessTreeAndWait
monkey1sai Aug 12, 2026
110c657
fix(launcher): prove containment for exited parents and legacy fallbacks
monkey1sai Aug 12, 2026
26f056d
docs(evidence): bind mechanism-hardening-2 bootstrap evidence to its …
monkey1sai Aug 12, 2026
d634530
fix(launcher): gate orphan sweeps by platform, require a clean pass, …
monkey1sai Aug 12, 2026
834ef5d
docs(evidence): record the round 3 containment fixes and their measur…
monkey1sai Aug 12, 2026
6454db9
Merge branch 'main' into fix/mechanism-hardening-2-bundle
monkey1sai Aug 12, 2026
3044e78
fix(launcher): narrow the process-tree helper's claim to what it can …
monkey1sai Aug 12, 2026
8fd3ca2
docs(evidence): record round 4, the HIGH-2 refutation and the residua…
monkey1sai Aug 12, 2026
5ad1058
Merge branch 'fix/mechanism-hardening-2-bundle' of github.com:monkey1…
monkey1sai Aug 12, 2026
f5078d9
fix(env): 補上 Kit 控制網址樣板佔位
monkey1sai Aug 12, 2026
8aee337
chore(governance): declare platform-adapter.ps1 in the mechanism-hard…
monkey1sai Aug 12, 2026
1958045
Merge branch 'main' into fix/mechanism-hardening-2-bundle
monkey1sai-blip Aug 12, 2026
10ae377
Merge branch 'main' into fix/mechanism-hardening-2-bundle
monkey1sai Aug 12, 2026
e4cd51d
fix(deploy): 保留明示環境檔並封閉子程序列舉失敗
monkey1sai Aug 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.web-plane.host-kit.example
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ HOST_CONVERSION_API_BASE=http://host.docker.internal:49101
KIT_SIGNALING_PORT=49100
# KIT_MEDIA_HOST=192.168.10.105
KIT_MEDIA_PORT=47998
KIT_CONTROL_URL=

# Same-Kit spectator streams. Default gives 5 spectator viewer slots in addition
# to the primary stream. Set KIT_SPECTATOR_COUNT=4 if the desired total is 5 viewers.
Expand Down
9 changes: 9 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,15 @@ jobs:
shell: pwsh
run: pwsh -NoProfile -NonInteractive -ExecutionPolicy Bypass -File scripts/tests/test-verify-all.ps1

# scripts/lib/host-native-launcher.ps1 is classified into this job, but no
# workflow ever ran its suite: the process-tree containment regressions
# were green only in manually recorded evidence, so a broken terminator
# could merge. PowerShell 7 only - the dynamic fixtures use
# ProcessStartInfo.ArgumentList, which .NET Framework does not have.
- name: Run host-native launcher contract tests (PowerShell 7)
shell: pwsh
run: pwsh -NoProfile -NonInteractive -ExecutionPolicy Bypass -File scripts/tests/test-host-native-launcher.ps1

secret-pattern-scan:
name: secret pattern scan
needs: changes
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
> Document nature: **working note**. This file is bootstrap evidence, not an authoritative runtime, API, or deployment specification.

# Mechanism hardening 2 bootstrap

- `stack_kind=self_referential_bootstrap`
- Pull request: see the ledger entry `mechanism-hardening-2` (`pr` field is the binding record)
- Baseline: freshly fetched `origin/main` at `472192386f8402cf19a29005daf25556d26f222c`
- Reviewed head: `110c657fd620e3bdbac4379ac716da99d37848b9` (round 2), `d63453024f59b13714ed222ea14bdc34a2890253` (round 3) and `3044e788ae2a741ea1f877f3353874cc31d606ad` (round 4), worktree clean at each — `git status --porcelain` produced no output at any of them
- This is isolated branch bootstrap evidence. It is not canonical post-change evidence and does not claim full-system E2E completion.

## Scope

Three post-merge findings from the PR #484 Codex tri-adversarial ship-gate, landed together because each one edits a classified verification-mechanism path:

| Issue | Finding | Mechanism path |
|---|---|---|
| #490 | L1-COR-001 — Kit control URL fixed before the `.env` missing-key merge | `scripts/deploy.ps1` |
| #491 | SEC-004 — Deployment profile never applied locality to the Kit control URL | `scripts/verify-all.ps1` |
| #489 | L1-COR-004 — process-tree terminator proved only the parent exited | `scripts/lib/host-native-launcher.ps1` |
Comment thread
monkey1sai-blip marked this conversation as resolved.

They share one ledger entry deliberately. The debt gate admits one open entry at a time, and every entry owes a full canonical Linux rebuild plus deployment verification to close. Splitting these three into separate pull requests would serialise three rebuilds for one coherent hardening round.

## Why this branch cannot produce canonical post-change evidence

The canonical deployment transport rebuilds the Linux test target only from freshly fetched `origin/main` and refuses an unmerged revision. All three changes live inside that transport: the deploy entrypoint that resolves runtime identity, the aggregate verifier that adjudicates the deployed runtime, and the shared launcher primitive both rely on to prove a terminated process tree is gone. A pre-merge run against `origin/main` therefore exercises the unchanged mechanism, and the changed mechanism has no mainline to run on until this merges.

## What this branch did verify

Local mechanism suites on the branch head, on Windows with PowerShell 7.5.4. The recorded results are in `verification.txt`, split into the two rounds that produced them: the initial bundle at the baseline, and the PR #513 review round at the reviewed head above. Each `PASS` line names either a command id that resolves through the immutable command map in `scripts/tests/test-self-referential-bootstrap.ps1`, or its resolved invocation inline when that map does not carry the id.

## Round 2: PR #513 ship-gate findings

The Codex tri-adversarial ship-gate returned NO-SHIP on four findings against `Stop-HostNativeProcessTreeAndWait`, and the PR review threads named the same defects. All four are closed at the reviewed head: the pre-entry `HasExited` return no longer skips descendant containment, descendant stops are identity-revalidated against PID reuse, containment is a bounded re-enumerating fixed point rather than one snapshot, and the tree-kill capability decision is injectable so the Windows PowerShell 5.1 fallback is exercised as behaviour. The round also restored `-DryRun` adjudication of `KIT_CONTROL_URL` and put `test-host-native-launcher.ps1` into the required `rebuild-test-deploy` CI job, which is why `.github/workflows/ci.yml` and `scripts/verification-manifest.json` joined this entry's `verification_mechanism_paths`.

## Round 3: PR #513 ship-gate second pass

A second gate pass found three more defects in the same helper, all real. The exited-parent sweep added in round 2 is only sound where the OS keeps the creator PID on an orphan — measured as true on Windows and false on Linux, where the kernel re-parents orphans — so that platform fact now lives in `Test-OrphanRediscoverySupported` and the helper fails closed where PPID rediscovery cannot prove containment, naming the caller as the authoritative boundary and accepting a pre-exit descendant record as the escape. Reaching the deadline is no longer treated as a clean containment pass. `TimeoutMs` is now one end-to-end budget spanning discovery, termination, the parent wait, and every containment pass.

Both behavioural regressions were confirmed against the previous implementation before the fix, not merely argued: the clean-pass scenario returned success after discovering twelve descendants, and the slow-discovery scenario overran its advertised bound by 1286 ms. The POSIX branch of the platform gate is proven on this host through the injected capability decision; it has not been executed on a real re-parenting kernel, which is recorded as a limit in `verification.txt`.

## Round 4: narrowing the claim instead of chasing the next window

Three gate rounds each produced a HIGH against the same helper, and each one was a different way of saying that a PPID-based sweep cannot deliver inescapable containment. Round 4 stops patching windows and fixes the claim: `Stop-HostNativeProcessTreeAndWait` is now documented, messaged and tested as a **bounded best-effort sweep with a fail-closed provability report** — never "nothing survived". Inescapable containment needs an OS boundary established at launch, which is tracked separately in [#517](https://github.com/monkey1sai/AI-BIM-governance/issues/517) and its `Start-HostNativeService` follow-up.

The `-KnownDescendantProcessIds` escape hatch was removed: it existed only to let the helper keep claiming provable containment on a re-parenting platform, and neither production caller used it.

The round's remaining HIGH — a descendant appearing between enumeration and the following stop — was **refuted by measurement**, and that measurement is now a regression case. One residual survives it and is documented rather than closed, because closing it would trade a fail-open gap for a fail-dangerous one; see `verification.txt` for both.

## Limits

- No canonical Linux rebuild and no canonical deployment verification were executed for this bundle. Both are recorded in the entry's verification contract and are owed at fixpoint.
- The Linux leg of the verifier (`pwsh scripts/verify-all.ps1 -Profile Deployment -PlanOnly` on the canonical target) was not executed from this workstation; only the Windows leg was.
- Full-system browser, Kit first-frame, stage, and DataChannel E2E are not claimed.

## Fixpoint obligation

After this pull request merges, rebuild the canonical Linux test target from freshly fetched `origin/main`, rerun the entry's verification contract in full, record the merged mechanism commit and the canonical evidence under `docs/evidence/mechanism-hardening-2/fixpoint/`, and close the ledger entry with its attestation.
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
document_nature=working_note_bootstrap_evidence_not_runtime_spec
stack_kind=self_referential_bootstrap
ledger_entry=mechanism-hardening-2
base_commit=472192386f8402cf19a29005daf25556d26f222c
host=windows pwsh=7.5.4
gitnexus=NOT_APPLICABLE (the GitNexus index carries no PowerShell symbols; `impact Stop-HostNativeProcessTreeAndWait` and `impact Resolve-HostNativeKitControlUrl` both returned target-not-found, so callers were established by repository-wide grep instead)
command_resolution=every `PASS <id>` below without an inline invocation resolves through the immutable command map `$commandSpecById` in scripts/tests/test-self-referential-bootstrap.ps1 at the recorded head; the ids that map does not carry are written with their resolved invocation inline
--- round 1: initial bundle, recorded at base_commit ---
PASS test-deploy-governance-static
PASS test-verify-all
PASS test-host-native-launcher
PASS test-host-native-child-launch
PASS test-deploy-dryrun (pwsh -NoProfile -NonInteractive -File scripts/tests/test-deploy-dryrun.ps1)
PASS test-deploy-env-fallback (pwsh -NoProfile -NonInteractive -File scripts/tests/test-deploy-env-fallback.ps1)
PASS test-rebuild-test-deploy
PASS test-platform-adapter
PASS test-preflight-ports
PASS test-stop-all-single-pid (pwsh -NoProfile -NonInteractive -File scripts/tests/test-stop-all-single-pid.ps1)
PASS test-kit-log-probe
PASS test-deploy-target-registry
PASS test-remote-deploy-transport
PASS test-self-referential-bootstrap
PASS test-agent-governance-check
PASS invoke-powershell-static
Comment thread
monkey1sai-blip marked this conversation as resolved.
NOTE test-deploy-dryrun, test-deploy-env-fallback and test-stop-all-single-pid each have an executable source under scripts/tests/ and pass on this branch, but none of the three is in the immutable command map, so none of them is a verification-contract command id; all three are supporting evidence only. Adding them to the map and to the entry's ordered command_ids would enlarge this entry's fixpoint obligation, so that scope decision is left to the ledger owner rather than taken inside a review-fix round.
PASS deploy-dry-run-operator-path (scripts/deploy.ps1 -DryRun exits 0 and leaves the working tree clean)
PASS verify-all-deployment-plan-only-windows (scripts/verify-all.ps1 -Profile Deployment -PlanOnly exits 0)
NOT_RUN verify-all-deployment-plan-only-linux (no canonical Linux session was opened for this bundle)
NOT_RUN canonical-linux-rebuild (owed at fixpoint; no baseline rebuild was executed for this bundle)
NOT_RUN canonical-linux-deployment-verify (owed at fixpoint)
--- round 2: PR #513 ship-gate NO-SHIP findings and review threads ---
reviewed_head_commit=110c657fd620e3bdbac4379ac716da99d37848b9
reviewed_head_worktree=clean (`git status --porcelain` produced no output at the recorded commit)
reviewed_host=windows pwsh=7.5.4
reviewed_scope=scripts/lib/host-native-launcher.ps1, scripts/deploy.ps1, scripts/tests/test-host-native-launcher.ps1, scripts/tests/test-deploy-dryrun.ps1, .github/workflows/ci.yml, scripts/verification-manifest.json, scripts/self-referential-bootstrap-ledger.json
PASS test-host-native-launcher
PASS test-deploy-governance-static
PASS test-verify-all
PASS test-self-referential-bootstrap
PASS invoke-powershell-static
PASS test-rebuild-test-deploy
PASS test-agent-governance-check
PASS test-deploy-dryrun (pwsh -NoProfile -NonInteractive -File scripts/tests/test-deploy-dryrun.ps1)
NOT_RUN the remaining round-1 command ids were not re-executed in round 2; nothing in the round-2 scope reaches them
--- round 3: PR #513 ship-gate second pass (L1-COR-001 platform gate, L1-SEC-001 clean pass, L1-COR-002 single budget) ---
reviewed_head_commit=d63453024f59b13714ed222ea14bdc34a2890253
reviewed_head_worktree=clean (`git status --porcelain` produced no output at the recorded commit)
reviewed_host=windows pwsh=7.5.4
reviewed_scope=scripts/lib/host-native-launcher.ps1, scripts/lib/platform/platform-adapter.ps1, scripts/tests/test-host-native-launcher.ps1
PASS test-host-native-launcher
PASS test-deploy-governance-static
PASS test-verify-all
PASS test-self-referential-bootstrap
PASS invoke-powershell-static
PASS test-platform-adapter
PASS test-host-native-child-launch
PASS test-rebuild-test-deploy
MEASURED windows-orphan-rediscovery=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; this is the platform fact Test-OrphanRediscoverySupported encodes)
MEASURED regression-is-real (previous implementation at 26f056d, same two scenarios): the clean-pass scenario returned SUCCESS after discovering 12 descendants with an empty survivor set, and the slow-discovery scenario spent 2786 ms against an advertised 1500 ms bound
NOT_RUN linux-leg-of-the-platform-gate (no canonical Linux session was opened; the POSIX fail-closed branch is proven on this host through the injected capability gate, not on a real re-parenting kernel)
NOT_RUN the remaining round-1 command ids were not re-executed in round 3; nothing in the round-3 scope reaches them
--- round 4: PR #513 ship-gate third pass, resolved by NARROWING the helper's claim ---
reviewed_head_commit=3044e788ae2a741ea1f877f3353874cc31d606ad
reviewed_head_worktree=clean (`git status --porcelain` produced no output at the recorded commit)
reviewed_host=windows pwsh=7.5.4
reviewed_scope=scripts/lib/host-native-launcher.ps1, scripts/tests/test-host-native-launcher.ps1
PASS test-host-native-launcher
PASS test-deploy-governance-static
PASS test-verify-all
PASS test-self-referential-bootstrap
PASS invoke-powershell-static
PASS test-platform-adapter
PASS test-host-native-child-launch
PASS test-rebuild-test-deploy
MEASURED post-enumeration-descendant=CONTAINED (gate HIGH-2 refuted). Real three-level chain, grandchild hidden from the snapshot only and running throughout, tree-kill capability forced off so .NET's recursive kill could not mask the helper's own logic. Containment pass 1 re-walked every snapshot member the stop had just killed, rediscovered the grandchild through its dead parent's link and stopped it; pass 2 returned clean. Parent, child and grandchild all gone, helper returned success, lookup sequence [P, D, P, D, conhost, G, P]. Now pinned as a regression case.
ANALYSIS-NOT-MEASURED residual-sub-window: a descendant discovered AND stopped inside one pass drops out of the expansion roots, so a child it spawned between that pass's enumeration and its stop is not rediscovered. Not closed on purpose - expanding from dead PIDs on 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). Owned by the launch-time OS boundary follow-up, #517.
CONTRACT the helper is now documented and tested as a bounded best-effort sweep with a fail-closed provability report, NOT an escape-proof boundary; -KnownDescendantProcessIds was removed because it let the helper keep claiming provable containment on a re-parenting platform and neither production caller used it
NOT_RUN linux-leg-of-the-platform-gate (still no canonical Linux session; the POSIX fail-closed branch remains proven only through the injected capability gate on this host)
NOT_RUN the remaining round-1 command ids were not re-executed in round 4; nothing in the round-4 scope reaches them
LIMIT canonical-post-change-verification=pending merge and mainline fixpoint rebuild
LIMIT full-system-e2e=not claimed
Loading
Loading