v4.3.0
[4.3.0] - 2026-07-29
The agents join the system they were supposed to be part of. Before this
release an agent was a fourth front-end without parity: it carried its own
copy of the rules, re-derived structure the plugin had already computed, and
nothing it produced fed the learning loop. Each fix below was reproduced
before it was fixed and carries a test that fails if it regresses.
Fixed
-
The orchestrator told the model to run skills the model cannot run.
Sixteen of twenty-two skills carrydisable-model-invocation: true, which
means only the user can start them by typing the slash command first in a
prompt./craftsman:workflownonetheless announced "Invoking
/craftsman:design..." for four of its seven steps, and five agents listed
locked skills inskills:frontmatter. Every one of those references was
unreachable: the Skill tool answerscannot be used with Skill tool due to disable-model-invocationand the pipeline stops there. The workflow now
hands off, printing the exact command to paste and waiting, and the nine dead
agent references are gone. -
/craftsman:teamcould not be started by anything except a bare prompt.
It was classified as a heavy review in ADR-0017 and given
disable-model-invocation: true, so no orchestrator could reach it. The flag
is dropped and the skill is model-invocable. It stays out of a fork on
purpose: it asks the user which template to use and callsTeamCreateto
spawn teammates into the session, and a fork would strand both. -
An agent could be told to fork into itself.
agents/architect.md
declaredcraftsman:challenge, which is bound toagent: craftsman:architect.
Same shape inagents/team-lead.mdforcraftsman:team. -
The subagent quality gate validated nothing. Its header said "validates
code produced by subagents against craftsman rules"; its body logged an
agent_type and a timestamp. It now reads the subagent's transcript, runs
every file the subagent wrote through the same pack validators as the hooks
and CI, records each finding in the metrics DB tagged
subagent:<agent_type>, and surfaces the findings to the main loop as
additionalContext. Silence remains the pass signal, and the gate stays
non-blocking. -
The agent context injector never reached an agent. The old
agent-structure-analyzer.shasked each agent to re-scan the repository,
from a hook onInstructionsLoaded- a side-effects-only event whose output
the platform ignores, aimed at an event that does not fire on agent dispatch
anyway. Removed. Agents now start by running
hooks/lib/dispatch-context.sh, which returns the resolved doctrine (same
rules engine as hooks and CI), the HEAD-cached codemap, the top hotspots and
the correction trends: one deterministic turn instead of a self-guided scan. -
A review could silently run a tier below what the docs promise.
challengedeclaresmodel: opusand forked into anarchitectdeclaring
model: sonnet; the platform does not document which wins.architect,
legacy-surgeonandteam-leadnow declareopus, matching the reference
table, and the invocation-policy test fails any forking skill whose bound
agent disagrees on the model. -
subagent-quality-gate.shprinted a bare counter onto its JSON channel.
session_state.py incrementechoes the new value; the hook never silenced
it, so every SubagentStop emitted a stray1on stdout.
Added
hooks/lib/dispatch-context.sh: single source of start-of-dispatch context
for all 12 agents (resolved doctrine, cached codemap, hotspots, correction
trends). The agent is a front-end of the rules engine like hooks and CI:
it no longer carries its own copy of the rules.- Per-agent violation metrics: the
sourcecolumn now distinguishes
subagent:<agent_type>rows, so/craftsman:metricscan show which agent
keeps producing which violation and agent prompts can be tuned from data. - Agent contracts: every craftsman agent ends with an Output Contract (test
evidence required before "done"), and every agent carries a one-line Memory
Contract saying exactly what it may persist; reviewers persist rejected
findings so the same false positive is not raised twice. /craftsman:teamdegraded mode: whenCLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS
is absent the skill announces it once and runs the same composition through
parallel subagent dispatches instead of failing; the healthcheck reports
which mode the environment provides. The team-lead delegation matrix also
gained the missing legacy row (legacy-surgeon / legacy-takeover template).tests/core/test-invocation-policy.shcrosses every agentskills:entry and
every**Invokes:**claim with its target's invocation policy, and rejects
self-forking bindings. Nothing checked this before, which is why sixteen
locked skills and nine dead references coexisted with a green suite.