Commit Graph

93 Commits

Author SHA1 Message Date
Paul O'Reilly
da23760e93 fix(models): airouter-qwen3 default_flags.model Qwen3.6 -> Qwen3.8 (live id; agent-runtimes c3551e3a)
Claude-Session: https://claude.ai/code/session_01N218bERyNeLhbLmDRDvbWF
2026-09-30 11:46:24 +13:00
f64be1d467 fix(gitea-ssh-hatchmate): correct account_ref space id (hatchmate, not platform) (#4)
Merge PR #4
2026-09-18 02:18:46 +00:00
c89cb5beab Merge pull request 'feat(forge-credential): hatchmate working-repo key layer + 4 composite forks' (#3) from feat/hatchmate-per-project-fork-key into main
Merge PR #3
2026-09-18 02:05:48 +00:00
Paul O'Reilly
59f7b9e5f8 feat(forge-credential): add gitea-ssh-hatchmate/v1 layer + 4 hatchmate composite forks
M2-CRS W4 unblock: dispatched agents could not clone hatchmate/hatchmate-agents
because the shared gitea-ssh/v1 context mounts the ai_enablement deploy key,
which is scoped to skynet/* only. Same bug would hit every project whose
working repo lives outside the skynet org.

This implements the per-org pattern the framework already uses for accelerators
(gitea-ssh-accelerators/v1) and homelab (gitea-ssh-homelab/v1):

- harnesses/contexts/gitea-ssh-hatchmate/v1/{init.sh,harness.yaml} — NEW
  forge-credential context mirroring accelerators, with account_ref
  'hatchmate.space:platform' and write_targets covering hatchmate/*. The
  init.sh stages the ESO-mounted private key to ~/.ssh/gitea-oreillyit-nz-hatchmate
  (matching the ssh alias declared in harness.yaml). URL host pattern
  'gitea.oreillyit.nz-hatchmate' (per-org alias) drives SSH config block
  selection — already auto-written by harness_init.py from each layer's
  ssh_hosts: declarations.

- harnesses/composites/code-*-tdd-repo-hatchmate/v1/ — NEW composites for
  fable/minimax/airouter/opus that compose BOTH gitea-ssh/v1 (for reference
  clones, skynet org) AND gitea-ssh-hatchmate/v1 (for working-repo clone +
  push, hatchmate org). Composites are unchanged for non-hatchmate projects.

- tests/invariants/test_forge_credentials_declare_write_targets.py — the
  existing xfail(strict=True) marker was wrong: the 4 existing layers all
  declare write_targets today, so the test was XPASSing. Removed the
  xfail marker so HC-11 is now a real positive gate (5 layers instead
  of 4). This was a pre-existing test bug surfaced by the 5th layer.

W4 next step: dispatcher's account_ref resolution needs the hatchmate CP
account + grant to be created (via the new scripts/provision-hatchmate-fork-key.sh
in the hatchmate app repo).
2026-09-18 12:28:06 +12:00
Paul O'Reilly
d19da44f7a feat: AR-39a — templates pass AGENT_UPSTREAM_REPO_URL/BRANCH; agent-repo/v1 init.sh invokes select-base (upstream > reference > fork) (bug 0772408e)
Claude-Session: https://claude.ai/code/session_01G3SkMRBRWXyiGuMGs8WVas
2026-09-16 19:34:47 +12:00
Paul O'Reilly
7e757b0fd9 harness(HC-11): declare write_targets on the four forge-credential layers (gitea-admin, gitea-ssh, gitea-ssh-accelerators, gitea-ssh-homelab) (b1de17b4)
Held locally until the agent-runtimes HC-11 composer change is deployed: the live composer is extra=forbid and would reject the new key.

Claude-Session: https://claude.ai/code/session_018LRh1S2bHJYhEgrMu3UJx8
2026-09-13 20:09:50 +12:00
Paul O'Reilly
b7cf256c44 test(invariants): HC-11 forge-credential layers must declare write_targets (xfail until layers are stamped)
Helper tests/invariants/forge_credentials.py detects credential carriers via
mounts[]/env/secrets_required[]/ssh_hosts[]; today gitea-admin, gitea-ssh,
gitea-ssh-accelerators, gitea-ssh-homelab are found and none declare
write_targets — the invariant xfails(strict) until the CRS-103 rollout stamps them.

Claude-Session: https://claude.ai/code/session_018LRh1S2bHJYhEgrMu3UJx8
2026-09-13 13:09:24 +12:00
Paul O'Reilly
e31d472ff9 fix: migrate Claude model files to current API IDs (opus-5, sonnet-5, haiku-4.5)
Bug 57d8a047-d26d-47ce-ae6f-bc5cb98fef0e: Opus-tier tasks 404'd because
models/claude-opus-4.yaml pinned default_flags.model to "claude-opus-4-5",
a retired ID. models/claude-sonnet-4.yaml was pinned to a dated snapshot
("claude-sonnet-4-20250514") with the same problem.

Slug strategy: the registry slug (filename / RegistryEntry.name) doubles
as the literal --model argument on the workflow-template pass-through path
(task-templates/workflow/*.yaml `model:` field -> compiler WF-COMP-18 ->
payload.runtime.model -> entrypoint/runners/claude.py `--model`), which has
no translation step through this file's default_flags. So rather than
patch default_flags.model in place (leaving the slug stale and the
pass-through bug latent), rename the slug to match the current API ID:

- models/claude-opus-4.yaml, model-registry/claude-opus-4.yaml
  -> claude-opus-5.yaml (name/endpoint/default_flags.model: claude-opus-5)
- models/claude-sonnet-4.yaml, model-registry/claude-sonnet-4.yaml
  -> claude-sonnet-5.yaml (claude-sonnet-5)
- model-registry/claude-haiku-4.yaml -> claude-haiku-4-5.yaml
  (claude-haiku-4-5); added the previously-missing models/claude-haiku-4-5.yaml
  so the claude runner can actually resolve this endpoint
- model-registry/harness-roles.yaml, model-registry/tiers.yaml,
  workflows/smart-agent.yaml, task-templates/workflow/{spec,plan}-review-loop@1.yaml:
  updated every claude-opus-4 / claude-sonnet-4 / claude-haiku-4 reference
  to the new slugs
- models/openrouter-sonnet.yaml: dated snapshot "claude-sonnet-4-20250514"
  -> "claude-sonnet-5" (third-party router proxying the same retired ID)
- refreshed cost_per_1k_tokens on the three renamed registry entries to
  current published pricing

Claude-Session: https://claude.ai/code/session_015nXvGNNNixJPFwZKZHNyha
2026-09-10 12:05:14 +12:00
Paul O'Reilly
30c3a75c20 feat(workflow): bug-ancestor-auto-advance@1 demo template (M43 Task 2) 2026-09-10 09:35:29 +12:00
Paul O'Reilly
3eabc924a2 refactor(python-dev): swap pip -> uv pip for project install
uv is now pre-baked into the base image
(agent-runtimes/images/base/Dockerfile) and is faster than pip with
better retry on transient network failures. Closes the last runtime
hang vector for project-deps install — apt install was removed 2026-09-06
in 0c57972f-pre-bake work but the pip install -e line in init.sh
remained. uv pip install is the equivalent operation with the new
pre-baked tooling.

Refs F-WE-PDIV/RCA-2026-09-04-zombies.
2026-09-09 21:56:48 +12:00
Paul O'Reilly
be57e1e246 fix(bug-verify): fresh UUID Idempotency-Key so re-verification with a different verdict does not 409
Claude-Session: https://claude.ai/code/session_01U3biMxRhFGkwtf4jVTNjcj
2026-09-09 13:57:40 +12:00
Paul O'Reilly
33501ca54e fix(bug-verify-sonnet@1): agent self-transitions flow_state, remove dead verdict-tx node
verdict-tx (kind: script) never worked: script nodes are harness-exempt
(WF-COMP-6/MN-38) and run in their own empty container, so it could
never credentially read /workspace/verdict from the agent's node.

Option 3: give the agent node's own composite (planning-sonnet-repo) a
cp-service-token/v1 layer, and have the agent PATCH its own item's
flow_state (verified|rejected) to the CP directly as its last step,
before task_complete. Removes verdict-tx entirely.

See agent-runtimes work item 88ecd23e and spec/typed-workflows.md
WF-COMP-25 (agent-runtimes commit 8972d266) for the finalize.py
precedence fix this depends on (ambiguous pipe-separated output.state
must never be auto-PATCHed over the agent's own value).

Claude-Session: https://claude.ai/code/session_01U3biMxRhFGkwtf4jVTNjcj
2026-09-09 13:56:34 +12:00
Paul O'Reilly
5a8cd32aec feat(harnesses): add customer-script/v1 composite
Minimal harness for kind: customer_script nodes (agent-runtimes
spec/tenant-namespaces.md SCR-1..SCR-6). No LLM turn - runs via the
"shell" runner, agent-repo/v1 clone access only. Per-script credential
needs are deliberately not baked into this base (SCR-6: narrow,
per-script review) - compose a customer-script-<need>/v1 variant
layering whichever specific credential context a given script actually
needs, rather than widening this shared base.

Without this commit, kind: customer_script was not dispatchable from
any machine other than the one it was authored on - the harness lookup
against a fresh CRS sync would fail.

Claude-Session: https://claude.ai/code/session_012arAwUuBQrpnMzJ36mEVBk
2026-09-08 07:42:48 +12:00
Paul O'Reilly
3a550837aa docs(bug-verify-sonnet): note the scratchpad/verdict follow-up, not yet wired
Attempted to wire verdict-tx to clone the agent's branch and read
scratchpad/verdict (the new cross-node artifact convention,
agent-repo/v1 init.sh) instead of the ephemeral /workspace/verdict.
Reverted: script tasks (dispatcher/task_manager.py::_run_script_task)
have no credentialed way to clone a private repo — the per-task SSH key
is provisioned through the full ESO/account harness resolution
pipeline, which script tasks deliberately bypass entirely. Left the
template on its current (still-broken-for-cross-container-reasons)
/workspace/verdict contract with a note, pending a scoped follow-up on
how script nodes get read access to the branch (new secrets plumbing,
vs. folding the state transition into the agent node's own already-
credentialed CP access).
2026-09-06 23:59:52 +12:00
Paul O'Reilly
4b4d02926d feat(agent-repo): create scratchpad/ at task branch top level
Cross-node artifact passing within a workflow manifest — nodes each run
in their own ephemeral container/pod with no shared filesystem, so an
agent node writing e.g. a verdict to /workspace/verdict is invisible to
a downstream kind: script node in the same manifest (found live
2026-09-06, bug-verify-sonnet's verdict-tx). The git task branch is the
only channel every node in a manifest actually shares: write to
scratchpad/, commit (picked up by finalize.sh's existing git add -A),
next node clones the same branch and reads it back.

scratchpad/ is scratch, never deliverable content, and must never
survive a merge into main — a CI gate in the target repo
(agent-runtimes .gitea/workflows/build-images.yaml,
no-scratchpad-in-main) is the hard backstop.
2026-09-06 23:44:51 +12:00
Paul O'Reilly
a685bf16a6 feat: bug-verify-sonnet@1 template + planning-sonnet-repo runtime
Adds the CRS-side deliverables for agent-runtimes work item f59f0132
(ai-resolve bug-verification stage, M42 concept 7666d278). Mirrors
planning-opus-repo's layer stack with the sonnet model applied at the
node level (model: sonnet), per the established convention that the
composite name is descriptive only — the workflow node's own model:/
tier: field is what actually selects the model.

The template's terminal node runs the (separately-tracked, sibling
task ad975ac6) state-tx-verdict script — this template will not be
runnable end-to-end until that script lands, but the declarative
config itself is independently valid: schema-validates cleanly and
both eligibility scenarios from the task spec pass (verify-pending +
ai-resolve -> ok=True; missing flow_state -> state_mismatch).
2026-09-05 11:34:37 +12:00
Paul O'Reilly
0384e5d453 fix: remove misplaced hatchmate-plan-review-loop@1 (project template referencing hatchmate-crs model slugs; broke CP WorkflowRegistry reload 2026-09-05)
Belongs in hatchmate-crs/task-templates/workflow/plan-review-loop@1.yaml, which already exists.

Claude-Session: https://claude.ai/code/session_01FNHuaZyTjdknKYcQdbRTcp
2026-09-05 10:24:36 +12:00
Paul O'Reilly
b4bac0d2e8 feat: hatchmate-plan-review-loop@1 — project-specific plan review template
Hand-sync of hatchmate-crs's plan-review-loop@1 under a project-prefixed name
so hatchmate's triggers can reference it via the global WorkflowRegistry.

Interim pattern until agent-runtimes ships project-scope template serving
via crs_manager (M42 gap: DispatchService only consults the concepts_syncer
WorkflowRegistry, not crs_manager's repo store). Template is hatchmate-specific
throughout: Fable-low + MiniMax-M3-max + Airouter-Qwen3.8-max reviewers,
hatchmate/hatchmate-agents clone URL, hatchmate-aware prompts and conventions.

Claude-Session: https://claude.ai/code/session_01PdFrhZypEDBTsbAeTJqHq1
2026-09-04 20:49:13 +12:00
Paul O'Reilly
253b147a39 fix(harness): cp-service-token/v1 — restage ESO secret, fix unreadable-by-agent bug
The ESO-mounted secret is root-owned mode 0400 (correct — init.sh runs as
root before the gosu drop to the agent user). The original version of
this context pointed CP_SERVICE_TOKEN_FILE directly at that raw mount,
which the agent process (uid 1000) can never read.

Confirmed live 2026-09-03: a real scope-decompose-sonnet@1 dispatch
against concept 7666d278-ae58-4f12-990d-c4959a3e19a9 hit exactly this —
the agent correctly diagnosed 'cp_cli invocation can't proceed... token
is root-owned mode 0400 so it's not readable by the agent user', wrote
its decompose plan, but could never actually call cp-cli to create the
child tasks. The trigger engine's new side-effect verification (finalize.py,
bug 9dffc5b8) correctly caught this and refused to advance flow_state —
so this was a visible, retriable failure rather than another silent
false-positive.

Fix: init.sh restages the secret to /run/agent/cp-service-token/token,
mode 0600, owned by the agent user — mirrors
anthropic-cloud-paul-oauth/v1/init.sh's existing pattern.
CP_SERVICE_TOKEN_FILE now points at the restaged copy.
2026-09-04 13:03:07 +12:00
Paul O'Reilly
38cd0b040b feat(harness): cp-service-token/v1 context — AU-51/AU-51b credential for decompose
New context mounts the cp-decompose-service-token account (system
provider type, account_id 1d963673-6ac9-4f85-875a-2ce5323e76ad, owner
(cp, cp)) via ESO and exports CP_SERVICE_TOKEN_FILE pointing at the
mounted secret file. Wired into spec-writing-sonnet-repo (backs
scope-decompose-sonnet@1, which calls back POST
/v1/work-items/{id}/decompose — bug b3a96acc / fa41caac / M42 stall).

The mounted value must match the CP's CP_INTERNAL_BEARER_TOKEN
(agent-runtimes deploy repo, overlays/{production,staging}/app-secret.sops.yaml).

No init.sh needed — the mount path is static at harness-authoring time
and entrypoint/actions/decompose_work_items.py (AU-51b, agent-runtimes
commit 0fa8b760) reads CP_SERVICE_TOKEN_FILE directly, so no
transformation/staging step is required.
2026-09-04 05:31:34 +12:00
Paul O'Reilly
2dcb9c7605 fix(minimax-m3-max, fable-low-effort): requires takes harness refs, not capability tags
'requires: [claude-code]' failed composition ('Invalid harness reference
format'). Both contexts need no hard dependency — layer ordering in the
composites already guarantees the auth layer precedes them. Validated
locally with entrypoint.harness compose_harness for all 6 affected
composites this time.

Claude-Session: https://claude.ai/code/session_019tJk7P8tZzJ24PvtgoGhLN
2026-09-03 01:13:34 +12:00
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