Skip to content

Workflow policy: pull_request reachability rules (supersedes #682) and a ParseScalar-exact guard check - #686

Merged
seathatflowsinourveins merged 4 commits into
mainfrom
foundation/workflow-policy-pr-reachability-20261004
Oct 4, 2026
Merged

seathatflowsinourveins merged 4 commits into
mainfrom
foundation/workflow-policy-pr-reachability-20261004

Conversation

@seathatflowsinourveins

@seathatflowsinourveins seathatflowsinourveins commented Oct 4, 2026 •

Copy link
Copy Markdown
Collaborator

Scope

The three rules (in RULES; check_directory() now reads the directory as a whole):

Rule Fails on Planted (each must fail with exactly this rule) Accepted (must pass)
pull-request-environment an environment: on a job that a pull_request-family event reaches, whatever its if: environment-on-a-pull-request-job, environment-behind-an-if-guard, environment-on-a-comment-job, environment-in-a-called-workflow (two files: a pull_request caller and a workflow_call callee) environment-off-the-pull-request-family (push only)
pull-request-remote-workflow such a job calling a reusable workflow by anything but ./.github/workflows/{file} or $/.github/workflows/{file} remote-reusable-workflow (pinned by SHA, so zizmor's unpinned-uses passes it), remote-call-in-a-reusable-workflow remote-call-off-the-pull-request-family, local-reusable-workflow-call and same-commit-call-with-the-dollar-form (two files each)
comment-event-secret a secret other than GITHUB_TOKEN (named, secrets: inherit or the whole context; decoded values, then the raw text, as pull-request-secret reads them) in a workflow that issue_comment, pull_request_review or pull_request_review_comment triggers issue-comment-secret, review-secrets-inherit, review-comment-secret-behind-an-escape (secrets); from the review round: issue-comment-whole-context-after-a-quoted-marker, review-whole-context-after-a-quoted-marker, review-comment-whole-context-after-a-quoted-marker, comment-call-passing-an-indexed-secret-after-a-quoted-marker, comment-secret-by-a-computed-index comment-workflow-with-the-job-token; from the review round: comment-workflow-with-the-job-token-by-index, comment-workflow-with-the-job-token-by-a-double-quoted-index

Reachability (reachable()). The pull_request family is #682's event set: pull_request, pull_request_target, pull_request_review, pull_request_review_comment, issue_comment and workflow_run. A workflow is reached by one of those triggers, and then, as #682 computed it, through every ./ or $/ call that a reached job makes, transitively and whatever the callee's own triggers. After that, a workflow_call trigger alone counts, as #681's PULL_REQUEST_EVENTS already counts it. The reason is that adoption/scaffold/.github/workflows/sota-sources.yml.template calls sota-sources-gate.yml from other repositories' pull_request workflows. This last step is stricter than #682 (see open points).

The two job rules do not credit if:. The module's one accepted guard, github.event_name != 'pull_request', still lets issue_comment and review runs through, and in a called workflow github.event_name is the caller's. A new test, test_reachability_follows_local_calls_and_names_the_caller, checks two things: a violation in a callee names its caller, and a call is followed through a $/ hop to a callee that has no workflow_call trigger.

On the base's 21 workflows, no job declares environment:, no job calls a reusable workflow, and no workflow has a comment or review trigger. All three rules therefore pass on the real tree with no exemption.

The P2 residuals on #681's excludes_pull_request (repair round 2). The helper now follows actions/runner's TemplateReader.ParseScalar. A value either holds no ${{ (a bare expression), or opens one at its first character and closes it, quote-aware, at its last. The expression's text outside string literals may hold no delimiter.

  • (a) strip() accepted literal whitespace around a whole expression. ParseScalar keeps that whitespace as a literal segment of a truthy format() string.
    • Planted regressions: upload-guard-with-a-leading-space, upload-guard-with-a-trailing-space, upload-guard-in-a-clipped-block-scalar (the line break a | scalar keeps), save-guard-with-a-leading-space and save-guard-with-a-trailing-space.
    • Unit cases: " ${{ ... }}", "${{ ... }} " and "${{ ... }}\n".
  • (b) The }} substring check refused valid guards. ParseScalar closes an expression only at a }} outside a single-quoted literal.
    • Accepted regressions: upload-guard-with-a-quoted-closing-marker and save-guard-with-a-quoted-closing-marker.
    • Unit cases: contains('a}}b', 'a'), bare and wrapped.
    • The discriminating refused case: a quoted ${{ in a bare value (contains(github.head_ref, '${{ github.sha }}')) still starts a segment, because ParseScalar finds the first ${{ with IndexOf, whatever the quotes.

Dependabot wording (the P2 in the review of #682 at 846cb03e). docs/decisions/2026-09-22-github-automation-closure.md said "fork and Dependabot PRs get a read-only token". It now says that Dependabot's token is read-only by default (it can be raised), citing GitHub's "Changing GITHUB_TOKEN permissions". No other test or document on main states the Dependabot token. The check was a scan of every tracked .md, .py, .json, .yml, .yaml, .toml and .txt file for "Dependabot" within 250 characters of "read-only". #682's own wording never reached main.

Cross-family review of aeb5ba25 (FINDINGS; one repair round, in d73e617e5). Both findings reproduced before the fix. They sit in the secrets scan that pull-request-secret, comment-event-secret and test_pull_request_jobs_hold_no_secret_and_no_write share.

  • P1. secret_references() delimited expressions with \$\{\{(.*?)\}\}, which stops at a }} inside a string literal. As a result, TOKEN: "${{ format('a}}b{0}', toJSON(secrets)) }}" gave no violation under any of the three comment/review events, nor under pull_request. The same held for secrets['NPM_TOKEN'] after the marker, including in a called workflow's secrets: mapping.
    • Fix: tests/test_workflow_policy.py:567 adds expressions(), which delimits as ParseScalar does, via expression_end() (:483, now taking a start offset). An expression that never closes is read to the end. secret_references() (:589) reads those spans (:598).
  • P2. secrets['GITHUB_TOKEN'] was flagged while secrets.GITHUB_TOKEN passed, although index and property syntax access the same value (Contexts reference).
    • Fix: SECRET_INDEX (:586) normalizes index access by one single- or double-quoted literal, unescaping '', to the name it indexes, before the token exception applies (:600).
    • The whole context (secrets, toJSON(secrets), secrets.*) and an index that is not one literal (secrets[format('{0}_TOKEN', 'GITHUB')]) stay violations, whatever they compute.
  • New controls.
    • Planted (each must fail with exactly its rule), at :994–:1008: the reviewer's env form under each of the three events, an indexed secret after a quoted }} in a call's secrets: mapping, and a computed index, all comment-event-secret; plus the env form under pull_request, pull-request-secret.
    • Accepted, at :1100–:1102: the token by single- and by double-quoted index.
    • Unit test test_secret_references_delimit_expressions_as_parse_scalar_does (:1352): 5 allowed and 9 refused forms, plus the span split.
  • Decision record. docs/decisions/2026-10-04-ci-least-privilege.md:291 records the round.
  • Not changed. The reviewer's non-blocking note that the reachability test's leaf.yml (on: workflow_dispatch) is not a GitHub-runnable callee: it is deliberate, to show that a call is followed whatever the callee's triggers, as the record states.

Map of #682's assertions (class PullRequestReachableJobsTests at 6e166809):

#682 assertion Where it lives now
Reachability: on: names a pull_request* event, issue_comment or workflow_run; local reusable workflows are followed transitively This PR: PULL_REQUEST_FAMILY and reachable(), which also counts workflow_call alone (stricter)
Every YAML-significant line stays in a plain block subset: no non-empty flow mapping, anchor, alias, tag, merge key, quoted key, multi-line scalar or backslash escape #681: the strict loader and the unparseable rule (StrictLoaderTests.test_constructs_outside_the_subset_are_rejected; planted anchor-and-alias, flow-mapping, tag, multi-line-plain-scalar, duplicate-permissions-key, tab-indentation). Quoted keys and escapes are decoded rather than refused (planted secrets-inherit-under-a-quoted-key, secrets-inherit-under-an-escaped-key, secret-behind-a-u-escape, secret-behind-an-x-escape)
Every on: yields events #681: load_workflow requires on, and triggers() reports any other form as unparseable
The job layout jobs() reads: headers at two spaces, keys at four, and a matching header count Not needed: #681's loader reads every job, and load_workflow requires a non-empty mapping of job mappings
A reachable job's ./.github/workflows/x is a workflow file here Not carried: a ./ or $/ path names a file at the caller's commit, and every file present is checked on its own; reachable() follows the call when the file is present
PyYAML cross-check of the event reader #681: test_the_loader_agrees_with_pyyaml compares the whole parsed tree (now 84 texts)
No ${{ }} naming the secrets context (secrets.X, secrets['X'], toJSON(secrets), comment lines included) in a pull_request workflow or a callee #681: pull-request-secret (decoded values, then the raw text with comments) for pull_request and workflow_call workflows
The same in a pull_request_target or workflow_run workflow #681: dangerous-trigger bans both triggers
The same in an issue_comment, pull_request_review or pull_request_review_comment workflow This PR: comment-event-secret
No secrets: key (secrets: inherit, a mapping, or a workflow_call declaration) secrets: inherit: #681's pull-request-secret, plus comment-event-secret here. A mapping that forwards ${{ secrets.X }} is caught by that reference. A declaration with no use, or literal values, reads no secret and is not carried
secrets.GITHUB_TOKEN refused Not carried (open point). #681 accepts it (accepted variant github-token-secret), and comment-event-secret follows that, now in both access forms (secrets.GITHUB_TOKEN, secrets['GITHUB_TOKEN']). It is the job's own token, also github.token, bounded by pull-request-write-scope and WRITE_GRANTS
No environment: on a reachable job This PR: pull-request-environment
No remote reusable-workflow call from a reachable job This PR: pull-request-remote-workflow
PULL_REQUEST_SECRET_SOURCE_ALLOWLIST (empty), where stale entries fail #681: EXEMPTIONS and test_each_exemption_is_still_needed, which now runs over the directory-wide pass
The write scopes of reachable jobs equal PULL_REQUEST_WRITE_ALLOWLIST in both directions (the two SARIF uploads) #681: pull-request-write-scope and WRITE_GRANTS (test_write_grants_are_the_reviewed_inventory, an equality over every job of every workflow)
write-all is refused, and so is any workflow-level write #681: writes() treats any non-mapping form as a write, and workflow-permissions-not-empty requires a top-level {}
A job with no permissions under a workflow with none (the repository default) #681: workflow-permissions-missing, and writes() counts the default as a write
A permissions form or access value it does not read #681: non-empty flow mappings are unparseable, and writes() counts any access other than read or none as a write
if: is not credited for write scopes Differs: #681 credits a whole github.event_name != 'pull_request' conjunct, now matching ParseScalar exactly (repair round 2). Both SARIF uploads pass through it
Its decision-record section and the PULL_REQUEST_EXPOSURE wording docs/decisions/2026-10-04-ci-least-privilege.md, "Reachability rules and repair round 2". The Dependabot qualification is applied to the one such sentence on main

SOTA sources

All were read on 2026-10-04 at 08:18Z; GitHub Docs were fetched through the docs article API. The older page URLs named in the brief redirect to the ones below.

Evidence-class table

Claim Evidence class Command / receipt
The three rules pass on the 21 workflows of main at b629b5b4 (merged in, including #688's security-scan.yml change), and both modules pass local_integration python3 -m unittest tests.test_workflow_policy tests.test_workflow_hardening: 138 tests, OK (skipped=3), exit 0 (base 6af8e55b: 136, exit 0)
Each of 59 planted entries fails with exactly its rule, and all 15 accepted variants pass synthetic the same run (PlantedViolationTests)
Breaking each new rule's predicate fails exactly that rule's controls synthetic a mutation harness kept outside the repository; results below
#681's helper fails the repair-round-2 regressions, and reverting either review-round fix fails its controls synthetic the same harness, cases M4, M6 and M7
Both review findings reproduced at aeb5ba25 before the fix: [] for the quoted-marker forms under all three events and pull_request, and comment-event-secret for secrets['GITHUB_TOKEN'] synthetic an in-memory check_directory() probe on that head
The loader agrees with PyYAML on all 92 texts, including the block-scalar, quoted-whitespace and quoted-marker forms local_integration uv run --no-project --with pyyaml==6.0.3 python -m unittest tests.test_workflow_policy.StrictLoaderTests.test_the_loader_agrees_with_pyyaml: OK, exit 0
GitHub's behaviour for environments, reusable workflows, events, context access, expression literals and Dependabot; ParseScalar's scan; zizmor's audits source_review the sources above
Hosted CI aeb5ba25: 8/8 required green (20 pass, 5 skipping); this head is next this PR's checks

Mutation results (at head 33276786; identical to the run before the merge). Each case runs PlantedViolationTests (12 tests) on a scratch copy of the module, with .github linked read-only. The worktree file's hash did not change.

Case Mutation Result
M0 none exit 0, OK
M1 pull-request-environment never fires exit 1, 5 failures: planted environment-on-a-pull-request-job, environment-behind-an-if-guard, environment-on-a-comment-job and environment-in-a-called-workflow, plus test_reachability_follows_local_calls_and_names_the_caller
M2 pull-request-remote-workflow never fires exit 1, 2 failures: planted remote-reusable-workflow and remote-call-in-a-reusable-workflow
M3 comment-event-secret never fires exit 1, 8 failures: planted issue-comment-secret, review-secrets-inherit, review-comment-secret-behind-an-escape, and the 5 review-round comment-event-secret controls
M4 excludes_pull_request reverted to #681's exit 1, 14 failures: the 5 repair-round-2 planted guards, its 2 accepted variants and 7 unit cases
M5 reachable() stops following calls exit 1, 1 failure: the reachability test. The workflow_call step still reaches the planted callee
M6 secret_references() back on the \$\{\{(.*?)\}\} regex (P1 reverted) exit 1, 8 failures: the 5 quoted-marker planted controls (all three events, the call's secrets: mapping, and pull_request) and 3 unit cases
M7 every index access read as the whole context (P2 reverted) exit 1, 7 failures: the 2 index-form accepted variants and 5 unit cases

Local commands run

All ran with nice -n 19 and a scratch TMPDIR outside the checkout, at head 33276786 (origin/main b629b5b4 merged in):

$ python3 -m unittest tests.test_workflow_policy tests.test_workflow_hardening
Ran 138 tests ... OK (skipped=3)                     # exit 0 (base 6af8e55b: 136 tests, exit 0)
$ python3 -m unittest tests.test_workflow_security_coverage tests.test_sota_sources_gate tests.test_adoption_docs_consistency
Ran 60 tests ... OK (skipped=1)                       # exit 0
$ uv run --no-project --with pyyaml==6.0.3 python -m unittest tests.test_workflow_policy.StrictLoaderTests.test_the_loader_agrees_with_pyyaml
OK                                                    # exit 0
$ python3 scripts/validate.py
{"components": 69, "hashed_files": 9881, "profiles": 4, "receipts": 195, "status": "passed"}   # exit 0
$ python3 scripts/evidence_manifest.py --check
{"files": 9881, "status": "passed"}                   # exit 0
$ python3 scripts/component_matrix.py --check; python3 scripts/new_host_grand_list.py --check
# exit 0; exit 0 (their --write steps in the hot-file protocol changed nothing)
$ git diff --check origin/main...HEAD                 # exit 0
$ python3 -P merge_tree_landing_check.py b629b5b41 332767860    # the coordinator's landing check, against current main
ok 1 to ok 5, LANDABLE                                # exit 0
$ python3 mutation_harness.py <worktree>              # kept outside the repository; exit 0, results above

Commits: 0a876732b (content), aeb5ba259 (registry), d73e617e5 (review-round content), then 332767860, the last commit. It merges origin/main at b629b5b4, takes main's manifests/evidence.json and re-registers the three files, per docs/lanes.md's merge path. Main's #688 had edited docs/decisions/2026-09-22-github-automation-closure.md 30 lines at 465, which merged cleanly with this branch's sentence, now at 1653. The registry differs from main's in exactly those three rows.

Decision record

docs/decisions/2026-10-04-ci-least-privilege.md, section "Reachability rules and repair round 2 (2026-10-04, superseding #682)". It covers the rules, the reachability computation, why these three rules, repair round 2, the Dependabot wording, what #682 held that is not carried, zizmor as the alternative, the overturn conditions, the evidence class and the sources.

Host evidence

Not applicable: no file under evidence/hosts/ changes.

Checklist

  • New/changed GitHub Actions are pinned to a full commit SHA with a
    version comment (no floating tags). No workflow or action changes.
  • New/changed workflows declare top-level permissions: {} and grant each job
    only what it needs (contents: read, or an explicitly justified addition). No workflow changes; the tripwire now also refuses environments and remote reusable workflows on pull_request-family jobs.
  • No secrets are printed, logged or committed; no new required secret was
    added without a documented owner.
  • No new paid hosting, subscription or billing surface was introduced.
  • Peer-owned untracked files and worktrees were preserved (not deleted,
    moved or overwritten).

Open points

🤖 Generated with Claude Code

Scout and others added 2 commits October 4, 2026 04:36
…ar-exact guard check

Fold the assertions of #682 that tests/test_workflow_policy.py did not yet hold into it as rules on the parsed
workflows, each with planted negative controls and accepted variants:

- pull-request-environment: no `environment:` on a job that a pull_request-family event reaches (#682's event set;
  local ./ and $/ reusable-workflow calls followed transitively; then a workflow_call trigger alone), whatever its if:
- pull-request-remote-workflow: such a job calls no reusable workflow except through ./.github/workflows/ or
  $/.github/workflows/
- comment-event-secret: no secret other than GITHUB_TOKEN in a workflow that issue_comment, pull_request_review or
  pull_request_review_comment triggers (the pull-request-secret reference set: decoded values, raw text, inherit)

Repair round 2, the P2 residuals on #681: excludes_pull_request now follows actions/runner's
TemplateReader.ParseScalar (d7bc179baf11). Literal whitespace around a whole expression, including the line break a
`|` block scalar keeps, no longer counts as excluding pull requests, and a `}}` inside a string literal no longer
refuses a valid guard.

Qualify the Dependabot token sentence in docs/decisions/2026-09-22-github-automation-closure.md (read-only by
default; it can be raised) and record the change in docs/decisions/2026-10-04-ci-least-privilege.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ecords

Hot-file protocol (docs/lanes.md): main's manifests/evidence.json with the three files this branch changed
re-registered through host_receipts.register_file; component_matrix.py --write and new_host_grand_list.py --write
changed nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@seathatflowsinourveins seathatflowsinourveins added the lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers label Oct 4, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-04T10:50:03.201611Z aeb5ba2 PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@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: aeb5ba2597

ℹ️ 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 tests/test_workflow_policy.py
Scout and others added 2 commits October 4, 2026 10:20
…HUB_TOKEN by index

Cross-family review of #686 at aeb5ba2 (one repair round):

- P1: secret_references() found expressions with the regex \$\{\{(.*?)\}\}, which stops at a `}}` inside a string
  literal, so `${{ format('a}}b{0}', toJSON(secrets)) }}` and the same with secrets['NPM_TOKEN'] passed
  comment-event-secret for all three comment and review events, and pull-request-secret on pull_request. It now reads
  each expression as expressions() delimits it, with expression_end(), the actions/runner TemplateReader.ParseScalar
  scan (d7bc179baf11); an unclosed expression is read to the end.
- P2: secrets['GITHUB_TOKEN'] was a violation while secrets.GITHUB_TOKEN passed. Index access by one string literal
  (SECRET_INDEX, single or double quotes) now names the secret it indexes, so the token passes in both forms; the
  whole context and an index that is not one literal stay violations.

New planted controls: the reviewer's env form under issue_comment, pull_request_review and
pull_request_review_comment, an indexed secret after a quoted `}}` in a called workflow's secrets mapping, a computed
index, and the env form under pull_request. New accepted variants: the token by single- and double-quoted index. The
decision record's section gains the review round.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… three files

Hot-file protocol, merge path (docs/lanes.md): main moved during the review round and its #688 edits
docs/decisions/2026-09-22-github-automation-closure.md (30 lines at 465; this branch's sentence, now at 1653, merged
cleanly) and .github/workflows/security-scan.yml. manifests/evidence.json is main's copy with
tests/test_workflow_policy.py and the two decision records re-registered through host_receipts.register_file;
component_matrix.py --write and new_host_grand_list.py --write changed nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

Claude session native-agent-stack-5f: landing at head 33276786006a664b3c309b7d626ade654cec76ca. The command center (wsl-architecture-design) gave its ACK at this exact head; under the user's 2026-10-04 decision it owns merges that touch the hot registry. The read-only cross-family review (GPT-6.1 Sol max, the packaged Codex SDK worker) returned FINDINGS at aeb5ba2597df; this head is reached from it through recorded carry edges (equal owned patch-ids, or a cross-family delta read returning ACCEPT at the edge's target), with its 1 P1 item(s) resolved in one repair round as recorded.

Observed main b629b5b413d75deb4c98dd26d62b129173b87d44. coordination/merge_tree_landing_check.py (sha256 a11649fcf2e5844c…) exit 0:

main b629b5b413d75deb4c98dd26d62b129173b87d44 head 33276786006a664b3c309b7d626ade654cec76ca base b629b5b413d75deb4c98dd26d62b129173b87d44 merged-tree 839db27a790f9a3324c95d00b3c08e3e2c212e91 merge-tree-exit 0
ok   1: clean three-way merge
ok   2: merged-vs-main paths 4, outside PR-owned 0 []
ok   3: main drift 0 paths, overlap with PR-owned inputs (registry excluded) []
ok   4: registry foreign rows equal True, order preserved True, PR-owned rows 3, unowned top-level keys differing []
ok   5: merged files[] sorted by path with no duplicates: True (9881 rows)
LANDABLE
condition 5: merged files[] sorted and unique (tree 839db27a790f9a3324c95d00b3c08e3e2c212e91)

Required checks at this head: 8 pass . Unresolved review threads: 0.

@seathatflowsinourveins
seathatflowsinourveins merged commit 07a6a0a into main Oct 4, 2026
28 of 31 checks passed
@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

Claude session native-agent-stack-5f: post-merge observation. Landed as 07a6a0a71c9d4823cc641e41b31fee58f10f7acd (parent b629b5b413d75deb4c98dd26d62b129173b87d44), tree 839db27a790f9a3324c95d00b3c08e3e2c212e91. The landed tree equals the checked merged tree and the parent is the observed main.

@seathatflowsinourveins
seathatflowsinourveins deleted the foundation/workflow-policy-pr-reachability-20261004 branch October 4, 2026 15:09
seathatflowsinourveins pushed a commit that referenced this pull request Oct 4, 2026
…ds branch (hot-file protocol: main's registry; PR rows re-registered last)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
seathatflowsinourveins pushed a commit that referenced this pull request Oct 4, 2026
…y (387 pieces, 80 not wired, 39 own entry)

The key under tui.model_availability_nux is one more not-wired piece (client state, not
configuration). Recounted on the tree merged with main 54eb892 (#674, #683, #686) by the GPT-6.1 Sol
worker; reviewed by the coordinator.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
seathatflowsinourveins added a commit that referenced this pull request Oct 4, 2026
… row, held status, TUI notice key (#687)

* Codex dated holds (R6): one pin row with a host-agnostic 0.159.3 hold until 2026-11-04

- adoption/pins-linux-x86_64.json: the codex row carries holds[] with one entry, 0.159.3 until
  2026-11-04 (X18, the #626 landing exception). Wrapper URL and SHA-256 are the row's values before
  f77a35e (from 85543ef, #580), re-verified against a registry download; the linux-x64
  platform_dependency (row shape) is first recorded here from the npm registry.
- scripts/adoption_status.py --pinned-versions: a probe naming a hold's version before its until date
  (UTC) is held (hold_* fields, summary "held", "held until <date> (<reason>)"), not drift; on and
  after until it is mismatched with the expiry stated. Malformed holds are skipped. The default run,
  the exit code and the existing keys are unchanged.
- tools/adoption/apply_codex_lane.py still refuses any codex but CODEX_VERSION; the refusal now names
  a matching hold and its until date.
- tests/test_pin_holds.py: every hold complete, until a real date after today (UTC) and at most
  90 days away, at most one hold per row (the OSV ignoreUntil precedent), with mutants.
- adoption/templates/codex.config.template.toml: "gpt-6.1-sol" = 4 under [tui.model_availability_nux],
  cited from openai/codex rust-v0.160.0 (MODEL_AVAILABILITY_NUX_MAX_SHOW_COUNT = 4).
- docs/decisions/2026-10-04-codex-dated-holds.md: design, alternatives, precedent, overturn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Codex dated holds: stack.json reference and evidence registry (hot-file protocol, last commit)

manifests/stack.json's codex row carries no install data, so its freshness refers to the pins row's
dated hold instead of copying it. manifests/evidence.json takes main's copy (6af8e55) and
re-registers this branch's changed files plus its new test and decision record, as #626 did;
component_matrix.py and new_host_grand_list.py --write reproduced their outputs unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* New-WSL client-config record: recount after the gpt-6.1-sol notice key (387 pieces, 80 not wired, 39 own entry)

The key under tui.model_availability_nux is one more not-wired piece (client state, not
configuration). Recounted on the tree merged with main 54eb892 (#674, #683, #686) by the GPT-6.1 Sol
worker; reviewed by the coordinator.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Registry: re-register the PR-owned files after the recount (last commit)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Hot-file protocol: reset manifests/evidence.json to the merge base before the final hot-file commit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Reapply this branch's manifests/evidence.json edits on the merge base (hot-file protocol: every hot-file edit in the last commit)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* adoption_status: one hold schema for run time and the pins test (cross-family P1)

pin_holds() now keeps only holds that hold_schema_problems() accepts. The same validator is imported by
tests/test_pin_holds.py. It requires the wrapper url and sha256, and the platform package's shape, version,
url, digest and binary check when the pin has one. So a hold with malformed install metadata is ignored,
and the version is reported as drift instead of held. Failing-first: the three missing-field cases failed
before the fix; 16 malformed-metadata cases pass after it.

Built by the GPT-6.1 Sol worker; reviewed by the coordinator (Claude Opus).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Registry: re-register the fix's files (last commit)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Hot-file protocol: reset manifests/evidence.json manifests/stack.json to the merge base before the final hot-file commit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Reapply this branch's manifests/evidence.json manifests/stack.json edits on the merge base (hot-file protocol: every hot-file edit in the last commit)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Scout <scout@local>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant