From 3392492ff6d9e2cd20db0d1542262225469ac856 Mon Sep 17 00:00:00 2001 From: KbWen Date: Sat, 5 Sep 2026 21:52:07 +0800 Subject: [PATCH 1/2] chore(release): cut v1.8.26 Bumps the seven canonical version surfaces plus CITATION.cff date-released (1.8.25 -> 1.8.26, 2026-08-27 -> 2026-09-05) and adds the CHANGELOG entry for the three units merged since v1.8.25: the pre-commit credential fail-open fix (#433), the workflow job-graph guard (#183), and the skill trigger-accuracy eval (#398). The release notes lead with the one thing an adopter must act on: re-run the INSTALL copy. .githooks/pre-commit is a copy the user made and deploy.sh never rewrites it, so the fix does not reach an already-installed hook on its own. Without that line the release would claim a fix most existing adopters do not have - the same over-promise class the release itself fixes. Downstream delta measured rather than described: of the 26 files changed since v1.8.25, 6 are in the deploy set. The three credential tools are core tier and force-update; the eval suite deliberately does not ship. No engine, gate order, deployed file set, or configuration change. Co-Authored-By: Claude Opus 5 --- .agentcortex/bin/deploy.sh | 2 +- .agentcortex/docs/TESTING_PROTOCOL.md | 2 +- .agentcortex/docs/TESTING_PROTOCOL_zh-TW.md | 2 +- .agentcortex/docs/guides/antigravity-v5-runtime.md | 2 +- CHANGELOG.md | 13 +++++++++++++ CITATION.cff | 4 ++-- docs/AGENT_MODEL_GUIDE.md | 2 +- docs/AGENT_MODEL_GUIDE_zh-TW.md | 2 +- 8 files changed, 21 insertions(+), 8 deletions(-) diff --git a/.agentcortex/bin/deploy.sh b/.agentcortex/bin/deploy.sh index a6cd5a5a..d1b681ce 100644 --- a/.agentcortex/bin/deploy.sh +++ b/.agentcortex/bin/deploy.sh @@ -26,7 +26,7 @@ TARGET="${TARGET:-.}" TARGET="${TARGET%/}" MANIFEST_FILE="$TARGET/.agentcortex-manifest" -ACX_VERSION="1.8.25" +ACX_VERSION="1.8.26" # --- Self-deploy guard --- TARGET_ABS="$(cd "$TARGET" 2>/dev/null && pwd || echo "$TARGET")" diff --git a/.agentcortex/docs/TESTING_PROTOCOL.md b/.agentcortex/docs/TESTING_PROTOCOL.md index 0c310e0d..17e0dbf3 100644 --- a/.agentcortex/docs/TESTING_PROTOCOL.md +++ b/.agentcortex/docs/TESTING_PROTOCOL.md @@ -1,4 +1,4 @@ -# Testing Protocol v1.8.25 +# Testing Protocol v1.8.26 > **This document guides the AI Agent to produce high-quality, trustworthy, and defensive test code.** diff --git a/.agentcortex/docs/TESTING_PROTOCOL_zh-TW.md b/.agentcortex/docs/TESTING_PROTOCOL_zh-TW.md index a04a55d3..79fdbb74 100644 --- a/.agentcortex/docs/TESTING_PROTOCOL_zh-TW.md +++ b/.agentcortex/docs/TESTING_PROTOCOL_zh-TW.md @@ -1,4 +1,4 @@ -# Testing Protocol (測試教戰守則) v1.8.25 +# Testing Protocol (測試教戰守則) v1.8.26 > > **本文件旨在指引 AI Agent 產出高品質、可信任、且具備防禦性的測試程式碼。** diff --git a/.agentcortex/docs/guides/antigravity-v5-runtime.md b/.agentcortex/docs/guides/antigravity-v5-runtime.md index 316abcdd..b78b4ecb 100644 --- a/.agentcortex/docs/guides/antigravity-v5-runtime.md +++ b/.agentcortex/docs/guides/antigravity-v5-runtime.md @@ -8,7 +8,7 @@ Date: 2026-04-17 > **Two version axes — do not conflate.** "Runtime v5" throughout this file is this > anti-drift *engine spec's* own generation number; the canonical Antigravity runtime > **contract** version is **Runtime v1** (see `AGENTS.md §Agentic OS Runtime v1`). The -> framework release version (v1.8.25) is tracked separately in `CHANGELOG.md`. +> framework release version (v1.8.26) is tracked separately in `CHANGELOG.md`. Scope: **Antigravity environments** (token-generation agents where shell exit codes don’t halt execution) ### Why v5 exists diff --git a/CHANGELOG.md b/CHANGELOG.md index 65b2333a..2db4ec4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [1.8.26] - 2026-09-05 + +This release carries one security fix that adopters must act on, plus two upstream guards. **If you installed the pre-commit hook, re-run the INSTALL copy after updating — the fix does not reach your installed hook on its own.** + +- **The pre-commit credential pre-screen no longer reports success while a staged secret reaches object history.** It picked its interpreter by existence alone, so the stock-Windows App Execution Alias stub — a `python` that resolves on PATH and cannot start — was selected, failed, and the hook printed "could not run … continuing". A startable python whose scanner run errors did the same. In both states the deployed no-Python floor, which ADR-008 designates the **canonical** control, was never consulted. Both were reproduced end-to-end on fresh deploy targets, each landing a real commit that still returned the staged private-key header from object history. The hook now probes startability exactly as `validate.sh` does (backlog #144's fix, applied at last to its third call site) and falls through to the floor on a scanner execution error — the policy `security.yml` already applies in CI: *an execution error is NOT a clean scan*. +- **A no-Python adopter's first framework commit was blocked by the framework's own file, and that is fixed at the source.** Following the deploy banner's instructions verbatim — install the hook, then the banner's own `git add … .agentcortex/ …` — the floor flagged `.agentcortex/tools/scan_credentials.py`, a core-tier file the deploy had just written, and told the adopter to *rotate a secret*. The flagged line is the docstring documenting the allowlist escape hatch, quoting AWS's public example key in full; exactly one line matched across 169 staged files. The file's own fixtures already avoid this by concatenation — the prose never applied its own convention. Measured before and after on the identical path: blocked, then clean. +- **Honest labelling on the paths that stayed.** When the fallback runs and the floor comes back clean, the hook now says so explicitly: the floor screens 3 credential shapes where the python scanner screens 7, so a clean floor is not a clean scan — and a test pins both numbers to the two tools' own sources rather than leaving a quantified claim to decay. Both floors also stopped promising "CI TruffleHog is the backstop": a deployed tree ships no `.github/workflows` at all, so an adopter may have no CI backstop. +- **Two upstream guards, no adopter-visible behavior.** A CI test now fails on a dangling workflow `needs:` target (#183), and a skill trigger-accuracy suite guards the `trigger-registry.yaml` data contract from rotting (#398). The eval suite deliberately does **not** ship downstream; what does ship from that work is `repo-gotchas.md` §16, which records that skill activation is decided by `routing.md §3` and `bootstrap.md §3.6` — and that `trigger-registry.yaml`'s `intent_patterns` has no runtime consumer at all. + +**Downstream delta.** Measured, not assumed: **6 of the 26 files changed since v1.8.25 are in the deploy set**. Four are the credential fix (`.githooks/pre-commit.guard-ssot.sample`, `credential_floor.sh`, `credential_floor.ps1`, `scan_credentials.py`); `repo-gotchas.md` carries §16; `current_state.md` is scaffold tier and your own copy is preserved. The three tools are `core` tier and force-update on the next deploy, so the first-commit block closes for everyone automatically. **The hook does not.** `.githooks/pre-commit` is a copy you made; `deploy.sh` never rewrites it. An unmodified `.githooks/pre-commit.guard-ssot.sample` is updated for you and a modified one arrives as `.acx-incoming` — but until you re-run the INSTALL copy, your active hook keeps the old fail-open dispatch. No engine, gate order, or configuration change. + +**What this release does not do.** It does not reconcile the two credential screens' detection surfaces — the floor reads whole staged blobs where the scanner reads only added lines, excludes nothing where the scanner excludes two files, and matches its allowlist case-sensitively (#195); narrowing it would contradict AC-S4, so that needs a spec decision rather than a patch. `credential_floor.ps1` still ships with zero runtime callers (#196), and `deploy.sh` still has no stale-installed-hook detection (#197). Backlog #194's remaining downstream-audit scenarios — re-deploy idempotency, Windows-native path hazards, non-git targets, the check-for-check validator-twin diff, skill-body shipping, and the gate-bypass battery — remain **unaudited, not clean**. + ## [1.8.25] - 2026-08-27 This release closes the release-to-downstream consistency gap found by an adversarial premortem and removes a local test-discovery trap. diff --git a/CITATION.cff b/CITATION.cff index e9384aae..d3ea0e47 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -4,8 +4,8 @@ authors: - family-names: Wen given-names: Kb title: "Agentic OS: Governance-First Workflows for AI Coding Agents" -version: 1.8.25 -date-released: 2026-08-27 +version: 1.8.26 +date-released: 2026-09-05 url: "https://github.com/KbWen/agentic-os" abstract: "A governance-first framework for AI coding agents. Portable workflows, delivery gates, engineering guardrails, and 14 professional skills for Claude Code, OpenAI Codex, Google Antigravity, Cursor, GitHub Copilot, and other coding agents." keywords: diff --git a/docs/AGENT_MODEL_GUIDE.md b/docs/AGENT_MODEL_GUIDE.md index 95c7b90a..08674b55 100644 --- a/docs/AGENT_MODEL_GUIDE.md +++ b/docs/AGENT_MODEL_GUIDE.md @@ -1,4 +1,4 @@ -# Agentic OS v1.8.25 — Model Selection Guide +# Agentic OS v1.8.26 — Model Selection Guide > For human reference only — this file is not loaded into AI context. diff --git a/docs/AGENT_MODEL_GUIDE_zh-TW.md b/docs/AGENT_MODEL_GUIDE_zh-TW.md index 9509c656..86153923 100644 --- a/docs/AGENT_MODEL_GUIDE_zh-TW.md +++ b/docs/AGENT_MODEL_GUIDE_zh-TW.md @@ -1,4 +1,4 @@ -# Agentic OS v1.8.25 — 模型選擇指南 +# Agentic OS v1.8.26 — 模型選擇指南 > 人類參考用 — 此檔案不會被載入 AI context。 From 27fbc54b797bbd02ade53d66d3a95dea2a45b2d2 Mon Sep 17 00:00:00 2001 From: KbWen Date: Sat, 5 Sep 2026 21:59:02 +0800 Subject: [PATCH 2/2] chore(ship): record the v1.8.26 release cut and archive its Work Log SSoT sequence 168->169 with the completion record at the top of Ship History; rotated at cap 10 (Ship-fix-agents-md-backlog-write-scope-178-2026-08-23 -> archive/ship-history-2026.md, 151 -> 152 entries, no duplicate, no relative links to re-depth). Work Log moved to archive/ with its date suffix and appended to the hash-chained INDEX.jsonl (prev_sha 3a792eb8); check_audit_chain.py reports the chain intact. The rotation target named in the first draft of the ship entry was wrong - it still said the #398 eval entry, which the previous rotation had already moved past. Corrected against the file before writing rather than published and fixed afterwards. validate.sh after these writes: pass=99 warn=4 fail=0 skip=3, exit 0. Co-Authored-By: Claude Opus 5 --- .agentcortex/context/.guard_receipt.json | 6 +- .agentcortex/context/archive/INDEX.jsonl | 1 + .../archive/chore-release-v1.8.26-20260905.md | 150 ++++++++++++++++++ .../context/archive/ship-history-2026.md | 8 + .agentcortex/context/current_state.md | 20 +-- 5 files changed, 172 insertions(+), 13 deletions(-) create mode 100644 .agentcortex/context/archive/chore-release-v1.8.26-20260905.md diff --git a/.agentcortex/context/.guard_receipt.json b/.agentcortex/context/.guard_receipt.json index 88a3fcf2..aa3714f7 100644 --- a/.agentcortex/context/.guard_receipt.json +++ b/.agentcortex/context/.guard_receipt.json @@ -1,7 +1,7 @@ { - "expected_sha": "dd77b4f39777466835988468b07814ca8bd22ef580b2673d37b21f96cfa27db6", + "expected_sha": "d2831acb1a5c1fa22528706524e6ed50479741d425b5bc81749efc7da8606484", "mode": "replace", - "new_sha": "d2831acb1a5c1fa22528706524e6ed50479741d425b5bc81749efc7da8606484", + "new_sha": "d2622d215737951bb4edcca09cefc27d3391dce281f7b344ae5012b315c63d61", "target": ".agentcortex/context/current_state.md", - "timestamp": 1788609072 + "timestamp": 1788616412 } diff --git a/.agentcortex/context/archive/INDEX.jsonl b/.agentcortex/context/archive/INDEX.jsonl index 04977084..83cc5379 100644 --- a/.agentcortex/context/archive/INDEX.jsonl +++ b/.agentcortex/context/archive/INDEX.jsonl @@ -170,3 +170,4 @@ {"branch": "feat/skill-trigger-accuracy-eval-398", "classification": "feature", "decisions": ["D-5 supersedes D-4: runner is source-only", "AC-7 partially met, not rewritten", "premise refuted: intent_patterns has no runtime consumer"], "log": "feat-skill-trigger-accuracy-eval-398-20260901.md", "modules": [".agentcortex/eval/skills.yaml", ".agentcortex/tools/run_skill_eval.py", ".agentcortex/tests/test_skill_trigger_eval.py"], "patterns": ["eval-suite", "premise-refutation", "no-runtime-consumer", "roundtable-rejected-demolition"], "prev_sha": "7239221b", "shipped": "2026-09-01", "specs": ["docs/specs/skill-trigger-accuracy-eval.md"]} {"branch": "docs/downstream-stability-audit-findings", "classification": "quick-win", "decisions": ["File only primary-agent-reproduced findings; carry unreproduced subagent reports as leads in #194", "Expose exactly one finding (#191) as public issue #430 per the issue-exposure policy", "Put the audit continuation in a committed backlog row, not a gitignored Work Log or a session-local resume handle"], "log": "docs-downstream-stability-audit-findings-20260905.md", "modules": ["docs/specs/_product-backlog.md"], "patterns": ["downstream-simulation", "evidence-before-adding", "ai-discoverable-handoff"], "prev_sha": "0b7a27be", "shipped": "2026-09-05", "specs": ["backlog #188-#194"]} {"branch": "fix/precommit-credential-failopen", "classification": "hotfix", "decisions": ["Reject floor-first-always; keep probe + fallthrough", "The probe is justified on parity, not on security", "Classification stays hotfix above the rule minimum", "Fix the false positive at its source, not by re-scoping the floor"], "log": "fix-precommit-credential-failopen-20260905.md", "modules": [".githooks/pre-commit.guard-ssot.sample", ".agentcortex/tools/credential_floor.sh", ".agentcortex/tools/credential_floor.ps1", ".agentcortex/tools/scan_credentials.py"], "patterns": ["fail-open", "interpreter-startability", "advertised-but-unenforced", "paired-check-parity"], "prev_sha": "dc48eafa", "shipped": "2026-09-05", "specs": ["docs/specs/dev-flow-hardening.md#AC-8", "docs/specs/downstream-adaptability-optimization.md#AC-S4"]} +{"branch": "chore/release-v1.8.26", "classification": "quick-win", "decisions": [], "log": "chore-release-v1.8.26-20260905.md", "modules": [".agentcortex/bin/deploy.sh", "CITATION.cff", "CHANGELOG.md", "docs/AGENT_MODEL_GUIDE.md", ".agentcortex/docs/TESTING_PROTOCOL.md"], "patterns": ["release-cut", "adopter-delta-measured", "honest-subset-claim"], "prev_sha": "3a792eb8", "shipped": "2026-09-05", "specs": []} diff --git a/.agentcortex/context/archive/chore-release-v1.8.26-20260905.md b/.agentcortex/context/archive/chore-release-v1.8.26-20260905.md new file mode 100644 index 00000000..46626115 --- /dev/null +++ b/.agentcortex/context/archive/chore-release-v1.8.26-20260905.md @@ -0,0 +1,150 @@ +# Work Log: chore/release-v1.8.26 + +## Header + +- Branch: `chore/release-v1.8.26` +- Classification: `quick-win` +- Classified by: `claude-opus-5` +- Frozen: `2026-09-05` +- Created Date: `2026-09-05` +- Owner: `KbWen` +- Guardrails Mode: `Quick` +- Current Phase: `ship` +- Diff Base SHA: `0b08cb5` +- Checkpoint SHA: `none` +- Recommended Skills: `verification-before-completion, karpathy-principles` +- Primary Domain Snapshot: `release metadata` +- SSoT Sequence: `168` + +--- + +## Session Info + +- Agent: `claude-opus-5` +- Session: `2026-09-05 14:30 UTC` +- Platform: `claude-code` +- Files Read: `6` + +--- + +## Task Description + +Cut release v1.8.26. Bump the seven canonical version surfaces plus `CITATION.cff` `date-released`, and write the CHANGELOG entry for the three units merged since v1.8.25 (#183, #398, #433). No engine, gate, or configuration change. + +--- + +## Phase Sequence + +| Phase | Status | Entered | Notes | +|---|---|---|---| +| bootstrap | done | 2026-09-05 | quick-win, matching `chore/release-v1.8.23` precedent | +| plan | done | 2026-09-05 | 8 surfaces + CHANGELOG; downstream delta measured first | +| implement | done | 2026-09-05 | version bump + CHANGELOG entry | +| review | n/a | — | quick-win: optional, evidence inline | +| test | n/a | — | quick-win: optional, evidence inline | +| handoff | n/a | — | quick-win exempt | +| ship | pending | — | — | + +--- + +## Phase Summary + +**bootstrap/plan** — Classified `quick-win` on the `chore/release-v1.8.23` precedent (same shape, same archive header). The plan step that mattered was measuring the adopter delta **before** writing the notes rather than describing the release from its commit list: `git diff --name-only v1.8.25..HEAD` intersected with the deploy manifest golden gives **6 of 26** changed files actually reaching an adopter. That number, not the 14-commit log, is what the Downstream delta paragraph states. + +**implement** — Seven version surfaces plus `CITATION.cff date-released` bumped 1.8.25 → 1.8.26 / 2026-08-27 → 2026-09-05, each by an asserted single-occurrence replace. CHANGELOG entry written in house format. The release notes lead with the one instruction an adopter must act on: **re-run the INSTALL copy**, because `.githooks/pre-commit` is a user-made copy `deploy.sh` never rewrites — without that line the release would claim a fix most existing adopters do not have, which is the same over-promise class this release fixes. + +⚡ ACX + +--- + +## Gate Evidence + +- Gate: bootstrap | Verdict: PASS | Classification: quick-win | Timestamp: 2026-09-05T14:30:00Z +- Gate: plan | Verdict: PASS | Classification: quick-win | Timestamp: 2026-09-05T14:35:00Z +- Gate: implement | Verdict: PASS | Classification: quick-win | Timestamp: 2026-09-05T14:45:00Z + +--- + +## External References + +| Type | Path / URL | Notes | +|---|---|---| +| PR | https://github.com/KbWen/agentic-os/pull/433 | the security fix this release carries | +| Backlog | `#195` / `#196` / `#197` / `#194(b)-(h)` | named in the release notes as NOT done | +| Guard | `tests/ci/test_release_version_consistency.py` | pins all 8 surfaces to `deploy.sh` | + +--- + +## Known Risk + +- The hook fix does not reach an already-installed `.githooks/pre-commit`. Mitigated only by the release notes; the mechanical fix is filed as **#197**, not attempted here. +- Rollback: revert the version bump commit; no state migration. The tag/Release are the only non-git artifacts and are created after merge. + +--- + +## Decisions + +none + +--- + +## Conflict Resolution + +none + +--- + +## Skill Notes + +none + +--- + +## Drift Log + +none + +--- + +## Review Feedback + +none + +--- + +## Red Team Findings + +none + +--- + +## Design Reference + +none + +--- + +## Observability + +none + +--- + +## Resume + +none + +--- + +## Test Gate Results + +none + +--- + +## Evidence + +- **Adopter delta measured, not assumed**: `git diff --name-only v1.8.25..HEAD` = 26 files; intersected with `deploy_manifest_golden.txt` = **6** — `.githooks/pre-commit.guard-ssot.sample`, `credential_floor.sh`, `credential_floor.ps1`, `scan_credentials.py`, `repo-gotchas.md`, `current_state.md` (scaffold, adopter copy preserved). `run_skill_eval.py` and `eval/skills.yaml` are **not** in the deploy set (grep count 0), so #398's suite is upstream-only. +- Release guard `tests/ci/test_release_version_consistency.py`: **2 passed** after the bump. +- Version-sensitive subset run locally: `test_release_version_consistency.py` + `test_deploy_tiering.py` + `test_pre_commit_hook.py` -> **47 passed, 1 skipped** (9:41). This is a **subset, not CI-equivalent** - the full 947-test suite runs on CI's three Windows shards, which is the real environment for it; no local full-suite claim is made for this cut. +- Stale-version sweep after the bump: the only surviving `1.8.25` outside `CHANGELOG.md`/archive is inside the v1.8.25 Ship History entry, which `ship.md` forbids editing. Correct to leave. diff --git a/.agentcortex/context/archive/ship-history-2026.md b/.agentcortex/context/archive/ship-history-2026.md index 6215c504..5304ebd2 100644 --- a/.agentcortex/context/archive/ship-history-2026.md +++ b/.agentcortex/context/archive/ship-history-2026.md @@ -2,6 +2,14 @@ Archived from `current_state.md ## Ship History` to stay within the 10-entry cap. Entries are rotated out verbatim (per ship.md §205 — never edited), newest-archived first. +### Ship-fix-agents-md-backlog-write-scope-178-2026-08-23 +- Feature shipped: **backlog #178 — a precedence contradiction that fired on every non-`tiny-fix` bootstrap is gone.** `AGENTS.md` §Write Isolation scoped `_product-backlog.md` writes to spec-intake/ship, while `bootstrap.md §1` step 5 **mandates** a `Pending → In Progress` advance at bootstrap and calls it the only valid such transition. Under the documented precedence (AGENTS.md > workflows) the governance surface forbade the step the workflow required. **Reproduced live** during this session's #175 bootstrap before being fixed here. Resolved by **widening the enumeration, not by moving the advance**: the bootstrap step is the behaviour the repo wants, so the surface that failed to name it is the one that was wrong — moving it would have traded a text defect for a behaviour change, and later phases are not guaranteed to run for every classification, so a row could sit `Pending` while work proceeded. +- **The §13 trim is real, not a formality.** Deletion-First requires a change to an always-loaded surface to cite a deletion in the same change. That `AGENTS.md` line carried **two duplicate no-Python fallback clauses** — one parenthetical, one trailing sentence, both left by the 2026-05-26 compression pass `f3b3b81` — which are merged into one here. Net **0 lines**, **+56 characters**, recorded honestly in the Work Log rather than claimed as a wash. The directive-count ratchet held at **37/37**, and the green was mutation-verified before being trusted: appending one `MUST` to the file yields `count 38 exceeds baseline 37 (growth)`. +- **Sub-item reconciled, and its knock-on stated at true size.** `docs/specs/downstream-adaptability-optimization.md` frontmatter read `status: frozen` while the SSoT Spec Index had recorded `[Shipped 2026-06-14, PR #238]` since June; it is now `shipped`. The index entry was confirmed present **first**, because under ADR-010 the Spec-Index-completeness check *skips* `frozen` but *requires* `shipped` specs to be indexed — flipping an unindexed spec would have turned a skip into a FAIL. One stale word in `tests/ci/test_validator_absent_tool_signal.py:43` ("frozen" → "shipped") was corrected in the same change. **Backlog #177's premise was rewritten rather than left to rot**: its frozen-gate half is now gone, but **AC-S5's wording still blocks** collapsing the two `deploy.sh` sites — that needs a spec-freshness update, not an unfreeze. +- **The gate caught two of my own errors mid-implement, both from running it rather than reading it.** (1) Editing `AGENTS.md` stales `trigger-compact-index.json`; the first `validate.ps1` run came back `fail=2` (`metadata deep validation` + `compact index freshness`) until `generate_compact_index.py` was re-run in the same change. (2) A new backlog row was filed with `Labels: dx` — but `dx` is a **Kind** value, not an existing label, which violates `bootstrap.md §5`'s label-reuse rule and tripped `backlog label vocabulary: 16 distinct labels (>15)`. Corrected to the existing `tooling`; the vocabulary is back to 15. +- **Test-cost measured, and it is worse than the backlog says.** Real job times from the #417 CI run: `Pytest (Windows) (1)` **21m57s** against shards 2 and 3 at **3m19s** and **4m14s**, while Linux runs the *entire* 897-test suite in **3m29s**. The cost is Windows process-spawn tax, not test count, and the shards are badly unbalanced because `--splits 3 --group N` runs with **no committed `.test_durations`**, so pytest-split falls back to an even *count* split and clusters every subprocess-shelling deploy test onto one shard. Backlog **#88** already tracks this but records `7:14` — stale by ~3×. Balanced, the same ~29.5 minutes of work is ~10 min/shard: a >2× CI wall-clock cut from one committed file. Two paths are already closed and should not be re-proposed: `pytest-xdist` was **measured slower** here, and deselecting `slow` in CI is explicitly rejected in `pytest.ini` (subprocess fidelity is the point). New row **#181** files the macOS-coverage gap this measurement surfaced — filed on a *verified absence* (15 ubuntu + 2 windows + **0 macos**) rather than a suspected break, since a BSD-vs-GNU scan of both shipped shell scripts came back clean and `sha256sum` already carries a deliberate `shasum`/`openssl` fallback. +- Tests: `validate.ps1` **exit 0 · pass=118 warn=3 fail=0 skip=2** and `validate.sh` **exit 0 · pass=118 warn=4 fail=0 skip=2**, both printing an **unqualified** `Agentic OS integrity check passed`. The one-WARN delta is again this session's own `stale advisory work log locks` — the 60-minute `stale_timeout_minutes` elapsed during a 90-minute suite, i.e. the documented phase-granular limitation in `config.yaml §worklog_lock`, not twin divergence. Full CI-equivalent suite with **no `-m` filter**: **896 passed, 1 skipped, exit 0** in 1:30:03. Targeted first: `test_directive_count_ratchet.py` + `test_validator_absent_tool_signal.py` → 14 passed. + ### Ship-fix-validator-twin-parity-176-175-2026-08-23 - Feature shipped: **backlog #175 — `validate.ps1` no longer mojibakes its own output on a non-UTF-8 Windows console.** The file's `§` and `—` were rendered through the console's code page; on a cp950/Big5 box they came out as `0xA1B1` / `0xA158`. `[Console]::OutputEncoding` is **process-global** and the validator runs in the caller's live session, so a set-and-leave would have mutated console state after exit: the fix saves it, sets UTF-8 (`New-Object System.Text.UTF8Encoding $false`), and restores it in a matching `finally` that wraps the whole script. **+15 lines, 0 deletions, no re-indentation of the 2840-line body** — a PowerShell `try` block creates no scope (measured: locals, `$script:` vars and functions all survive it), and `finally` runs on the script's `exit 1` while preserving the code (measured: `exitcode=1`). - **The backlog row was wrong and measurement corrected it.** Row #175 recorded that the bug "does not reproduce on `pwsh` 7 (the invocation `README.md:38` documents)", which would have made this a 5.1-only curiosity. Measured on the redirected byte stream — the path CI and any log capture see — `powershell` 5.1 and `pwsh` 7 emit **identical** big5 bytes; after the fix both emit correct UTF-8 (`0xC2A7` / `0xE28094`) and `restored=big5` confirms the caller's console is handed back. The row is corrected in place rather than silently shipped around. diff --git a/.agentcortex/context/current_state.md b/.agentcortex/context/current_state.md index 01ba879f..54cabdf1 100644 --- a/.agentcortex/context/current_state.md +++ b/.agentcortex/context/current_state.md @@ -12,9 +12,9 @@ - Active Work Log Path: derive from the raw branch name using filesystem-safe normalization before any gate checks. - Workflows & Policies: `.agent/workflows/*.md`, `.agent/rules/*.md` - **Project Name**: (set by /app-init) -- **Last Updated**: 2026-09-05T14:10:00Z +- **Last Updated**: 2026-09-05T15:00:00Z - **Last Verified**: 2026-09-05 -- **Update Sequence**: 168 +- **Update Sequence**: 169 - **ADR Index**: - docs/adr/ADR-001-governance-friction-tuning.md — ADR-001: Governance Friction Tuning, accepted 2026-04-23 (amended 2026-07-16: `design_tool` capability-seam escape rejected — D2 reaffirmed, do NOT retry) - docs/adr/ADR-002-guarded-governance-writes.md — ADR-002: Guarded Governance Writes (lock unification + CI lint + lifecycle frontmatter), accepted 2026-04-25 @@ -113,6 +113,14 @@ - [Category: signal-preservation][Severity: HIGH][Trigger: adding-capture-around-an-asserting-command][prev: c0d86ba9] Adding observation plumbing around a command can silently disable the assertion it was carrying. Confirmed 2026-08-16 (PR #412): to grep the deployed validator's output, `bash validate.sh` became `bash validate.sh | tee out.txt` — and GitHub Actions runs `run:` blocks as `bash -e {0}` with NO pipefail, so the pipeline reports tee's status. A FAILING downstream validate would have landed a green job, in the only step where CI asserts that exit code, inside a PR titled 'stop reporting a partial install as an unqualified pass'. Measured: `bash -e -c 'bash -c "exit 7" | tee /dev/null'` -> 0; with `set -o pipefail` -> 7. The same workflow already used `shell: bash` + `set -uo pipefail` forty lines up, so this was a deviation from an in-file precedent, not an unknown. The defect was found by two independently-briefed fresh reviewers (diff + standards only, no implementation rationale) and NOT by the author, which is the /review Freshness Invariant paying for itself in one shot. Discipline: when an edit touches a line that carries a pass/fail signal — a command whose exit code gates something, an assertion, a return — state what the signal was BEFORE the edit and prove it survives; for CI shell specifically, any pipe added to an exit-code-bearing step needs `shell: bash` or `set -o pipefail`, verified by running a deliberately-failing command through the same shape. ## Ship History +### Ship-chore-release-v1.8.26-2026-09-05 + +- Feature shipped: **v1.8.26** packages the three units merged since v1.8.25 — the pre-commit credential fail-open fix (**PR #433**), the workflow job-graph `needs:` guard (#183), and the skill trigger-accuracy eval (#398) — behind the seven canonical version surfaces plus `CITATION.cff date-released` (1.8.25→1.8.26, 2026-08-27→2026-09-05), each bumped by an asserted single-occurrence replace and pinned by `test_release_version_consistency.py` (**2 passed**). **No engine, gate order, deployed file set, or configuration change in the cut itself.** +- **The adopter delta was measured before the notes were written, not described from the commit log.** `git diff --name-only v1.8.25..HEAD` gives 26 files; intersected with `deploy_manifest_golden.txt`, **6** reach an adopter — the four credential files, `repo-gotchas.md` (§16, from #398), and `current_state.md` (scaffold tier, so the adopter's own copy is preserved). `run_skill_eval.py` and `eval/skills.yaml` are **not** in the deploy set, so #398's suite is upstream-only; #183 is `tests/ci/` only. Fourteen commits, three units, six files that actually land. +- **The release notes lead with the one instruction an adopter must act on, and that placement is the point.** `.githooks/pre-commit` is a copy the user made and `deploy.sh` never rewrites it, so **until they re-run the INSTALL copy their active hook keeps the old fail-open dispatch** — the three credential *tools* are `core` tier and force-update, but the dispatch logic deciding how to use them does not. Stating the fix without that sentence would claim a repair most existing adopters do not have: the same over-promise class #433 was written to remove. The mechanical remedy is filed as **#197** and deliberately not attempted in a release cut. +- Tests: release guard **2 passed**; version-sensitive subset (`test_release_version_consistency.py` + `test_deploy_tiering.py` + `test_pre_commit_hook.py`) **47 passed, 1 skipped** locally. That is a **subset, and it is recorded as one** — the full 947-test suite ran on the PR's three Windows shards rather than locally, which is the real environment for it, and no local full-suite claim is made for this cut. Stale-version sweep after the bump: the only surviving `1.8.25` outside `CHANGELOG.md`/`archive/` sits inside the v1.8.25 Ship History entry, which `ship.md` forbids editing. SSoT sequence 168→169; Ship History rotated at cap 10 (`Ship-fix-agents-md-backlog-write-scope-178-2026-08-23` → `archive/ship-history-2026.md`). +- **Named as not done rather than left implicit**, in the release notes as well as here: **#195** (the python scanner and the no-python floor do not share a detection surface; narrowing the floor would contradict AC-S4, so it needs a spec decision), **#196** (`credential_floor.ps1` ships core-tier with zero runtime callers), **#197** (no stale-installed-hook detection), and backlog **#194**'s remaining downstream-audit scenarios — re-deploy idempotency, Windows-native path hazards, non-git targets, the check-for-check validator-twin diff, skill-body shipping, and the gate-bypass battery — which stay **unaudited, not clean**. Post-merge completion per repo-gotchas #12: lightweight `v1.8.26` tag + `gh release create --latest`, recorded here because that step is NOT complete at PR merge and this repo has forgotten it twice. + ### Ship-fix-precommit-credential-failopen-2026-09-05 - Feature shipped: **the opt-in pre-commit credential pre-screen can no longer report success while a staged secret reaches object history.** Two host states were reproduced end-to-end on fresh `deploy.sh` targets, each landing a real commit that `git show HEAD:leak.txt` then returned: a python that resolves on PATH but **cannot start** (the stock-Windows App Execution Alias stub — `could not run (exit 49); continuing`), and a **startable python whose scanner run errors** (rc=3 — `continuing`, with the validator fully green). Backlog #144 replaced existence-only interpreter selection with a startability probe in `validate.sh` and `validate.ps1`; the hook is the **third call site and was never swept**. Separately the hook turned every non-0/1 scanner exit into "continuing", so the deployed python-free floor — present, executable, and the control ADR-008 designated **canonical** — was never consulted. Fixed by matching validate.sh's probe (same `python3`→`python` order) and falling through to the floor on a scanner execution error. @@ -181,11 +189,3 @@ - **The two operational facts that cost the sessions are now written down** in `repo-gotchas` §15, not left in a backlog row nobody re-reads: the action walks **each commit's diff across the range**, so a follow-up rename does **not** clear a finding and neither does add-then-remove — only removing the introducing commit does, in practice a squash; and commit **messages** are in scope, so documenting the incident can re-instantiate the pattern inside the commit that documents it. Both were obeyed here: the shape is described in prose only, and the working diff was **self-checked against the detector's own regex → 0 matches** before commit. - **Disposition honesty**: this is option **(a)** from #171's own recorded options, not a fresh judgement made under merge pressure. Option (b) "absorb the occasional block" is what just cost a merge; option (c) "upstream a bug report" is worth doing but is not a fix for this repo's CI. The row named (a) as its preference months before this session needed it. - Tests: full CI-equivalent suite with **no `-m` filter** → **897 passed, 1 skipped, exit 0** in 1:16:00 — the **+1 against the prior 896 is exactly the new scope test**, a verifiable delta rather than an unchanged number asserted to have changed. `validate.ps1` **exit 0 · pass=118 warn=3 fail=0 skip=2**; `validate.sh` **exit 0 · pass=118 warn=4 fail=0 skip=2** (the delta is this session's own stale advisory lock across a 76-minute run — `config.yaml §worklog_lock`'s documented phase-granular limitation). `test_security_workflow.py` 41 → **42 passed**. - -### Ship-fix-agents-md-backlog-write-scope-178-2026-08-23 -- Feature shipped: **backlog #178 — a precedence contradiction that fired on every non-`tiny-fix` bootstrap is gone.** `AGENTS.md` §Write Isolation scoped `_product-backlog.md` writes to spec-intake/ship, while `bootstrap.md §1` step 5 **mandates** a `Pending → In Progress` advance at bootstrap and calls it the only valid such transition. Under the documented precedence (AGENTS.md > workflows) the governance surface forbade the step the workflow required. **Reproduced live** during this session's #175 bootstrap before being fixed here. Resolved by **widening the enumeration, not by moving the advance**: the bootstrap step is the behaviour the repo wants, so the surface that failed to name it is the one that was wrong — moving it would have traded a text defect for a behaviour change, and later phases are not guaranteed to run for every classification, so a row could sit `Pending` while work proceeded. -- **The §13 trim is real, not a formality.** Deletion-First requires a change to an always-loaded surface to cite a deletion in the same change. That `AGENTS.md` line carried **two duplicate no-Python fallback clauses** — one parenthetical, one trailing sentence, both left by the 2026-05-26 compression pass `f3b3b81` — which are merged into one here. Net **0 lines**, **+56 characters**, recorded honestly in the Work Log rather than claimed as a wash. The directive-count ratchet held at **37/37**, and the green was mutation-verified before being trusted: appending one `MUST` to the file yields `count 38 exceeds baseline 37 (growth)`. -- **Sub-item reconciled, and its knock-on stated at true size.** `docs/specs/downstream-adaptability-optimization.md` frontmatter read `status: frozen` while the SSoT Spec Index had recorded `[Shipped 2026-06-14, PR #238]` since June; it is now `shipped`. The index entry was confirmed present **first**, because under ADR-010 the Spec-Index-completeness check *skips* `frozen` but *requires* `shipped` specs to be indexed — flipping an unindexed spec would have turned a skip into a FAIL. One stale word in `tests/ci/test_validator_absent_tool_signal.py:43` ("frozen" → "shipped") was corrected in the same change. **Backlog #177's premise was rewritten rather than left to rot**: its frozen-gate half is now gone, but **AC-S5's wording still blocks** collapsing the two `deploy.sh` sites — that needs a spec-freshness update, not an unfreeze. -- **The gate caught two of my own errors mid-implement, both from running it rather than reading it.** (1) Editing `AGENTS.md` stales `trigger-compact-index.json`; the first `validate.ps1` run came back `fail=2` (`metadata deep validation` + `compact index freshness`) until `generate_compact_index.py` was re-run in the same change. (2) A new backlog row was filed with `Labels: dx` — but `dx` is a **Kind** value, not an existing label, which violates `bootstrap.md §5`'s label-reuse rule and tripped `backlog label vocabulary: 16 distinct labels (>15)`. Corrected to the existing `tooling`; the vocabulary is back to 15. -- **Test-cost measured, and it is worse than the backlog says.** Real job times from the #417 CI run: `Pytest (Windows) (1)` **21m57s** against shards 2 and 3 at **3m19s** and **4m14s**, while Linux runs the *entire* 897-test suite in **3m29s**. The cost is Windows process-spawn tax, not test count, and the shards are badly unbalanced because `--splits 3 --group N` runs with **no committed `.test_durations`**, so pytest-split falls back to an even *count* split and clusters every subprocess-shelling deploy test onto one shard. Backlog **#88** already tracks this but records `7:14` — stale by ~3×. Balanced, the same ~29.5 minutes of work is ~10 min/shard: a >2× CI wall-clock cut from one committed file. Two paths are already closed and should not be re-proposed: `pytest-xdist` was **measured slower** here, and deselecting `slow` in CI is explicitly rejected in `pytest.ini` (subprocess fidelity is the point). New row **#181** files the macOS-coverage gap this measurement surfaced — filed on a *verified absence* (15 ubuntu + 2 windows + **0 macos**) rather than a suspected break, since a BSD-vs-GNU scan of both shipped shell scripts came back clean and `sha256sum` already carries a deliberate `shasum`/`openssl` fallback. -- Tests: `validate.ps1` **exit 0 · pass=118 warn=3 fail=0 skip=2** and `validate.sh` **exit 0 · pass=118 warn=4 fail=0 skip=2**, both printing an **unqualified** `Agentic OS integrity check passed`. The one-WARN delta is again this session's own `stale advisory work log locks` — the 60-minute `stale_timeout_minutes` elapsed during a 90-minute suite, i.e. the documented phase-granular limitation in `config.yaml §worklog_lock`, not twin divergence. Full CI-equivalent suite with **no `-m` filter**: **896 passed, 1 skipped, exit 0** in 1:30:03. Targeted first: `test_directive_count_ratchet.py` + `test_validator_absent_tool_signal.py` → 14 passed.