Skip to content

build-gate: per-node verify stage, rebased onto main (supersedes #192) - #195

Merged
dsmcewan merged 4 commits into
mainfrom
claude/telos-verify-stage-rebased
Sep 24, 2026
Merged

dsmcewan merged 4 commits into
mainfrom
claude/telos-verify-stage-rebased

Conversation

@dsmcewan

Copy link
Copy Markdown
Owner

Summary

This is PR #192 (claude/telos-verify-stage) rebased onto current main, opened on a fresh branch because #192's branch could not be force-updated from this session. It carries the same change — the per-node verify stage for the autonomous builder — with the merge conflicts against main's proposal-lifecycle work resolved and CI-relevant checks green locally.

Supersedes #192. Once this is reviewed, #192 can be closed (or its branch force-updated to this commit if you prefer to keep that PR number).

Why a rebase was needed

#192 forked well before current main and carried stale build-gate copies, so it showed mergeable_state: dirty (conflict) and CI never ran. Its two commits (WIP + finish) are replayed here as one clean commit on top of main.

Conflict resolutions (keep-both throughout)

The verify stage is a blocking-only scrutiny layer; Rule 3 / defaultVerifyNode stays the sole settle authority. Nothing here weakens a fail-closed guarantee.

  • build-orchestrator.mjs — keep main's runProposalLifecycle import + lifecycle delegation; merge in the branch's reverifyRecord import, readArtifactFiles, runVerify, and verify-team routing. buildProject's parameters are the union of both sides (callWorkshopSeat/callParallelSeat/nowMs/maxRevisions + callVerify/requireVerify).
  • schemas.mjs — keep DAEDALUS_RESPONSE_SCHEMA / PROPOSAL_REVIEW_PACKET_SCHEMA / EVIDENCE_CLAIM_SCHEMA; add VERDICT_SCHEMA; SCHEMAS registry gains verdict.
  • teamPrompts.mjs — keep main's prompts.json refactor (drop the removed PACKET_INSTRUCTION); add promptForVerify / verifyPrompt / parseVerdict / makeLiveCallVerify.
  • package.json — keep main's full check/test script list; add test-verify-stage.
  • scripts/test-verify-stage.mjs — the one substantive follow-on: the keyless test dossier now opts into trust_mode: "advisory", because main's gate is signed-by-default (an absent trust_mode would block at approval). This matches test-build-orchestrator.mjs and keeps the test focused on the verify stage, not gate signing.

Verification (Node 22.22.2, on the rebased tree)

  • cd build-gate && npm test → exit 0 (includes test-verify-stage 6/6 and breakout)
  • cd merkle-dag && npm test → exit 0
  • node docs/institutional-memory/verify-contracts.mjs → 313/313 contracts match
  • node .github/scripts/check-portable-paths.mjs → 0 violations

Governance note

This touches trust-spine code, so merge remains The Eye's decision. This PR only replays already-authored work onto main and resolves conflicts; it adds no new scope. Left as draft, no merge.

🤖 Generated with Claude Code

https://claude.ai/code/session_013rxfYqddLk2NykrPkjy1Pr


Generated by Claude Code

Rebase of PR #192 (claude/telos-verify-stage) onto current main. The branch
had forked well before main and carried stale build-gate copies; this replays
its two commits (WIP + finish) as one clean commit on top of main and resolves
the conflicts against main's proposal-lifecycle work.

Conflict resolutions (keep-both throughout — the verify stage adds a blocking-only
scrutiny layer; Rule 3 / defaultVerifyNode stays the sole settle authority):
- build-orchestrator.mjs: keep main's runProposalLifecycle import + lifecycle
  delegation and merge in the branch's reverifyRecord import, readArtifactFiles,
  runVerify, and the verify-team routing; buildProject's params are the union of
  both (callWorkshopSeat/callParallelSeat/nowMs/maxRevisions + callVerify/requireVerify).
- schemas.mjs: keep DAEDALUS_RESPONSE/PROPOSAL_REVIEW_PACKET/EVIDENCE_CLAIM and add
  VERDICT_SCHEMA; SCHEMAS registry gains `verdict`.
- teamPrompts.mjs: keep main's prompts.json refactor (drop the removed
  PACKET_INSTRUCTION) and add promptForVerify/verifyPrompt/parseVerdict/makeLiveCallVerify.
- package.json: keep main's full check/test script list, add test-verify-stage.
- test-verify-stage.mjs: opt the keyless dossier into trust_mode "advisory" (main's
  gate is signed-by-default now), matching test-build-orchestrator.mjs.

Verification (Node 22.22.2, on the rebased tree):
- cd build-gate && npm test -> exit 0 (includes test-verify-stage 6/6 and breakout)
- cd merkle-dag && npm test -> exit 0
- node docs/institutional-memory/verify-contracts.mjs -> 313/313 contracts match
- node .github/scripts/check-portable-paths.mjs -> 0 violations

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013rxfYqddLk2NykrPkjy1Pr

dsmcewan commented Sep 24, 2026 •

Copy link
Copy Markdown
Owner Author

CI status: review check failing — not this PR's diff

Correction (see @dsmcewan's follow-up below): my original root-cause here was wrong. The review workflow does not use ANTHROPIC_API_KEY — it passes secrets.CLAUDE_CODE_OAUTH_TOKEN to anthropics/claude-code-action (code-review.yml line 68). The empty ANTHROPIC_API_KEY I quoted from the job's env group is an unused default var, not the credential the action reads. The OAuth token exists and was supplied (masked); the failure is that the first Claude turn returned is_error:true (zero cost, empty modelUsage) — a provider-side error on the credential (possibly expired/rejected — last updated Jul 30 — or an entitlement/limit), not a missing secret. Remedy: mint a fresh token with claude setup-token, update the CLAUDE_CODE_OAUTH_TOKEN repo secret, then re-run the failed job. The corrected diagnosis and the accurate parts below both stand; strike the "add ANTHROPIC_API_KEY" remedy.


Every functional check is green on the current head (689bcfd): required CI, all package/suite jobs (build-gate, merkle-dag, breakout, clotho, forge, saas-forge, ai-forge, ai-native-memory, lachesis, atropos, demo, connectors/ai-peer-mcp, narcissus flagship), plus institutional-memory (records == reality), fail-closed proof, workflow scripts (hestia ship gate), and portable-paths.

The only failing check is the non-required review job (the anthropics/claude-code-action reviewer), which failed for the credential reason described in the correction above — a repo-level issue that hits every PR (it fails identically on the unrelated, docs-only #194), not anything in this diff. No code change in this PR can resolve it.

This PR is otherwise green and mergeable pending review/approval. A manual code review has been posted separately on this PR to stand in for the automated one until the token is refreshed.

@dsmcewan dsmcewan mentioned this pull request Sep 24, 2026
5 tasks

Copy link
Copy Markdown
Owner Author

Manual code review (the automated review job can't run — no ANTHROPIC_API_KEY)

Scope: git diff main...HEAD (the 6 build-gate/ files). These findings are about the verify-stage design carried over from #192 — the rebase preserved that logic faithfully, so none were introduced by the conflict resolution. CI is green and VERDICT_SCHEMA is strict-mode-clean.

Mitigating context up front: the verify stage is blocking-only — Rule 3 / defaultVerifyNode stays the sole settle authority, so no bad verdict can approve a node past disk truth. The concerns below are that the advertised requireVerify strictness and independence don't fully hold.

🔴 The requireVerify fail-closed guarantee doesn't hold

  1. teamPrompts.mjs (parseVerdict/makeLiveCallVerify) — live requireVerify fails open. parseVerdict is fail-soft: unparseable/error text becomes {ok:true, blockers:[], checks:[]}. A keyless/misconfigured verify seat in production returns text, it does not throw (per this module's own note that a missing key yields a provenance-less response), so runVerify never reaches its {error:true} branch and requireVerify never fires. A run with require_verify:true and a broken verify seat settles every node as if verified. The unit test masks this by using a mock that throws instead of returning text.

  2. build-orchestrator.mjs (makeTeamDispatch, if (callVerify && verifyTeamFor)) — requireVerify is silently ignored when no callVerify is wired. Set dossier.require_verify:true but omit callVerify (easy for non-live integrations) and the whole verify block is skipped with no error — an explicit "verification required" produces zero verification.

🟠 Weakens the stated premise

  1. teams.mjs (verifyTeamForNode) — a node's builder can be its own verifier for workstream-owning verify teams (e.g. security-trust → the security team both builds and verifies), defeating "never self-certify" exactly where a dedicated verifier exists.

  2. build-orchestrator.mjs (runVerify, if (checks.length > 0)) — fact-grounding is vacuous when the verifier omits checks. {ok:true, checks:[]} is never grounded against disk, so "the model can't bluff ok" overstates what's enforced for a lazy/adversarial verifier (blocking-only still contains the blast radius).

  3. teamPrompts.mjs (makeLiveCallVerify) — the verdict is trusted with no provenance check, unlike every other seat call (which fail closed on missing provenance). Blocking-only contains the damage, but combined with docs: mark TELOS Codex merge complete #1/Add Claude Code GitHub Actions workflow #2 the verify layer provides no authenticated signal.

🟡 Minor

  1. build-orchestrator.mjs (runVerify) — requireVerify is passed at the call site but not destructured/used (dead arg; the decision lives in the dispatch). Harmless, but misleading for future maintainers.

Suggested disposition


Generated by Claude Code

@dsmcewan

Copy link
Copy Markdown
Owner Author

Correction to the earlier CI diagnosis: the review workflow does not use ANTHROPIC_API_KEY. It deliberately passes the repository's CLAUDE_CODE_OAUTH_TOKEN to anthropics/claude-code-action. GitHub confirms that secret exists, and the failing run shows it was supplied (masked), the pinned plugin installed, and Claude Code initialized. The first Claude turn then returned is_error:true with zero cost and empty modelUsage; no automated review occurred.

The public log does not reveal whether the OAuth credential was rejected, an account entitlement/limit intervened, or another provider-side error occurred. The secret was last updated July 30. A fresh OAuth credential is the next useful test, followed by one rerun of the failed job. Please do not treat green package CI or the failed review check as a completed code review.

Evidence: failing run, code-review.yml on main.

@dsmcewan

Copy link
Copy Markdown
Owner Author

Patch on c44e53f addresses the concrete requireVerify fail-open paths from the manual review:

  • A missing verify callback/team route now blocks before team files are written when verification is required.
  • Error text, error envelopes, incomplete JSON, and malformed injected verdicts are treated as unusable responses. Required verification blocks; advisory verification retains its prior skip behavior.
  • The proposal-lifecycle build path now passes through the verify callback and requirement, so it cannot silently skip the stage. The unused requireVerify argument to runVerify is removed.

Evidence: targeted tests cover missing callback, live error text, malformed object, and lifecycle blocking. The full build-gate test script (including breakout) passed locally with Linux Node/npm; institutional contracts matched 313/313; portable paths reported 0 violations. CI on this exact commit passed.

The separate automated review run still failed before model work (is_error:true, zero cost, empty modelUsage) with CLAUDE_CODE_OAUTH_TOKEN present. No automated review was produced. The design questions about verifier independence, empty declarative checks, and provenance from the earlier manual review remain open; this patch does not claim to resolve them.

@dsmcewan

Copy link
Copy Markdown
Owner Author

Repair status at c85e161

  • The required-verification fail-open paths were patched in c44e53f. Package tests, contract verification (313/313), and the full GitHub CI matrix passed.
  • Refreshed the repository's CLAUDE_CODE_OAUTH_TOKEN secret from Claude's existing authenticated login. The review job rerun on c44e53f successfully authenticated and used Claude (is_error: false, four turns): https://github.com/dsmcewan/TELOS/actions/runs/35952335132 .
  • The pinned review plugin explicitly skips draft PRs. This PR remains draft, so that successful run did not produce a review verdict. Commit c85e161 changes the workflow to show the review check as skipped while draft and to run it on ready_for_review (also on reopen). The latest CI run passed: https://github.com/dsmcewan/TELOS/actions/runs/35952992184 .

The design-level questions in the manual review (verifier independence, empty checks, and provenance) are still open. No automated review verdict or merge approval is claimed for this draft.

Bring the per-node verify stage up to date with main (079e77e), which now
carries #193 (repo code trace + keyless evidence fixes), #196 (gate verdict
surfacing + runBuild refusals as phased results, F1/F5), and #194 (trace docs).
build-orchestrator.mjs auto-merges cleanly: the verify-stage changes and the
F1/F5 changes touch different regions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013rxfYqddLk2NykrPkjy1Pr
@dsmcewan
dsmcewan marked this pull request as ready for review September 24, 2026 14:57
@dsmcewan
dsmcewan merged commit fd0e2cf into main Sep 24, 2026
33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants