Commit Graph

72 Commits

Author SHA1 Message Date
Paul O'Reilly
7244e0ec5f fix(minimax-m3-max, fable-low-effort): H-SECRET-4 rejected MAX_THINKING_TOKENS in env
The validator pattern-matches *TOKEN* as credential-shaped and rejected
both contexts, failing every task on the new harnesses. The env var name
is fixed by Claude Code, so deliver the thinking budget via the
settings.json env map in init.sh instead (jq-merge preserves apiKeyHelper
from the minimax/oauth layer).

Claude-Session: https://claude.ai/code/session_019tJk7P8tZzJ24PvtgoGhLN
2026-09-03 00:39:59 +12:00
Paul O'Reilly
2fa4dc92c2 pipeline model routing: mechanical stages to MiniMax M3, spec stages to Fable low effort
- scaffolding-repo + test-writing-repo: anthropic-cloud-paul-oauth -> minimax + minimax-m3-max
- merge@1: new best-practices-minimax-repo composite (impl-review stays Sonnet)
- spec-draft-opus@1: Opus -> Fable 5 low effort via new fable-low-effort/v1
  env context (ANTHROPIC_MODEL=claude-fable-5, MAX_THINKING_TOKENS=1024) +
  spec-writing-fable-low-repo composite
- review-spec-arch-opus@1: Qwen3.6/airouter -> Fable 5 low effort via
  best-practices-fable-low-repo (arch review was on the cheapest model)

Template names kept (trigger rules reference them). Node model: fields
removed where env pins the model — a --model flag overrides ANTHROPIC_MODEL.

Claude-Session: https://claude.ai/code/session_019tJk7P8tZzJ24PvtgoGhLN
2026-09-02 21:43:23 +12:00
Paul O'Reilly
4201b1ac3a integration-direct: route to MiniMax M3 max-effort instead of Anthropic OAuth
Integration runs were burning the personal Anthropic 5-hour window
(429 storm + window drain, 2026-09-02). New env-only context
minimax-m3-max/v1 pins ANTHROPIC_MODEL=MiniMax-M3[1m], maxes the
thinking budget, and sets the 1M auto-compact window; layered on
minimax/v1 for base URL + apiKeyHelper auth.

Claude-Session: https://claude.ai/code/session_019tJk7P8tZzJ24PvtgoGhLN
2026-09-02 21:33:50 +12:00
Paul O'Reilly
e89208f44b fix(templates): per-item branches for concept-stage nodes (was shared spec/auto-draft)
All 6 concept/idea-stage templates hardcoded the literal shared branch
spec/auto-draft instead of a per-item branch. Concurrent concept items
(now routine via the M41 auto-advance sweep) all pushed to the same
branch — a git collision risk. Switched to spec/${item.uuid}, matching
the established task/${item.uuid} convention used by every task-stage
template (merge@1, scaffold@1, etc — see spec/typed-workflows.md WF-COMP
stable-per-item-branch rationale). spec-review-loop@1's 4 nodes keep the
literal branch shared ACROSS the node set (now per-item, not global) so
loop iterations still accumulate on one branch per item, per spec's
cross-iteration-artifact caveat.

Files: review-spec-arch-opus@1.yaml, spec-draft-opus@1.yaml,
spec-review-loop@1.yaml, review-spec-arch-airouter@1.yaml,
spec-draft-airouter@2.yaml, scope-decompose-sonnet@1.yaml
2026-09-01 02:11:20 +12:00
Paul O'Reilly
e0d3a60279 fix(templates): spec-draft-opus@1 route to Opus, not airouter/Qwen3.6
Was silently dispatching to Qwen3.6 via airouter despite the name;
live runs were timing out (exit_code=124), wedging four M41 auto-advance
concepts. Mirrors agent-runtimes commit acc5cbe5.

Claude-Session: https://claude.ai/code/session_012arAwUuBQrpnMzJ36mEVBk
2026-09-01 00:37:52 +12:00
Paul O'Reilly
fefc8846c3 templates: reference triggers.yaml with WT-ADV safe defaults (M41)
version: 2 + auto_advance default deny — imported projects are inert until
a human applies a grant tag (spec/workflow-triggers.md §3b WT-ADV-8).

Claude-Session: https://claude.ai/code/session_012arAwUuBQrpnMzJ36mEVBk
2026-08-30 02:56:03 +12:00
Paul O'Reilly
73acc6a11d feat(best-practices): pointer CLAUDE.md so agents know the library exists
The 237KB library was mounted at /workspace/best-practices/ in every
consuming ConfigMap but nothing in the prompt mentioned it (directory
targets never enter the context manifest). New ~90-word CLAUDE.md file
target enters the system prompt: points at INDEX.md, instructs reading
only task-relevant topics.

Claude-Session: https://claude.ac/code/session_012arAwUuBQrpnMzJ36mEVBk
2026-08-19 09:34:31 +12:00
Paul O'Reilly
1ce42a9e59 fix(harness): resolve layer contradictions + context-budget caps for airouter TDD
- tdd-gate: pass criterion is the task's TEST_FILES scope (matches
  run-ci-tests.sh M19 P-14), not the full suite — contradicted
  qwen-code-methodology rule 5 in the same system prompt
- tdd-protect: tests/ path described relative to project working dir
  (AGENT_WORKING_DIR is /workspace/project in repo composites)
- qwen-code-methodology: task_complete tool DOES exist — rule 8 said
  the opposite; pytest examples use -q
- airouter-code-tdd template: TT-39 runtime_overrides
  (max_result_bytes 24KB, max_history_turns 16)

Claude-Session: https://claude.ai/code/session_012arAwUuBQrpnMzJ36mEVBk
2026-08-19 09:10:22 +12:00
Paul O'Reilly
76a7277961 fix(decompose-template): replace inline python3 -c paste with cp-cli decompose verb
The python3 -c block imported internal entrypoint code directly and
pasted module paths into agent prompts — a security boundary violation.
Switch to the thin-client verb (added in agent-runtimes a116aedb).

Claude-Session: https://claude.ai/code/session_0124mK2BVfCdkELLXDCr5Zzs
2026-08-17 10:11:22 +12:00
Paul O'Reilly
18a702d7a0 fix(integration-direct/v1): add missing agent-repo/v1 layer
All tasks dispatched to integration-direct/v1 were failing with
harness_missing_agent_repo_layer because dispatcher DSP-1 guard
requires agent-repo in the composite when AGENT_REPO_URL is set.

direct-push/v1 sets env vars (AGENT_SKIP_BRANCH_PUSH,
AGENT_EMPTY_DELIVERABLE_CHECK) that configure agent-repo's finalize.sh,
so agent-repo/v1 must precede it in the layer list.
2026-08-01 00:17:37 +12:00
Paul O'Reilly
b5f039f73f fix(workflows): use artifacts.item_body not metadata.task_description
metadata.task_description is not in the consumer snapshot — the trigger
consumer only populates metadata.automation from the outbox typed_payload.

artifacts.item_body IS populated via dispatch_service from
item_snapshot["body"] (set from typed_payload.body in the consumer,
which comes from item.get("body") in emit_work_item_event).

For M39 items the body contains the full task description, so
${artifacts.item_body} gives the agent complete implementation instructions.
2026-07-31 10:44:14 +12:00
Paul O'Reilly
fc27ffe170 fix(workflows): airouter-impl-ready prompt was producing empty task descriptions
${metadata.automation.test_files} and ${metadata.automation.spec_ids} are
absent from M39 work items (created from dashboard without these fields),
resulting in an empty, useless prompt:
  "Implement the failing test. Test files: . Spec IDs: ."

Switch to ${metadata.task_description} — a sibling metadata key (not under
automation, so write-protected path does not apply) — populated by patching
items with their body text. The _TriggerItemView in dispatch_service.py
correctly exposes item.metadata so this resolves at compile time.

All 16 scaffolded M39 items patched with metadata.task_description via CP API.
2026-07-31 10:40:34 +12:00
Paul O'Reilly
d06a526256 feat(templates): sync 4 workflow templates from agent-runtimes
Add direct-impl-sonnet@1, plan-review-loop@1, spec-review-loop@1,
test-write-review-loop@1 — present in agent-runtimes but missing here.
These are needed before agent-runtimes drops its baked-in copies and the
CP loads workflow templates exclusively from this CRS repo.
2026-07-29 09:09:52 +12:00
Paul O'Reilly
350c0eeed4 feat(templates): 6-tier escalation ladder — add MiniMax + Fable tiers
New tiers in the coding queue:
  airouter(0-2) → minimax(3-5) → sonnet(6-7) → opus(8-9) → fable(10) → blocked(11+)

- models/claude-fable-5.yaml: Fable 5 model definition (Anthropic cloud, claude runner)
- harnesses/composites/code-fable-tdd-repo/v1: Fable TDD composite (mirrors opus, anthropic-cloud-paul-oauth auth)
- model-registry/harness-roles.yaml: claude-fable-5 → code-fable-tdd-repo under code-tdd role
- model-registry/tiers.yaml: claude-fable-5 added to coding.qualifies_today
- task-templates/workflow/minimax-impl-ready@1.yaml: MiniMax TDD workflow (scope: 3 files / 200 lines / 30m)
- task-templates/workflow/fable-impl-ready@1.yaml: Fable TDD workflow (scope: 5 files / 400 lines / 60m)

Claude-Session: https://claude.ai/code/session_015sCpoFee3LsLKbHQ4FRRWY
2026-07-29 01:59:54 +12:00
Paul O'Reilly
a12f6ddaba feat(templates): tiered escalation ladder — remove airouter-eligible gate
Remove `tags_required: [airouter-eligible]` from airouter-impl-ready so all
non-skip tasks route through the full airouter→sonnet→opus ladder automatically.
Add `airouter-skip` to airouter's tags_forbidden so opt-out tasks go directly
to sonnet from attempt 0.

Relax sonnet-impl-ready tags_forbidden (drop multi-file + algorithmic-large)
so sonnet handles complex tasks at escalation tier without template rejection.

Add opus-impl-ready@1.yaml — last-resort escalation, code-opus-tdd-repo
composite, scope_budget 5 files / 400 lines / 3600s.
2026-07-29 01:32:24 +12:00
Paul O'Reilly
2c1ec7d52c fix: update MiniMax harness base URL to api.minimaxi.chat
MiniMax moved their Anthropic-compatible API from api.minimax.io to
api.minimaxi.chat. Update ANTHROPIC_BASE_URL in the minimax/v1 context
harness and corresponding comments in init.sh and the TODO note.

Model routing is unaffected: the API defaults unrecognised model names
(e.g. "minimax" from the registry slug) to MiniMax-M3 already.

Claude-Session: https://claude.ai/code/session_01XtWRazqRbMnMRa4iV3zbVx
2026-07-17 22:55:47 +12:00
Paul O'Reilly
1da98eb708 Add model-registry/harness-roles.yaml — W3 harness auto-selection role table 2026-07-12 23:17:07 +12:00
Paul O'Reilly
78229c5dba feat(routing): add tiers.yaml + rename spec/review-arch templates to airouter
W1 stage-routing work:
- model-registry/tiers.yaml: defines planning/spec-test/coding tier floors
  (complexity≥9/creativity≥9/context≥9 | spec_adherence≥9/test_pass_rate≥9 |
  spec_adherence≥7/test_pass_rate≥7) with qualifies_today lists
- spec-draft-airouter@2.yaml: honest name for what was spec-draft-opus@1
  (always ran Qwen3.6/airouter, not Opus)
- review-spec-arch-airouter@1.yaml: honest name for review-spec-arch-opus@1

Old @1 files kept for in-flight task backward-compatibility.

Claude-Session: https://claude.ai/code/session_01B35bPAKv5uyW1F9gzMcRN7
2026-07-12 19:03:51 +12:00
Paul O'Reilly
681f0ce4fa fix(hugo-content-workspace): never commit .agent-output/ runner scratch — was creating junk content commits + spurious CI rebuilds on every AI task 2026-07-07 16:56:24 +12:00
Paul O'Reilly
ae4c8c29f8 fix(gitea-ssh-accelerators): ESO mounts the key as private_key, not id_ed25519 — matches gitea-ssh/v1 and the acct secret's data keys 2026-07-07 11:17:52 +12:00
Paul O'Reilly
10df741c4a fix(hugo-content-workspace): requires: [] — resolver treats requires as harness refs, git-access capability name crashed composition 2026-07-07 11:10:35 +12:00
Paul O'Reilly
d1dcdf4a8c fix: per-item work branch (task/${item.uuid}) across all task-stage templates 2026-07-04 19:37:03 +12:00
Paul O'Reilly
4b39c9822f fix: impl-review + merge on Sonnet/best-practices-opus-repo (unclaimable routing + empty-delivery risk) 2026-07-04 18:50:57 +12:00
Paul O'Reilly
01fb6f3ad0 fix: scope-decompose claude cli + AR-38 audit off (API-side-effect deliverable) 2026-07-04 15:19:32 +12:00
Paul O'Reilly
b1ad85f46d fix: scope-decompose-sonnet runs model:sonnet on spec-writing-sonnet-repo (was Qwen3.6/airouter — empty-delivery in E1 E2E) 2026-07-04 14:09:24 +12:00
Paul O'Reilly
71f9cc0338 feat(airouter): DeepSeek V4 Flash TDD composite + max-effort template
New code-airouter-deepseekv4flash-tdd-repo/v1 composite (deepseek
methodology + the same tdd-protect/tdd-gate/python-dev/tdd-file-lock
layers as the Qwen TDD composite), plus a task-template that sets
reasoning_effort=max via the new extra_body passthrough (agent-runtimes
TT-38). Model/endpoint/model-registry entries already existed; only
the TDD-capable harness and the template were missing.
2026-07-03 12:36:43 +12:00
Paul O'Reilly
dab3db3727 fix(best-practices): restore canonical content, dedupe, sync script, spec exemplar
- best-practices/v1: replace 9 stale symlinks (into planning/v1) with real files
  synced byte-identical from the canonical best-practices project; add INDEX.md,
  scripting.md, mechanical-test-generation.md (canonical had drifted heavily,
  e.g. api-design.md 463->807 lines)
- planning/v1: delete duplicated best-practices/ copy (requires: inheritance
  confirmed via spec/harness.md HC-1/HC-7)
- scripts/sync-best-practices.sh: idempotent re-sync from canonical checkout
- code-methodology/v1: INDEX.md + scripting.md references now resolve; point
  test-writing tasks at mechanical-test-generation.md
- spec-writing/v1: worked spec exemplar (module layout table, Why: lines, exact
  error messages, parametrize pattern table) + CLAUDE.md pointer + mount entry
2026-07-02 21:27:43 +12:00
Paul O'Reilly
97d98689be feat(templates): add missing escalation targets + concept-intake stage
fix-test-fixture-sonnet@1, review-spec-opus@1, replan-spec-opus@1 — the
dangling escalation refs from airouter-impl-*/spec-draft/feature-delivery-loop.
Sonnet-authored, Opus-reviewed; review HIGH fixes applied (explicit model: opus
on both opus nodes — node model: sets runtime model, composite name does not).
Known gap filed in work-items epic (E1-escalation-state-gap.md): escalation
edges from non-primary states 422 state_mismatch pending escalation_input_states.
concept-intake@1: optional idea-elaboration pre-stage (output state
idea-elaborated — not yet wired into spec-draft-opus input).
All four validate against controlplane WorkflowTemplate schema.
2026-07-02 21:27:43 +12:00
Paul O'Reilly
f3d7b42db5 feat(sonnet-manager): write full manager CLAUDE.md from spec/manager-sonnet.md
Replaces the 7-line stub: hard rules (eligible-list-only dispatch, code-blind,
explicit auth, read-only policy, untrusted inbox bodies), normative outer loop
+ MS-24 idle-exit sequence, typed-message routing, MS-25 fallback format,
cp-cli exit-code reactions, decision-log etiquette.
2026-07-02 21:27:43 +12:00
Paul O'Reilly
4d7acc870c reflect-logs: distill session logs into topic memory (2026-07 sweep) 2026-07-02 16:05:43 +12:00
Paul O'Reilly
dd0d9e5c0a feat: hugo-content-workspace + hugo-content-airouter harnesses
New context: hugo-content-workspace/v1
- init.sh: clones hugo-{customer}-content at HUGO_CONTENT_BRANCH and
  hugo-{customer}-integration at main via gitea-ssh-accelerators
- finalize.sh: detects changes, commits content repo first then
  integration repo; skips silently if no changes
- CLAUDE.md: instructs the agent to work in /workspace/content/

New composite: hugo-content-airouter/v1
- Combines airouter/v1 + gitea-ssh-accelerators/v1 + hugo-content-workspace/v1
- Label-gated to airouter dispatchers (ESO secret required)

Used by cms-proxy /ai/{customer}/draft endpoint.
2026-06-24 07:10:05 +12:00
Paul O'Reilly
8167035b6b Add DeepSeek V4 Flash model and coder composite via airouter
- models/airouter-deepseekv4flash.yaml: DeepSeek-V4-Flash on airouter.ch endpoint,
  temp 1.0 / top_p 1.0 per recommended reasoning defaults, 262k context / 65k output
- model-registry/airouter-deepseekv4flash.yaml: deepseek provider, complexity 9,
  creativity 9, cost_efficiency 10 (covered by airouter sub)
- harnesses/contexts/deepseek-code-methodology/v1: DeepSeek-specific methodology
  CLAUDE.md; same rules as qwen-code-methodology but with correct model header
- harnesses/composites/code-airouter-deepseekv4flash-repo/v1: coder composite
  using airouter/v1 context (shared endpoint + secret — no new ESO resources needed)
2026-06-23 22:07:33 +12:00
Paul O'Reilly
93c4dad1a7 docs: update CLAUDE.md — CRS is now required, add workflow/ subdir to structure 2026-06-23 09:08:06 +12:00
Paul O'Reilly
f5968cfab5 feat: migrate missing harnesses, templates, and workflows from agent-runtimes
Brings the framework CRS repo up to date with all content that was
living in agent-runtimes (local-dev fallback) but hadn't been promoted.

New composites: feature-delivery-loop, integration-direct, scaffolding-repo,
sonnet-impl-narrow, sonnet-manager, test-writing-repo

New contexts: integration/v1, scaffolding/v1, sonnet-manager/v1, z-ai/v1,
airouter/v1/bin (anthropic-compat-wrapper.sh), cp-harness/v1/init.sh

New task-templates: sonnet-integrator.yaml, workflow/* (17 typed workflow
task templates for the Epic 1 pipeline)

Updated: agent-repo/v1/finalize.sh — adds AR-38/F97 empty-deliverable audit
(SKIP_BRANCH_PUSH support, boilerplate-path filtering, ci_metadata.json flag)

Also adds MEMORY.md index and memory/ topic files for the framework repo.
2026-06-23 08:59:01 +12:00
Paul O'Reilly
770ba97170 feat(epic1): add spec-writing-airouter-repo and best-practices-airouter-repo composites
Required by the Epic 1 trigger pipeline in agent-runtimes:
- spec-draft-opus@1 uses spec-writing-airouter-repo (concept→spec-draft workflow)
- review-spec-arch-opus@1 uses best-practices-airouter-repo (spec-draft→spec-reviewed-arch)
- scope-decompose-sonnet@1 uses spec-writing-airouter-repo (spec-reviewed-arch→scoped-tagged)

Both composites require the airouter label so only the airouter dispatcher claims them.
2026-06-19 17:34:58 +12:00
Paul O'Reilly
38dc28fef9 fix(harness): remove agent-repo/v1 from code-sonnet-direct composite
agent-repo/v1 init.sh creates /workspace/project/results/ and .gitignore,
making the directory non-empty before the integrator clone action runs.
git clone into a non-empty directory fails with 'already exists'.
Integrators don't need the agent-repo lifecycle — they clone origin/main
directly and push back. Remove agent-repo/v1 from the composite.
2026-06-15 01:27:55 +12:00
Paul O'Reilly
50c07b850c feat(harness): add code-sonnet-direct composite + direct-push context
Copies code-sonnet-direct/v1 (composite) and direct-push/v1 (context)
from agent-runtimes local harnesses to the CRS-served framework repo.
These are required by the sonnet-integrator task template used in the
ralph coding loop. Without them, all integrator dispatches fail with
"harness not found in any concepts repo: code-sonnet-direct/v1".
2026-06-15 00:18:43 +12:00
Paul O'Reilly
415118434c debug(agent-repo): expose reference_branches clone failure mode
Probes 7-9 (2026-05-08) all "succeeded" but with empty diffs because
AR-14a fell back to fork main: "WARNING: /workspace/reference/main/.git
not found; using fork main (may be stale)". The reference clone python
loop printed "Cloning git@..." but never "Cloned main successfully" —
no error visible either.

Most likely cause: full-history clone (post-3087ad7) is hitting some
silent failure mode (auth, fs perms, OOM, timeout). With capture_output=True
the git clone's own output was hidden.

Add explicit logging:
- python3 -u (unbuffered stdout)
- pre-loop "reference_branches loop: N entries"
- post-clone "clone returncode=N"
- always-print stdout (last 1KB) and stderr (last 1KB) from subprocess
- explicit chmod return code check
- post-clone .git existence assertion

Next probe will tell us EXACTLY what's failing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 17:24:10 +12:00
Paul O'Reilly
3087ad7de1 fix(agent-repo): full-history clone for reference + upstream-ref fetch
Probe 7 (2026-05-08) finally surfaced the actual push error:

  ! [remote rejected] HEAD -> task-9dc266b5 (shallow update not allowed)

Cause: REFERENCE_BRANCHES handler clones with --depth 1, AR-14a then
fetches upstream-ref --depth 1. The agent's task branch is a single
commit on top of a single shallow commit — no ancestry visible. Gitea
rejects shallow pushes server-side.

Fix:
- Reference clone drops --depth 1 (full history)
- AR-14a fetch upstream-ref drops --depth 1 (full fetch from local-path)
- Cost: a few extra MB per task on tmpfs/PVC. Acceptable.

This unblocks AR-14a's upstream-seeding for the dogfood pipeline. The
agent's branch now has the full upstream history visible to gitea.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 17:09:53 +12:00
Paul O'Reilly
bf18ca3ef5 fix(agent-repo): capture git push output explicitly for diagnosis
Probe 6 (2026-05-08) showed git push failing twice with exit 1 and
zero visible output — the previous form `if cmd 2>&1; then` redirected
git's stderr to stdout where the entrypoint's stderr-only log capture
missed it. CP-side log showed only the bash `set -x` trace, not the
actual git error message (e.g., "Permission denied (publickey)" or
"remote: pre-receive hook rejected").

Refactor the push retry loop:
- Capture output to PUSH_OUT via $() with `2>&1`
- Wrap in set +e/set -e to detect non-zero without aborting
- echo PUSH_OUT to stderr (where set -x trace also goes) so the
  entrypoint's stderr capture sees it

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 17:03:12 +12:00
Paul O'Reilly
9cf016fa1c fix(agent-repo): harden AR-21 diff-verify against set-e/pipefail abort
The 2026-05-08 attempt-2 dogfood batch had 8/8 tasks "succeed" with
zero branches pushed. Root cause: my AR-21 diff-verification block was
running under set -euo pipefail without explicit error handling. A
single non-zero exit anywhere in the `git diff | tr | sed` pipeline
killed finalize.sh before the metadata write or push ran.

Specific risk: `git diff <REF_HEAD>..HEAD` returns non-zero when the
SHA is unreachable (e.g., shallow clone with init.sh fork-fallback
where upstream-ref wasn't fetched). pipefail then kills the pipeline,
set -e kills the script.

Fix: wrap the entire AR-21 block in `set +eo pipefail` (with explicit
`set -eo pipefail` restore at the end). Also:
- Use `${arr[@]:-}` instead of `${arr[@]}` for set -u safety on empty
  arrays
- Add `|| true` to git command substitutions (belt-and-braces)
- Use `printf` instead of `echo` for the comma-wrap (more portable)

Verified locally: when `/workspace/reference/main/.git` is absent the
block correctly skips with the existing fallback; when present and
upstream-ref is reachable, the block runs and reports DIFF_VERIFIED.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 16:31:33 +12:00
Paul O'Reilly
07309567d5 feat(agent-repo,airouter): seed from upstream + label-gate + diff verify
Three load-bearing fixes for the airouter dogfood pipeline, derived from
the 2026-05-08 batch-3 dogfood postmortem (gotchas-airouter.md items 27-30):

1. agent-repo/v1/init.sh — seed fresh task branches from
   /workspace/reference/main/ (the upstream clone) rather than the agent
   repo's stale main. This was THE killer for batch 3: the
   agent-runtimes-agents fork has been frozen at 2026-05-04 since the
   "Fork cleanup" PR, so every agent started from old state, missing
   recent test files and the M16/M22 scripts to delete. The fork remains
   the push remote (so finalize.sh works); only the working-tree seed
   moves to the upstream reference. Falls back to fork main when the
   reference clone isn't available (preserves legacy behavior). Tagged
   AR-14a.

2. requires_labels on contexts/composites — airouter context + both
   airouter composites declare requires_labels: [airouter] so the
   dispatcher's _collect_supported_harnesses (with the matching agent-
   runtimes change) advertises them only on dispatchers carrying the
   airouter label. Stops the main dispatcher from claiming airouter-
   labeled tasks and dying at init time. Composites that wrap label-
   restricted contexts MUST redeclare their own requires_labels — no
   auto-traversal of layers (kept simple).

3. agent-repo/v1/finalize.sh — AR-21 diff-against-upstream verification.
   New env-var protocol:
     - AGENT_EXPECTED_CHANGED_FILES (comma-separated paths that MUST
       appear in `git diff <ref/main>..HEAD`)
     - AGENT_FORBIDDEN_CHANGED_FILES (paths that MUST NOT appear)
   finalize.sh fails the task (exit 1) if either invariant is violated;
   the branch is still pushed for forensics so the operator can inspect.
   Catches BOTH the false-success mode (item 30 — agent reports succeeded
   but never changed the target file) AND the destructive-Write mode
   (item 21 — task 4a2f2988 stripped 9 unrelated functions). Also writes
   diff_verified, diff_mismatch, diff_changed_files into ci_metadata.json.

CRS pulls all three on next CP poll — no agent-runtimes image rebuild
needed for the framework parts. The matching dispatcher poller filter
ships in agent-runtimes (separate commit).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 15:45:41 +12:00
Paul O'Reilly
45ec4af0e9 docs(qwen-methodology): add real incident to Rule 1 (Write on existing files)
After the 2026-05-08 M16 Wave A1 dogfood task `4a2f2988` produced a
correct narrow change but accidentally deleted 9 unrelated functions in
the same file (Write rather than Edit), the existing Rule 1 in
qwen-code-methodology/v1/CLAUDE.md is clearly insufficient — the agent
saw it and overrode it anyway. Concrete real-world example added inline
so the next agent reading this CLAUDE.md sees the consequence: "the
narrow test passed but the application broke everywhere else, the
branch was rejected, the agent thought it had succeeded."

CRS picks up automatically on next CP poll.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 13:09:52 +12:00
Paul O'Reilly
79f00b566d feat(cp-harness): migrate from agent-runtimes/harnesses/
The agent-runtimes repo is moving to a CRS-only harness model: dispatcher
images stop baking in /app/harnesses/ and discover them via CRS at runtime.
cp-harness was the only harness that lived only in the agent-runtimes
checkout (created in M16 Phase 1 D4, commit c1df4cc) — copied here so
nothing is lost in the cutover.

cp-harness has no current consumers (no composite or template references
it); it is infrastructure for the future M16 self-orchestration api_key
submission flow.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 12:25:47 +12:00
Paul O'Reilly
b1e3ee7052 fix(airouter): match ESO Secret schema (api_key) + drop dead wrapper
The airouter ESO ExternalSecret materialises a single key `api_key`
(matching the provider schema in agent-runtimes M22 Phase 8e cutover,
acct-59b7fb0b). The harness init script was checking for `auth_token` +
`base_url` (an Anthropic-compat shape that never existed in real Vault
state) and failing on every dispatch:

  ERROR: /run/agent/secrets/airouter/auth_token not readable.
  Check ESO ExternalSecret for airouter.

Surfaced as the second blocker for the M16 Wave A1 dogfood (the first
was the airouter dispatcher missing CRS sync; that fix went into
agent-runtimes-deploy@0f11cd1).

Same shape of bug as the minimax + gitea-ssh init scripts that landed
during the same M22 phase — those were fixed at the time, airouter was
not.

Changes:
- init.sh: verify the single `api_key` file (root-only, 0400 ESO mount).
  Stage to /var/agent-secrets/airouter/api_key with mode 0600 agent-owned
  (mirrors minimax pattern). H-SECRET-4 compliant — no exports.
- harness.yaml: add OPENAI_API_KEY_FILE pointing at the staged path.
  Agentic runner reads the file at request time per
  entrypoint/runners/agentic.py:146 (OPENAI_API_KEY_FILE precedence).
- Delete dead bin/anthropic-compat-wrapper.sh — confirmed unused per
  agent-runtimes/memory/log/2026-05-07.214249.md (post-M22-Phase-9 cleanup
  found these per-provider wrappers were never invoked; runner only
  prepends /opt/agent/claude-wrapper.sh).

CRS picks this up automatically on next CP poll; no agent-runtimes image
rebuild needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 12:24:58 +12:00
8669b3da7d Merge pull request 'chore(z-ai): retire harness — no active subscription' (#2) from retire-z-ai into main 2026-05-07 21:41:33 +00:00
Paul O'Reilly
335e6f5b34 chore(z-ai): retire harness — no active subscription
Removes harnesses/contexts/z-ai/v1/. Mirrors the agent-runtimes
companion PR — the z-ai harness was never cut over to ESO and
there's no active subscription. Revival path documented in
agent-runtimes planning/future/providers F49.

Removed:
- harnesses/contexts/z-ai/v1/{harness.yaml, init.sh}

Updated:
- CLAUDE.md — drops z-ai from the 'no secrets in this repo'
  context list. Retirement note added.
- gitea-admin/v1/init.sh — comment ref to z-ai removed.
- gitea-https/v1/init.sh — comment ref to z-ai removed.

No composites layer z-ai (verified via grep across composites/);
no model registry entries reference it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 09:40:44 +12:00
649acc07df Merge pull request 'fix(b22): bare account_ref + retarget composites + delete stale anthropic-cloud/v1' (#1) from b22-anthropic-cleanup into main 2026-05-07 20:10:15 +00:00
Paul O'Reilly
7a75c5ec3b fix(b22b): retarget composites + delete stale anthropic-cloud/v1
Phase 8 cutover (M22) renamed the anthropic harness from anthropic-cloud
→ anthropic-cloud-paul-oauth in agent-runtimes, but the equivalent
rename in this framework's composites and the deletion of the stale
SOPS-era anthropic-cloud/v1 dir were never done. Every cloud-Anthropic
composite (haiku/sonnet/opus code, planning, security-review, spec-
writing, test-writing, best-practices) layered the dead context and
silently never resolved a credential.

- Update 14 composites to layer anthropic-cloud-paul-oauth/v1
- Delete the orphaned harnesses/contexts/anthropic-cloud/v1/ directory
  (used pre-Phase-9 SOPS file delivery; now obsolete)

Closes BUG-22b. Pairs with the live PATCH /v1/accounts/{id} rename
shipped under BUG-22a.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 07:16:09 +12:00
Paul O'Reilly
3d6a50fdd7 fix(b22a): bare account_ref for anthropic-cloud-paul-oauth harness
Same bug as upstream agent-runtimes: scoped form never matched
because the dispatcher does literal scope.id compare and
owner_principal_id stores the user UUID, not 'paul'.

Pairs with PATCH /v1/accounts/{id} renaming the live account_label
to 'anthropic-cloud-paul-oauth' so the bare ref resolves uniquely.

Closes BUG-22a.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 06:58:39 +12:00