hermes: judge completion against the assigned task role #22

Manually merged
atlas-reconciler merged 0 commits from feature/hermes-review-goal-semantics into main 2026-08-18 21:28:02 +00:00

Problem

The local goal judge scored every worker report against "did the reviewed implementation reach a shippable state". On live task t_dbdcd739, a read-only independent release reviewer returned status=completed with a BLOCK verdict and twenty reproducible findings, and the judge resumed it turn after turn with an instruction to repair code it was explicitly forbidden to touch. The card burned four continuation turns on subscription capacity before a human stopped it.

Reproduction

repro_review_goal_loop.py replays the exact t_dbdcd739 worker context and result against the live hermes-model-gate judge.

Before (three consecutive runs of the same input):

turn 1: accepted=False reason='The report identifies several critical defects that need to be addressed...'
turn 2: accepted=False reason='The report identifies several critical defects that need to be addressed...'
turn 3: accepted=True  reason='The worker report provides concrete evidence...'

Turns 1-2 match the reason recorded verbatim in the live Kanban comment thread. Turn 3 shows the verdict is also non-deterministic for identical input.

After:

turn 1: accepted=True reason='review deliverable complete: BLOCK verdict with 20 finding(s); task role review resolved by inferred'

That exact context and result are now a committed fixture (testing/tests/data/hermes_t_dbdcd739_*), replayed in CI with the model judge stubbed to raise.

Change

Completion is judged against the action the card assigned.

  • Explicit role contract. Cards declare Hermes-Task-Role: review|implementation or Hermes-Expected-Output: verdict. Directives are read from real newlines and from the literal \n escapes the board stores in one-line bodies - 6 of the 78 live cards carry no real newline at all, including the card that authored this change. Two conflicting directives fall back to the stricter implementation regime.
  • Bounded legacy inference. Pre-contract cards resolve to review only when the card declares a read-only scope, asks for a SHIP/BLOCK-shaped verdict, requests no mutation deliverable, and the report changed no files. Measured on a verbatim snapshot of every live card on three boards: 21 of 78 resolve to review, up from 10, with no implementation card misclassified.
  • Card-scoped resolution. Role resolution reads only the card. The card ends at the first non-card ## heading and at the runner's goal-controller evidence, which is now emitted under its own heading. Prior attempts, parent results, cross-task history, comments and the controller's own rejection history can no longer reassign the role. This was a real defect: without it t_dbdcd739 resolved to implementation because a parent task's summary contained the phrase "the exact pushed SHA".
  • Deterministic review finalization. A review with a truthful SHIP/BLOCK verdict and evidence finalizes with no model call at all. Findings that make the reviewed artifact unfit to ship are the deliverable, not a task blocker.
  • Fail closed on a malformed verdict. Missing, unrecognized or self-contradictory verdict; BLOCK with no findings; a verdict with no findings/tests/artifacts; a summary too short to carry a rationale; blockers alongside completed; a non-completed status. Every rejection reason is prefixed with the read-only guard, so a resumed review is never told to edit the reviewed implementation.
  • Mutation evidence outranks a declaration. A report that changed files never resolves to review, even on a card that declares Hermes-Task-Role: review. It falls back to the model judge.
  • The role reaches the gate. The lane resolves the role from the card and passes it to unfinished_result_reason, and records task_role / task_role_source in the Kanban metadata.
  • Implementation cards are unchanged. Same fail-closed model judge, same unfinished-work heuristic, same judge-unavailable rejection, same goal loop and escalation. A property test asserts the implementation regime is byte-for-byte the gate main d8f2d818 shipped.
  • Bounded, sanitized reasons. Reasons go through the agent runtime's canonical redact_sensitive_text, extended for the two shapes it deliberately passes through and this lane actually handles: scheme://user:secret@host clone URLs and a credential named in prose. Redaction is anchored on surrounding syntax, so a 40-hex commit SHA - indistinguishable from a Gitea PAT in isolation - survives as review evidence. Reasons stay single-line, control-character-free and capped at 600 chars, and nothing mutates the reported result.

Deliberate decisions, stated explicitly

  • Findings-only cards stay on the model judge. A read-only card whose stated DELIVERABLE is a findings list, an observed-state table or a certify/reject recommendation does not infer the review role. The verdict is the review contract's only gate, so inferring it for a card that never asked for a verdict could only fail closed. Those cards should declare Hermes-Task-Role if deterministic finalization is wanted.
  • Single-shot mode gets the same contract as the goal loop. Two single-shot outcomes change against main, deliberately: a completed review whose prose calls the reviewed artifact pending now completes instead of being discarded, and a completed review carrying no usable verdict now blocks instead of completing. A review card's deliverable is its verdict; the lane fails closed rather than record a verdictless review as done.
  • A role-blind caller gets a replay contract, not a weaker classifier. PR #15 re-runs this gate on journalled terminal records without a card. role=None therefore keeps the unfinished-work heuristic - PR #15's integrity check still works - and skips it only for a report that satisfies the whole review contract and changed no files. That is exactly the set the role-aware lane accepts as a review, so a record accepted under one version re-validates under every other instead of being quarantined into a re-dispatch of an already-accepted task.
  • judge_goal_completion now also rejects a non-completed status before reaching the model. Unreachable from the lane, which only calls it inside a status == 'completed' branch, but it is a behaviour change for direct callers.

Verification

  • Full unit suite: PYTHONPATH=. pytest testing/tests -q -> 467 passed, 2 failed. Both failures are the pre-existing test_hermes_auto_router / test_hermes_coordinator failures that reproduce identically on main d8f2d818.
  • Local quality gate at exact baseline parity with main: docs ok, smell ok, hygiene failed, unit failed, coverage ok on both, with the identical four pre-existing >500 LOC files (none touched here) and the identical two unit failures.
  • cli_lane_goal.py at 100% statement and branch coverage (173 stmts, 66 branches), measured both with and without the agent runtime on PYTHONPATH so the canonical-redactor branch and its fallback are each exercised.
  • Every changed and added file under 500 LOC; ruff (F,B,SIM,C4,UP) clean on every lint path.
  • make render exit 0; kustomize build services/hermes exit 0; kubectl apply --server-side --field-manager=kustomize-controller --dry-run=server -> 113 objects, 0 errors.
  • Regression corpus: testing/tests/data/hermes_kanban_card_corpus.jsonl is a verbatim snapshot of all 78 cards on the live titan-iac, cassandra and soteria boards with a hand-labelled expected role per card, asserted one card at a time.
  • Secret scan of the full diff is clean; every credential in the tests is a documented synthetic value and no real credential file was read.

PR #15 merge

git merge-tree against PR #15 head 73fefbb5 conflicts on services/hermes/scripts/cli_lane_runner.py, because PR #15 reduces that file to a re-export shim and moves execute_claim into cli_lane_execution.py. Resolution: take PR #15's cli_lane_runner.py and port this PR's call-site change into cli_lane_execution.py - resolve the role with cli_lane_goal.task_role(context, structured), pass role= to unfinished_result_reason, and emit the controller evidence under cli_lane_goal.CONTROLLER_EVIDENCE_HEADING.

Both resolutions were built and tested:

  • Ported: 690 passed, 4 failed - the identical failure set PR #15 produces alone (test_hermes_auto_router, two test_hermes_cli_evidence_edges retirement tests, test_hermes_coordinator_boards). No new failure.
  • Unported (PR #15's side wins verbatim): the same 4, plus the 4 lane tests in test_hermes_cli_review_roles.py that assert the call-site behaviour. The merge fails loudly rather than silently regressing. Correctness does not depend on the port - the t_dbdcd739 incident is fixed either way, because a role-blind call can no longer reject a complete review deliverable before the role-aware judge runs. What the port restores is the resolved-role metadata and the controller-evidence heading.

Notes for the reviewer

  • The two test_hermes_cli_evidence_edges retirement failures in the merged tree reproduce on PR #15's head alone and are not caused by this merge.
  • The hermes-coordinator ConfigMap exceeds the 256KB last-applied-configuration annotation limit under a legacy client-side kubectl apply. This reproduces identically on main and is pre-existing; Flux's kustomize-controller uses server-side apply, which dry-runs clean.
  • Operational, unrelated to this diff: the reviewer of the previous head ran the runtime redactor over the live /runtime-access/gitea-token and echoed its value into their session output. Rotating that Gitea PAT would be prudent. Nothing in this change reads that file.
  • Draft, for human review. Nothing was merged, built, published, deployed, reconciled, or restarted.

Evidence: /opt/data/workspace/evidence/t_6da029e0/

🤖 Generated with Claude Code

## Problem The local goal judge scored every worker report against *"did the reviewed implementation reach a shippable state"*. On live task `t_dbdcd739`, a read-only independent release reviewer returned `status=completed` with a `BLOCK` verdict and twenty reproducible findings, and the judge resumed it turn after turn with an instruction to repair code it was explicitly forbidden to touch. The card burned four continuation turns on subscription capacity before a human stopped it. ## Reproduction `repro_review_goal_loop.py` replays the exact `t_dbdcd739` worker context and result against the **live** `hermes-model-gate` judge. Before (three consecutive runs of the same input): ``` turn 1: accepted=False reason='The report identifies several critical defects that need to be addressed...' turn 2: accepted=False reason='The report identifies several critical defects that need to be addressed...' turn 3: accepted=True reason='The worker report provides concrete evidence...' ``` Turns 1-2 match the reason recorded verbatim in the live Kanban comment thread. Turn 3 shows the verdict is also non-deterministic for identical input. After: ``` turn 1: accepted=True reason='review deliverable complete: BLOCK verdict with 20 finding(s); task role review resolved by inferred' ``` That exact context and result are now a committed fixture (`testing/tests/data/hermes_t_dbdcd739_*`), replayed in CI with the model judge stubbed to raise. ## Change Completion is judged against the action the card assigned. - **Explicit role contract.** Cards declare `Hermes-Task-Role: review|implementation` or `Hermes-Expected-Output: verdict`. Directives are read from real newlines *and* from the literal `\n` escapes the board stores in one-line bodies - 6 of the 78 live cards carry no real newline at all, including the card that authored this change. Two conflicting directives fall back to the stricter implementation regime. - **Bounded legacy inference.** Pre-contract cards resolve to `review` only when the card declares a read-only scope, asks for a SHIP/BLOCK-shaped verdict, requests no mutation deliverable, and the report changed no files. Measured on a verbatim snapshot of every live card on three boards: **21 of 78 resolve to review, up from 10**, with no implementation card misclassified. - **Card-scoped resolution.** Role resolution reads only the card. The card ends at the first non-card `##` heading and at the runner's goal-controller evidence, which is now emitted under its own heading. Prior attempts, parent results, cross-task history, comments and the controller's own rejection history can no longer reassign the role. This was a real defect: without it `t_dbdcd739` resolved to `implementation` because a *parent task's* summary contained the phrase "the exact pushed SHA". - **Deterministic review finalization.** A review with a truthful `SHIP`/`BLOCK` verdict and evidence finalizes with no model call at all. Findings that make the reviewed artifact unfit to ship are the deliverable, not a task blocker. - **Fail closed on a malformed verdict.** Missing, unrecognized or self-contradictory verdict; `BLOCK` with no findings; a verdict with no findings/tests/artifacts; a summary too short to carry a rationale; blockers alongside `completed`; a non-`completed` status. Every rejection reason is prefixed with the read-only guard, so a resumed review is never told to edit the reviewed implementation. - **Mutation evidence outranks a declaration.** A report that changed files never resolves to `review`, even on a card that declares `Hermes-Task-Role: review`. It falls back to the model judge. - **The role reaches the gate.** The lane resolves the role from the card and passes it to `unfinished_result_reason`, and records `task_role` / `task_role_source` in the Kanban metadata. - **Implementation cards are unchanged.** Same fail-closed model judge, same unfinished-work heuristic, same judge-unavailable rejection, same goal loop and escalation. A property test asserts the implementation regime is byte-for-byte the gate main `d8f2d818` shipped. - **Bounded, sanitized reasons.** Reasons go through the agent runtime's canonical `redact_sensitive_text`, extended for the two shapes it deliberately passes through and this lane actually handles: `scheme://user:secret@host` clone URLs and a credential named in prose. Redaction is anchored on surrounding syntax, so a 40-hex commit SHA - indistinguishable from a Gitea PAT in isolation - survives as review evidence. Reasons stay single-line, control-character-free and capped at 600 chars, and nothing mutates the reported result. ## Deliberate decisions, stated explicitly - **Findings-only cards stay on the model judge.** A read-only card whose stated DELIVERABLE is a findings list, an observed-state table or a certify/reject recommendation does not infer the review role. The verdict is the review contract's only gate, so inferring it for a card that never asked for a verdict could only fail closed. Those cards should declare `Hermes-Task-Role` if deterministic finalization is wanted. - **Single-shot mode gets the same contract as the goal loop.** Two single-shot outcomes change against main, deliberately: a completed review whose prose calls the *reviewed* artifact pending now completes instead of being discarded, and a completed review carrying no usable verdict now blocks instead of completing. A review card's deliverable *is* its verdict; the lane fails closed rather than record a verdictless review as done. - **A role-blind caller gets a replay contract, not a weaker classifier.** PR #15 re-runs this gate on journalled terminal records without a card. `role=None` therefore keeps the unfinished-work heuristic - PR #15's integrity check still works - and skips it only for a report that satisfies the whole review contract and changed no files. That is exactly the set the role-aware lane accepts as a review, so a record accepted under one version re-validates under every other instead of being quarantined into a re-dispatch of an already-accepted task. - **`judge_goal_completion` now also rejects a non-`completed` status** before reaching the model. Unreachable from the lane, which only calls it inside a `status == 'completed'` branch, but it is a behaviour change for direct callers. ## Verification - Full unit suite: `PYTHONPATH=. pytest testing/tests -q` -> 467 passed, 2 failed. Both failures are the pre-existing `test_hermes_auto_router` / `test_hermes_coordinator` failures that reproduce identically on main `d8f2d818`. - Local quality gate at **exact baseline parity** with main: `docs ok, smell ok, hygiene failed, unit failed, coverage ok` on both, with the identical four pre-existing >500 LOC files (none touched here) and the identical two unit failures. - `cli_lane_goal.py` at **100% statement and branch coverage** (173 stmts, 66 branches), measured both with and without the agent runtime on `PYTHONPATH` so the canonical-redactor branch and its fallback are each exercised. - Every changed and added file under 500 LOC; ruff (`F,B,SIM,C4,UP`) clean on every lint path. - `make render` exit 0; `kustomize build services/hermes` exit 0; `kubectl apply --server-side --field-manager=kustomize-controller --dry-run=server` -> 113 objects, 0 errors. - Regression corpus: `testing/tests/data/hermes_kanban_card_corpus.jsonl` is a verbatim snapshot of all 78 cards on the live titan-iac, cassandra and soteria boards with a hand-labelled expected role per card, asserted one card at a time. - Secret scan of the full diff is clean; every credential in the tests is a documented synthetic value and no real credential file was read. ## PR #15 merge `git merge-tree` against PR #15 head `73fefbb5` **conflicts on `services/hermes/scripts/cli_lane_runner.py`**, because PR #15 reduces that file to a re-export shim and moves `execute_claim` into `cli_lane_execution.py`. Resolution: take PR #15's `cli_lane_runner.py` and port this PR's call-site change into `cli_lane_execution.py` - resolve the role with `cli_lane_goal.task_role(context, structured)`, pass `role=` to `unfinished_result_reason`, and emit the controller evidence under `cli_lane_goal.CONTROLLER_EVIDENCE_HEADING`. Both resolutions were built and tested: - **Ported:** 690 passed, 4 failed - the identical failure set PR #15 produces alone (`test_hermes_auto_router`, two `test_hermes_cli_evidence_edges` retirement tests, `test_hermes_coordinator_boards`). No new failure. - **Unported (PR #15's side wins verbatim):** the same 4, plus the 4 lane tests in `test_hermes_cli_review_roles.py` that assert the call-site behaviour. The merge fails loudly rather than silently regressing. Correctness does not depend on the port - the `t_dbdcd739` incident is fixed either way, because a role-blind call can no longer reject a complete review deliverable before the role-aware judge runs. What the port restores is the resolved-role metadata and the controller-evidence heading. ## Notes for the reviewer - The two `test_hermes_cli_evidence_edges` retirement failures in the merged tree reproduce on PR #15's head **alone** and are not caused by this merge. - The `hermes-coordinator` ConfigMap exceeds the 256KB `last-applied-configuration` annotation limit under a legacy client-side `kubectl apply`. This reproduces identically on main and is pre-existing; Flux's kustomize-controller uses server-side apply, which dry-runs clean. - Operational, unrelated to this diff: the reviewer of the previous head ran the runtime redactor over the live `/runtime-access/gitea-token` and echoed its value into their session output. Rotating that Gitea PAT would be prudent. Nothing in this change reads that file. - Draft, for human review. Nothing was merged, built, published, deployed, reconciled, or restarted. Evidence: `/opt/data/workspace/evidence/t_6da029e0/` 🤖 Generated with [Claude Code](https://claude.com/claude-code)
hermes-automation added 1 commit 2026-08-17 14:56:24 +00:00
The local goal judge scored every worker report against "did the reviewed
implementation reach a shippable state". A read-only reviewer that returned a
completed BLOCK verdict with findings was therefore resumed turn after turn with
an instruction to repair code it was forbidden to touch (observed live on
t_dbdcd739), burning subscription capacity and risking an unbounded loop.

Completion is now judged against the action the card assigned:

* Cards declare their role explicitly with Hermes-Task-Role / Hermes-Expected-
  Output metadata. Pre-contract cards fall back to a narrow inference that needs
  a read-only scope, a requested verdict, no requested mutation deliverable, and
  a report that changed no files.
* Role resolution reads only the card itself. Prior attempts, parent results,
  cross-task history and comments appended to the worker context can no longer
  reassign the role.
* Review, audit and diagnostic cards finalize deterministically on a truthful
  SHIP or BLOCK verdict with evidence, and fail closed on a missing,
  unrecognized or self-contradictory verdict, on a BLOCK without findings, and
  on a verdict without evidence. Every rejection reason carries the read-only
  guard, so a resumed review is never told to edit the reviewed implementation.
* Implementation cards keep the fail-closed model judge unchanged, including the
  unfinished-work heuristic and judge-unavailable rejection.
* All judge reasons are bounded, single-line and secret-redacted before they
  reach Kanban metadata, comments and continuation prompts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
hermes-automation changed title from hermes: finalize completed review verdicts in the goal judge to WIP: hermes: finalize completed review verdicts in the goal judge 2026-08-17 14:56:32 +00:00
hermes-automation added 1 commit 2026-08-17 17:30:15 +00:00
Repairs the blockers from the independent review of the previous head. The
role-aware verdict contract was correct but reachable only through one call
site and only on cards written with real newlines, so most real review cards
never used it.

* The role-blind call is no longer a weaker classifier that can reject before
  the role-aware judge runs. Without a card there is no defensible
  role-dependent judgement, so `unfinished_result_reason()` applies only the
  card-independent checks. That closes the short-circuit at every call site,
  including the one PR15 moves to `cli_lane_execution`, and it makes a
  journalled terminal record accepted under one version of these semantics
  re-validate under any other instead of being quarantined into a re-dispatch
  of an already-accepted task.
* The lane resolves the role from the card and passes it, and records it in
  the Kanban metadata. The verdict contract binds only where the lane can buy
  another turn: in single-shot mode a rejection discards the worker's real
  result, so review cards keep the relaxation without gaining any rejection
  single-shot mode did not already have.
* Card scope expands the literal \n escapes the board stores in one-line
  bodies, so explicit `Hermes-Task-Role` / `Hermes-Expected-Output` directives
  are honoured on the 6 of 78 live cards that carry no real newline, and the
  read-only, verdict and mutation heuristics stop being cut apart by them.
* Card scope now ends at the first non-card H2 and at the runner's controller
  evidence, which is emitted under its own heading. Goal-controller rejection
  history can no longer sit inside the card, and an upstream heading rename
  fails closed instead of admitting history into role resolution.
* The inference recognises the SHIP/BLOCK-shaped deliverables real cards
  actually use: 21 of 78 live cards resolve to review, up from 10, with no
  implementation card misclassified. Cards asking for a findings list rather
  than a verdict deliberately stay on the model judge, since the verdict is
  the review contract's only gate.
* A declared review role no longer outranks mutation evidence: a report that
  changed files falls back to the implementation regime.
* Judge reasons go through the agent runtime's canonical redactor, extended
  for the two shapes it deliberately passes through and this lane handles -
  `scheme://user:secret@host` and a credential named in prose - while a 40-hex
  commit SHA survives as evidence.

Regressions cover the recovered t_dbdcd739 incident, a verbatim snapshot of
every live card on three boards with a hand-labelled expected role, the
upgrade and single-shot properties against the previous gate, the upstream
context-heading contract, and the end-to-end `execute_claim` shape that used
to burn every goal turn.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
hermes-automation changed title from WIP: hermes: finalize completed review verdicts in the goal judge to WIP: hermes: judge completion against the assigned task role 2026-08-17 17:31:20 +00:00
bstein changed title from WIP: hermes: judge completion against the assigned task role to hermes: judge completion against the assigned task role 2026-08-18 04:05:18 +00:00
bstein added 16 commits 2026-08-18 04:19:12 +00:00
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add kanban routing keys (provider_quota_min_remaining_percent: 15,
provider_capacity_cooldown_seconds: 300, provider_auth_cooldown_seconds:
3600), a lane-metrics port/Service on 9011 with service-annotation
scraping, monitoring ingress for the new port, and the lane's quota
metrics URL env. Based on PR #15 (fix/hermes-result-decomposition-
reliability); stacked because this work rides on the decomposed lane.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Based on PR #15 (fix/hermes-result-decomposition-reliability); stacked
on the decomposed cli_lane modules.

- cli_lane_quota: soft-exclude a provider from NEW cli-auto work below
  the remaining-quota threshold (both-below prefers more remaining;
  fetch failure fails open with a metric).
- cli_lane_health: lane now writes provider health (G7) with classified
  failure reasons splitting the capacity conflation (quota/auth/
  rate-limit/transport) and cooldown hysteresis; re-admission only on
  full cooldown expiry, passed quota reset, or fresh success (G4).
- cli_lane_routing: capacity-limited health now excludes a provider
  (G3); cooldown/reset-aware re-admission.
- cli_lane_failover: explicit cli-codex-*/cli-claude-* assignees fail
  closed as transient instead of switching providers (G5); fallback
  depth stays bounded at two hosted providers (G1) with effort
  preserved; Switchyard outages block transient, not capability (G9).
- cli_lane_metrics: route-decision/fallback counters, quota and
  soft-exclusion gauges, pod-local scrape server (G6).
- cli_lane_provider: worker env drops ANTHROPIC_API_KEY, CLAUDE_API_KEY,
  OPENAI_API_KEY, API_SERVER_KEY so no metered path exists (G10).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Deterministic coverage for the quota-aware lane: threshold boundaries
(14.9/15/15.1), both-below preference, fetch-failure fail-open, cooldown
elapsed-vs-not hysteresis, quota-reset recovery (never for auth),
explicit fail-closed in both directions, bounded double-failure block,
failure-reason classification, metrics emission, and worker env key
stripping. Based on PR #15 (fix/hermes-result-decomposition-reliability).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CAPACITY_PATTERN (the gate that sets result.capacity_failure) lacked the
bare unauthorized/forbidden/401/403 signals that classify_capacity_failure
already recognizes, so an auth blip surfacing only as "403 Forbidden"
was blocked as capability instead of transient: no auto failover, no
health cooldown. Add 401|403|unauthorized|forbidden to the gate so it
matches the classifier; reason classification still distinguishes auth
from quota/rate-limit/transport.

Tests: an auto card failing with only "403 Forbidden" now fails over to
the other provider, records an auth cooldown (authenticated:false), and
classifies the fallback reason as auth in metrics; a manual card with the
same failure still fails closed as transient. Router-outage tests moved to
test_hermes_cli_router_outage.py to keep both files <500 LOC.

Based on PR #15 (fix/hermes-result-decomposition-reliability).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reconcile two independent test/gate reorganizations:
- Gate/semgrep/mailu: keep main's #16 dual-metric implementation.
- quality_contract.json: union #16 image-builder + #14 scm/node + #15 cli_lane.
- agent-deployment.yaml: keep #14 gitea removal + #16 image-build-token + #15 probe.
- Test splits: main's chat/coordinator/agent organization is authoritative;
  drop #15's redundant competing splits and #14's stale cli-lane duplicates;
  keep #15's cli-lane decomposition suite and port the execution-safety test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	services/hermes/networkpolicy.yaml
#	testing/quality_contract.json
#	testing/tests/test_hermes_agent_security.py
# Conflicts:
#	services/hermes/scripts/cli_lane_runner.py
atlas-reconciler manually merged commit 1c4ed3af93 into main 2026-08-18 21:28:02 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: titan/atlas-iac#22
No description provided.