Companion (V2)¶
Companion is the background loop layer of the plugin — five small hook handlers that fire on Claude Code events (PreToolUse, PostToolUse, UserPromptSubmit, Stop) and keep the work Claude does for you honest against the workbook.
Design principle: Companion is silent unless something material happened. If you're mid-implementation and nothing is committed-decision-ish, Companion stays out of your way. When you finish a verify, when you mark a task DONE, when you say "save progress" — those are the moments it speaks up.
The pillars¶
1. Proactive verify gate¶
Blocks mcp__dezycro__update_task calls that try to mark a path-linked task as DONE or PUSHED when no recent passing verifier run is on file. The agent receives a structured deny with the specific paths and the exact /dezycro:verify --path <p> command to run.
Why: prevents the most common silent failure — Claude marking work "done" when the verifier would have failed it.
Override: set companion.autoVerify.preTaskDone: false in .dezycro/config.json.
2. Spec-publish nudge¶
Tracks every Edit / Write / MultiEdit against companion.autoVerify.controllerPaths (default: **/controllers/**, **/api/**). When a controller path is touched, Companion records the change and sets needsSpecPublish=true.
The next /dezycro:verify run reads that flag and chains /dezycro:publish-spec first, so you never run the verifier against a stale spec.
After 5 controller edits without a verify, Companion emits a one-line pulse nudge.
3. Workbook sweep — trigger-based, silent by default¶
When the agent finishes a turn, Companion does nothing by default. It fires the workbook-sweep directive only when one of these is true:
- The user said a wrap phrase on this turn:
save progress,log what we did,/dezycro:sync,wrap up,we're done,end of session, etc. /dezycro:verifyjust completed this turn (snapshot moment for committed decisions).
When it does fire, the directive asks the agent to scan the recent conversation for:
- Decisions (committed technical/product choices)
- Issues (current blockers/bugs)
- Assumptions (unverified beliefs)
- Task-status hints (a tracked task is now DONE/PUSHED)
…with confidence thresholds per the configured preset (default conservative: 0.85 / 0.80 / 0.90 / 0.90). The agent then calls the matching MCP workbook tool (add_decision, add_issue, add_assumption, update_task) and announces what it logged in plain English, with an 'undo that' if wrong suffix.
Caps: at most 2 entries per turn, 10 per session (configurable). Content-hash dedup against a 32-entry ring buffer prevents the same decision from being logged twice.
Undo: type undo that on the next user turn (within the immediate-next-turn window) and Companion emits a reversal directive that flips the entry to INVALIDATED / CANCELLED / restores the prior task status.
4. Coverage nudges¶
Two nudges, both deterministic — no LLM round-trip:
- Pre-PUSH: when you mark a task PUSHED and the verifier passed, Companion surfaces a one-liner of remaining coverage gaps via the system-message channel. Never blocks; informational only.
- Post-verify Stop: if a verify completed after the previous snapshot was last surfaced, Companion emits a coverage delta (e.g.
Coverage delta since last verify: -2 paths uncovered, -1 baseline stale).
The one-liner format pluralizes and omits zero-count segments:
5. /dezycro:author sanity check¶
When the agent calls change_document_status to push a TRD to APPROVED, Companion runs a light deterministic sanity check against the most-recent draft sidecar — flags obvious placeholder tokens (TBD, TODO, FIXME) and warns on tiny drafts so a half-finished doc doesn't accidentally get marked as approved.
There's no schema enforcement — TRDs don't have a required structure. The check exists as a "did you mean to do that?" guard, not as a content gate.
Configuration¶
All settings live in .dezycro/config.json under the companion key. Defaults (you can override any of these per-repo):
{
"companion": {
"safeMode": false,
"autoVerify": {
"preTaskDone": true,
"prePush": true,
"postEditPulse": { "enabled": true, "threshold": 5 },
"autoPublishSpecOnControllerChange": true,
"controllerPaths": ["**/controllers/**", "**/api/**"]
},
"autoWorkbookUpdates": {
"enabled": true,
"preset": "conservative",
"maxAutoLogsPerTurn": 2,
"maxAutoLogsPerSession": 10,
"thresholds": {
"decision": null,
"issue": null,
"assumption": null,
"taskStatus": null
}
},
"coverageNudges": {
"enabled": true,
"staleBaselineDays": 14
}
}
}
Confidence presets¶
| Preset | Decision | Issue | Assumption | Task-status |
|---|---|---|---|---|
conservative |
0.85 | 0.80 | 0.90 | 0.90 |
balanced |
0.75 | 0.70 | 0.80 | 0.85 |
aggressive |
0.60 | 0.55 | 0.70 | 0.75 |
Numeric thresholds.* overrides win over the preset (per-type).
Kill switch¶
Set companion.safeMode: true to disable all Companion behaviors except the deterministic Pillar 1/2 gates. Or disable individual pillars via the per-key enabled: false flags.
State and logs¶
Companion writes two files under .dezycro/:
companion-state.json— session counters, ring buffers, last verify timestamp, coverage snapshot. Safe to delete (regenerates).companion.log— JSON-lines log of every hook firing. Tail withtail -f .dezycro/companion.log | jqto debug.
Both files are gitignored by /dezycro:init.
Manual trigger¶
You can also drive Companion's workbook sweep directly:
Or say "save progress" — the next assistant turn-end will fire the sweep.