claude-mcp-workflow 0.1.10 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/package.json +1 -1
- package/templates/skills/claude-code-config/SKILL.md +1 -0
- package/templates/skills/debugging/SKILL.md +41 -0
- package/templates/skills/domain-gamedev/SKILL.md +21 -0
- package/templates/skills/hxq/SKILL.md +2 -0
- package/templates/skills/hxq/references/ops.md +3 -3
- package/templates/skills/task-delegation/SKILL.md +12 -1
- package/templates/testing.yaml +12 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "workflow",
|
|
3
3
|
"displayName": "Workflow Engine",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.11",
|
|
5
5
|
"description": "Structured workflow orchestration for AI agents via finite-state machines.",
|
|
6
6
|
"keywords": ["workflow", "fsm", "orchestration", "state-machine", "mcp"],
|
|
7
7
|
"author": {
|
package/package.json
CHANGED
|
@@ -148,6 +148,7 @@ Entry shape: `{"id","type","status","description"}` + type-specific fields (`com
|
|
|
148
148
|
|
|
149
149
|
- `id` is stable across Stop firings; there are **NO timestamps** or turn counters. Distinguishing "started this turn" from "long-lived since an earlier turn" (dev server, watcher) requires persisting seen ids between Stop firings yourself (state file keyed by `session_id`).
|
|
150
150
|
- Non-empty `background_tasks` ≠ new work in progress: a persistent dev server stays listed at EVERY Stop — a hook that suppresses on non-empty silences itself for the whole session.
|
|
151
|
+
- Suppression heuristics must be TYPE-aware: `subagent`/`workflow` tasks always complete and re-invoke the main agent (their Stop is not the real finish), but `shell` tasks may NEVER complete (`npm run dev`) — a Stop with a freshly started shell task IS a real completion. "Started this turn ⇒ still working" is false for shell.
|
|
151
152
|
- Only live tasks are listed (completed ones are removed), and `session_crons` entries also carry `id`.
|
|
152
153
|
- `prompt_id` (v2.1.196+) identifies the current prompt; `last_assistant_message` (v2.1.145+) holds the final text.
|
|
153
154
|
- JSON string values escape quotes as `\"`, so a naive grep for `"key":"` cannot false-match text inside `command`/`description` values.
|
|
@@ -80,3 +80,44 @@ the baseline three rounds ago.
|
|
|
80
80
|
**Corollary:** In a long-running UNCOMMITTED working tree, "revert" may mean
|
|
81
81
|
hand-reconstruction. Commit checkpoints at every user-visible-good state so a
|
|
82
82
|
revert is one command, not an archaeology project.
|
|
83
|
+
|
|
84
|
+
## Model Emits What the Presenter Can't Deliver → Fix the Emitter, Check the Rejected-Fix Ledger First
|
|
85
|
+
|
|
86
|
+
When a bug is a contract violation between a data/model layer and a
|
|
87
|
+
presentation layer — the model emitted an outcome the presenter cannot
|
|
88
|
+
honestly produce (an unreachable target, a state the UI can't render as one
|
|
89
|
+
coherent motion) — the durable fix is in the EMITTER: stop emitting
|
|
90
|
+
undeliverable pairings, constrained against the presenter's real capability.
|
|
91
|
+
|
|
92
|
+
**DON'T:** Patch the presenter to fake the model's claimed outcome (splicing
|
|
93
|
+
a canned glide/animation to "reach" a value the simulation never hit) —
|
|
94
|
+
however small the visual gap, it reads as fake physics and gets rejected.
|
|
95
|
+
**DO:** Measure the presenter's honest capability empirically — drive its
|
|
96
|
+
real pipeline over a parameter grid, not a hand-derived geometric bound
|
|
97
|
+
(chaotic outcomes have no clean closed-form threshold). Constrain the
|
|
98
|
+
emitter to the measured-deliverable region. Before designing the fix, check
|
|
99
|
+
the project's record of previously rejected fix families (memory/docs/commit
|
|
100
|
+
lore) — a design in a rejected family costs a full user round-trip
|
|
101
|
+
regardless of execution quality.
|
|
102
|
+
|
|
103
|
+
**Tell:** Your fix adds presentation-side code animating toward a model
|
|
104
|
+
value the simulation never reached; or you're about to ship a fix pattern
|
|
105
|
+
the project's history already rejected under a different symptom.
|
|
106
|
+
|
|
107
|
+
## Predicted-vs-Measured Mismatch = Falsified Hypothesis; Verify the Fix Against the ORIGINAL Metric
|
|
108
|
+
|
|
109
|
+
Two disciplines for "my fix is principled but the bug persists".
|
|
110
|
+
|
|
111
|
+
**Falsifier rule:** when a candidate mechanism lets you PREDICT an observable
|
|
112
|
+
consequence — the time, place, or value at which something should happen —
|
|
113
|
+
and the prediction MISSES what you measured (even slightly), the hypothesis
|
|
114
|
+
is FALSIFIED, not "measurement noise / seeding uncertainty". A real but
|
|
115
|
+
MASKED cause (a second effect hiding behind the one you're studying) produces
|
|
116
|
+
exactly this trap: the fix is sound in isolation, measures zero effect, and
|
|
117
|
+
the mismatch was the tell all along. Don't absorb the gap — find what your
|
|
118
|
+
model didn't account for.
|
|
119
|
+
|
|
120
|
+
**Post-fix gate:** after applying the fix, re-run the ORIGINAL failing metric,
|
|
121
|
+
not a proxy. A byte-identical result means you changed the wrong thing →
|
|
122
|
+
return to diagnosis; never start tuning the fix's parameters to chase the
|
|
123
|
+
symptom (that's curve-fitting, not fixing).
|
|
@@ -228,3 +228,24 @@ When forward motion transitions from **real translation** (object moves in world
|
|
|
228
228
|
**Measurement gotcha**: if the engine time-scales animation (e.g. `gsap.globalTimeline.timeScale(speed)` for a `?speed` param), the sampled background px/s is `game-speed × timeScale`. Multiply back by `1/timeScale` before comparing to your intended game-time speed, or a correct value reads as "too slow."
|
|
229
229
|
|
|
230
230
|
**Secondary motion gotcha**: a vertical overlay (e.g. wind weave) at large amplitude (±70 px) on a now-slow background DOMINATES perception — reads as "bobbing in place." Keep secondary motion small relative to apparent forward speed (±70 → ±26 px fixed it).
|
|
231
|
+
|
|
232
|
+
## A Rate Step in a Smooth-Input System = Look for a Clamp Boundary First
|
|
233
|
+
|
|
234
|
+
When a visible discontinuity localizes to one variable's RATE stepping
|
|
235
|
+
(×2-3 within 1-2 frames) while every input to it stays smooth, the operative
|
|
236
|
+
mechanism is almost always a hard bound being engaged or left — a clamped
|
|
237
|
+
variable LOOKS like a smooth signal until you test it against the bound.
|
|
238
|
+
|
|
239
|
+
**DO (first, cheap):** print `value − bound(t)` per frame for every
|
|
240
|
+
computable clamp/floor/min-max in the path. An exact `0.0` run means the
|
|
241
|
+
variable is riding the bound; the "mysterious step" is the frame it leaves
|
|
242
|
+
(or engages) it. Only after bounds are ruled out, hunt subtler causes.
|
|
243
|
+
|
|
244
|
+
**Masked-clamp trap**: an input-side clamp hidden behind an output-side clamp
|
|
245
|
+
makes a principled fix measure zero effect — the discontinuity is real but
|
|
246
|
+
one bound masks the other. Confirm the mechanism with the general falsifier /
|
|
247
|
+
post-fix-metric discipline (debugging skill), not by eyeballing the curve.
|
|
248
|
+
|
|
249
|
+
**Metric caveat:** threshold-based detectors on resampled paths (heading
|
|
250
|
+
delta per arc-step, per-frame jumps) flip verdicts with sampling rate —
|
|
251
|
+
judge continuity on the raw velocity/rate series, not on a thresholded flag.
|
|
@@ -234,6 +234,8 @@ Create-side + whole-file counterparts of the node-level writer-emit ops. **Raw `
|
|
|
234
234
|
- **Script-checking "is X gone?"** — pass `--exit-on-empty` (alias `--require-match`) to a find-walker (refs/uses/meta/lit/cases/blast/mentions/search): 0 hits → non-zero exit instead of the default 0. Without the flag a walk always exits 0, so a bare `hxq refs X …; echo $?` can't distinguish found-vs-gone.
|
|
235
235
|
- **Output flood** (e.g. `lit '/*' src/ --any-kind`) — auto-truncated per-hit content (multi-line block-comments → first line + ` … +N lines`); auto-cap at 500 hits with stderr nudge. Both opt-out via `--limit`.
|
|
236
236
|
- **`#if`…`#end` bodies are invisible to walkers and lint — a 0-hit `refs` is NOT proof of "unused".** A conditional-compilation region projects as one `Conditional` node whose interior is raw preserved trivia; `refs`/`uses`/`mentions`/`lit` and lint rules (notably `unused-private`) never see identifiers used only inside an `#if` body. Before deleting something a structural query calls unused in a codebase with conditional compilation, cross-check with a raw-text search (`hxq source`) over the file — `lint --fix` can and does delete private members whose only callers live behind an `#if`.
|
|
237
|
+
- **`patch` anatomy — the three failure modes in one line each.** (1) The payload is ONE argument: `old` / `new` fragments alternating, separated by `====` on its OWN line (even section count; N pairs = one call) — multiple payload arguments are rejected. (2) Exactly one of `--select`/`--match`/`--at` is required, and the old-fragment must occur — uniquely — INSIDE the resolved node: `--at` resolves the NARROWEST node (often a bare `IdentExpr`, too small to contain any pair) and `--match` must itself parse as a pattern node (a typedef header or modifier-bearing decl fragment doesn't) → for statement-level edits default to `--select` on the enclosing member/class and widen the old-fragment with surrounding lines until unique. (3) Copy old-fragments from `hxq source --select` output VERBATIM — it is writer-reformatted (colon spacing, collapsed one-line `if`), so bytes you remember from writing the code may not be the bytes in the node.
|
|
238
|
+
- **Widening an interface with many implementors is impossible under per-op auto-rebuild** — every mutation op rebuilds first and ABORTS on the transient state where implementors lack the new method. Ship a separate capability interface instead (`X implements NewCapability`) so every intermediate compile is green. Same trap in miniature: a multi-step patch that USES a constant before the patch that DECLARES it — run the intermediate op with `HXQ_AUTO_REBUILD=0` (stale binary is safe for a patch; the binary doesn't depend on the file being edited), then rebuild once at the end. Never HXQ_QUIET (kills the staleness check entirely → later probes lie).
|
|
237
239
|
- **`test-summary -` TRUNCATES a large piped stream** — `node bin/test.js | hxq test-summary -` read only ~1583 of 5023 tests and still printed `0 failures` (a partial slice looks green; same hxnodejs stdin pipe limitation as the `Sys.stdin().readAll()` gotcha). For a full-suite run ALWAYS redirect to a file first: `node bin/test.js > out.txt 2>&1; hxq test-summary out.txt`. Piping is safe only for short filtered runs (`APQ_TEST=X node bin/test.js | hxq test-summary -`).
|
|
238
240
|
|
|
239
241
|
## Report on hxq gaps
|
|
@@ -36,7 +36,7 @@ Distinct from the read-only query subcommands above: these REWRITE source. All a
|
|
|
36
36
|
| `hxq introduce-parameter-object <file> (<l>:<c>\|--select\|--match) --params a,b --as <TypeName> [--name <obj>] [--write]` | replace a CONTIGUOUS run of a function's params with one object param of a generated module-level `typedef` (`IntroduceParameterObject`) — rewrites the signature (`a,b` → `obj:TypeName`), the body's references (`a` → `obj.a`, via `Refs` binding-match, braced `${a}` interpolations included), and every resolvable IN-FILE call site (folded args → `{ a: x, b: y }` literal). Reuses the `CallSites` completeness proof (same as `remove-param`); `typedef` field types read via `declaredTypeSources` | params must be contiguous + each explicitly typed; refuses a short `$a` interpolation (needs `${obj.a}`), an unresolvable/arity-mismatched call site (whole-op refuse), an object name colliding with a kept param (`--name`); cross-file method callers out of scope (advisory); verbatim splice + 3+-newline collapse (canonical when params/annotations use the writer's colon style) |
|
|
37
37
|
| `hxq make-final <file> <field> --type <T> [--scope <dir>] [--write]` | turn a mutable `var` field into `final` when never reassigned after its single init (`MakeFinal`) — the make-final pass that UNBLOCKS the `move-member` instance path (final-fields contract). Detects writes structurally (`*Assign`/`Pre/PostIncr/Decr` whose child-0 is `IdentExpr <field>` bare-in-type or `FieldAccess <field>` this/obj); a write inside the ctor = the final's one init, any write OUTSIDE it (cross-file `obj.field =` included) refuses (listed by file). Verbatim `var`→`final` splice (re-parse-gated, no writer-emit) | refuses no-init-and-no-ctor-write (uninit final) / decl-init-AND-ctor-write (double init); conservative — a `.field` write on an unrelated same-named type also refuses (false refusal, never wrong); already-`final` not matched; `--scope` widens the write check cross-file |
|
|
38
38
|
| `hxq encapsulate-field <file> <field> --type <T> [--reformat] [--write]` | turn a stored `var` field into a property with `get`/`set` accessors (`EncapsulateField`) — uses Haxe `@:isVar` so the field STAYS the backing storage: `public var x:Int=0` → `@:isVar public var x(get,set):Int=0` + `get_x()`/`set_x(value)`; NO reference renamed (existing `x` now routes through the accessors) | requires a plain (non-`final`), non-`static`, EXPLICITLY-typed instance `var` (type read via `declaredTypeSources`); refuses an already-property field (accessor clause `(` after the name) or an existing `get_`/`set_`; setter param avoids shadowing a field literally named `value` (→ `newValue`); writer-emitted, canonical-gated (`--reformat`) |
|
|
39
|
-
| `hxq set-doc <f> <l>:<c> (<text> \| --from-file \| -) [--reformat] [--write]` | add or REPLACE the doc-comment of the decl at the cursor (`SetDoc.hx`) — edits ONLY the doc region `[docExtendedSpan.from, declGroupSpan.from)` (existing leading `/*`-doc replaced, else inserted), the decl untouched. Closes the member-doc-ADD gap (`replace-node --with-doc` needs the whole decl retyped) | text via inline / `--from-file` / `-` (stdin) through `resolveCodeArg`; payload = RAW doc text — a `/** */`-wrapped payload is rejected (`RefactorSupport.docComment` adds the delimiters); canonical-gate |
|
|
39
|
+
| `hxq set-doc <f> <l>:<c> (<text> \| --from-file \| -) [--reformat] [--write]` | add or REPLACE the doc-comment of the decl at the cursor (`SetDoc.hx`) — edits ONLY the doc region `[docExtendedSpan.from, declGroupSpan.from)` (existing leading `/*`-doc replaced, else inserted), the decl untouched. Closes the member-doc-ADD gap (`replace-node --with-doc` needs the whole decl retyped) | text via inline / `--from-file` / `-` (stdin) through `resolveCodeArg`; payload = RAW doc text — a `/** */`-wrapped payload is rejected (`RefactorSupport.docComment` adds the delimiters); leading/trailing blank payload lines are TRIMMED (a heredoc/stdin trailing `\n` is safe; internal blanks stay as paragraphs); on a `final class` the doc slot lifts to the `FinalDecl` wrapper, so a `ClassDecl:`/`ClassForm:`-resolved cursor lands the doc before `final`; **a no-change result is `Err` + exit 1** ("the edit produced no change") — fires BOTH when re-setting a byte-identical doc (idempotent re-runs read as an error by design; check the message) and when the position cannot carry a doc (a plain-expression cursor — previously a SILENT "wrote" while the writer dropped the comment); canonical-gate |
|
|
40
40
|
| `hxq set-modifier <f> <l>:<c> <change>... [--reformat] [--write]` | flip visibility / add-remove modifiers WITHOUT retyping the decl (`SetModifier.hx`) — `public`/`private` (set visibility), `+<mod>`/`-<mod>` (static/inline/override/macro/extern/dynamic). **The safe replacement for the `replace-node --at <modifier>` footgun** (which grabs the whole-decl wrapper → overwrote the member). Recomputes only the NON-`@:meta` modifier run + splices it; `@:meta`/decl/body untouched | changing visibility/mods OF a `final` decl works (final is part of the decl node); adding/removing `final` itself → `Err` (it wraps; use replace-node); a bare change must be public/private; canonical-gate |
|
|
41
41
|
| `hxq set-comment <f> <l>:<c> (<text> \| --from-file \| -) [--reformat] [--write]` | replace the COMMENT at the cursor (`SetComment.hx`) — the comment counterpart of `set-doc`, for inline `//` comments (trivia no other op reaches): a block comment whole, a contiguous full-line `//` run merged as ONE unit, a trailing `//` after code alone; string literals skipped (`RefactorSupport.commentBlockAt`). The replacement must itself be a comment (`//` or `/*`) | the writer re-indents the spliced comment to its attachment context; canonical-gate |
|
|
42
42
|
| `hxq rewrite <f> '<pattern>' '<replacement>' [--reformat] [--write]` | structural search-and-replace (`Rewrite.hx`) — the FUSION of `search` + span-replace (gofmt -r / comby). Every node matching `<pattern>` (`hxq search` syntax, `$x` metavars) is rewritten from `<replacement>`: `$x` / `${x}` → the captured metavar's verbatim source, `${x+N}` / `${x-N}` → an integer-literal metavar shifted by N. All matches in one pass | reuses `Matcher` (`Match.span` + bindings); keeps only non-overlapping matches; `${x±N}` refuses a non-integer metavar; canonical-gate. Killer use: bump a positional arg across all calls — `rewrite f 'g($a, $b, $c)' 'g($a, $b, ${c+1})'` |
|
|
@@ -61,13 +61,13 @@ Distinct from the read-only query subcommands above: these REWRITE source. All a
|
|
|
61
61
|
|
|
62
62
|
**Ops caveat — `add-member` can leave a DOUBLE blank line at the append boundary.** When the class body already ends with a trailing blank before `}`, the appended member arrives separated by TWO blank lines (trivia — survives the canonical gate, so `fmt` won't fix it; reviewers flag it). After a run of `add-member`s, check the boundaries (`hxq source <f> --select 'FnMember:<new>'` context or a `'\n\n\n'` scan) and normalise to one blank via a python one-liner + `hxq fmt -l` re-check.
|
|
63
63
|
|
|
64
|
-
**Ops caveat — `add-element` next to a doc-commented sibling can ORPHAN that sibling's doc.** Inserting a module-level decl with `--after --select 'TypedefDecl:X'` (or `--before`) when the ADJACENT decl carries a leading `/**`-doc landed the new decl on the WRONG side of that doc — the whole-file writer re-attaches a standalone `/**` block to whatever decl follows it in the trivia stream, so the new element slotted in AFTER the neighbour's doc, leaving that doc floating above the new decl and the neighbour doc-less. Parses + passes the canonical gate (pure trivia) — but `hxq lint` FLAGS it as `fragmented-doc-comment` ("documented by 2 adjacent comment blocks"), so **`hxq lint <file>` after any `add-element` that inserts a module-level decl next to a doc-commented sibling is the reliable self-check** (don't rely on eyeballing `hxq source`). FIX recipe: `replace-node --select 'TypedefDecl:<orphaned-neighbour>' --with-doc` — `--with-doc` absorbs BOTH adjacent `/**` blocks, so give the new source with only the correct doc; then `set-doc --select 'TypedefDecl:<the-doc-less-decl>'` (raw text, no `/** */` wrapper
|
|
64
|
+
**Ops caveat — `add-element` next to a doc-commented sibling can ORPHAN that sibling's doc.** Inserting a module-level decl with `--after --select 'TypedefDecl:X'` (or `--before`) when the ADJACENT decl carries a leading `/**`-doc landed the new decl on the WRONG side of that doc — the whole-file writer re-attaches a standalone `/**` block to whatever decl follows it in the trivia stream, so the new element slotted in AFTER the neighbour's doc, leaving that doc floating above the new decl and the neighbour doc-less. Parses + passes the canonical gate (pure trivia) — but `hxq lint` FLAGS it as `fragmented-doc-comment` ("documented by 2 adjacent comment blocks"), so **`hxq lint <file>` after any `add-element` that inserts a module-level decl next to a doc-commented sibling is the reliable self-check** (don't rely on eyeballing `hxq source`). FIX recipe: `replace-node --select 'TypedefDecl:<orphaned-neighbour>' --with-doc` — `--with-doc` absorbs BOTH adjacent `/**` blocks, so give the new source with only the correct doc; then `set-doc --select 'TypedefDecl:<the-doc-less-decl>'` (raw text, no `/** */` wrapper) to reattach. A missing blank line before the reattached doc is writer-canonical (writer preserves but never inserts blank-before-doc) → add one via a validated python one-liner + `hxq fmt -l` re-check. (Hit TWICE across sessions inserting a `private typedef` after a doc-commented sibling typedef — the `--with-doc`+`set-doc` recipe fixed it both times.)
|
|
65
65
|
|
|
66
66
|
**Net rule: `- <<'EOF'` is the DEFAULT for every op — one bash call, quote-safe.** Reach for `--from-file`/temp-file ONLY to (a) reuse the same code across several ops, or (b) iterate on it (edit the file + re-apply, e.g. fix one line and re-run `replace-node`). Writing a temp file just to feed a single op is the needless crutch to stop.
|
|
67
67
|
|
|
68
68
|
**Ops caveat — `add-member`/`add-element` reject an `EnumAbstractDecl` body.** `typeDeclOf`/the container-resolver don't recognise `enum abstract` (the decl projects as `EnumAbstractDecl`, distinct from `AbstractDecl`/`ClassDecl`), so `add-member --type <EnumAbstract>` errors `no type named "<X>"` and `add-element --append <enum-pos>` errors `not on the first token of a container`. WORKAROUND to add a static method/value to an enum abstract: `replace-node --select 'FnMember:<siblingMethod>'` with the sibling member + the new member appended in `<newSource>` (per-member replace round-trips fine).
|
|
69
69
|
|
|
70
|
-
**Ops caveat — `
|
|
70
|
+
**Ops caveat — a `patch` result can refuse the NEXT op's canonical gate.** A patch whose new fragment carries a line the writer would re-wrap (e.g. an over-long `case … if (…): Err(…)` one-liner) writes successfully, but the following writer-emit op on the same file errors `file is not in canonical form`. Recovery: `hxq fmt <f> --write`, then re-run the refused op. Symptom-level rule: after patching in long or hand-wrapped lines, `hxq fmt <f> --list` before chaining further ops.
|
|
71
71
|
|
|
72
72
|
**Ops caveat — `set-comment` quirks.** (a) A `- <<'EOF'` heredoc whose BODY contains shell-ish words (`tail`/`head`/`cat`/`sed`) can be false-denied by the .hx view-gate — use `--from-file` for such payloads. (b) On a comment block starting at column 1, the cursor `<line>:1` can err "not on a comment" — take the exact col from `hxq lit '<text>' <file> --kind Comment` output.
|
|
73
73
|
|
|
@@ -118,7 +118,18 @@ Pick the agent type by task shape:
|
|
|
118
118
|
branch tip AT merge time — never from an earlier observation; after
|
|
119
119
|
merging, diff the merged SHA against the SHA the final report names.
|
|
120
120
|
- Use SendMessage (agent ID or name) to continue an existing agent with its
|
|
121
|
-
context intact — don't respawn for a follow-up question.
|
|
121
|
+
context intact — don't respawn for a follow-up question. **But SendMessage-
|
|
122
|
+
resume of a COMPLETED agent is always background** — that path has no
|
|
123
|
+
`run_in_background: false`, so it cannot honour the "one gating spawn →
|
|
124
|
+
sync" rule: you send, then idle-wait for a wake-up. So when the follow-up
|
|
125
|
+
gates your next step, decide by SIZE, not by "an agent already has the
|
|
126
|
+
context": a small, already-precisely-diagnosed fix (≤~30 lines — the same
|
|
127
|
+
threshold as tiny-edits-stay-inline above) → edit it inline YOURSELF; the
|
|
128
|
+
background round-trip costs more than it saves, and repeating it becomes
|
|
129
|
+
spawn-one-and-wait, the exact anti-pattern the sync rule forbids. Reserve
|
|
130
|
+
SendMessage-resume for a LARGE or coupled follow-up where re-establishing
|
|
131
|
+
the agent's own context is worth the background wait — and then don't idle:
|
|
132
|
+
it's the rolling-window case (do other work, expect the wake-up).
|
|
122
133
|
- Launch ALL independent agents in **one message**, not sequentially.
|
|
123
134
|
- **Worktree-isolated agents fork from the session-start HEAD, not the current branch tip.** Commits you make mid-session are NOT in a later-spawned agent's worktree base — the agent may see stale code, wrongly conclude your work "was never merged", or produce patches that conflict. Rule: COMMIT each phase before spawning the next dependent wave; when a wave's base is already stale, merge its patches with `git apply --3way` and expect to hand-reconcile files several agents touched. Also instruct agents to report their base commit (`git log --oneline -1`) so staleness is visible. One more trap in that merge flow: `git apply --3way` STAGES everything it applies — a later `git add <subset> && git commit` silently commits the WHOLE staged index, not your subset (the tell: the first chunk commit's stat lists every merged file and later chunk commits say "nothing to commit"). Run `git reset -q` to unstage all before building chunked commits, and if rebuilding botched history, soft-reset to the true pre-merge base, never to a mid-wave commit.
|
|
124
135
|
|
package/templates/testing.yaml
CHANGED
|
@@ -79,6 +79,10 @@ states:
|
|
|
79
79
|
Unit tests are failing. Analyze the failures and fix the code.
|
|
80
80
|
|
|
81
81
|
Do NOT fix tests to match wrong behavior — fix the implementation.
|
|
82
|
+
A small, already-diagnosed fix → edit inline YOURSELF; do NOT hand it to
|
|
83
|
+
a background SendMessage-resume and idle-wait — that path is
|
|
84
|
+
background-only and can't gate synchronously (see task-delegation
|
|
85
|
+
Lifecycle). Delegate only a large/coupled fix.
|
|
82
86
|
After fixing, transition back to re-run unit tests.
|
|
83
87
|
|
|
84
88
|
Choose transition:
|
|
@@ -146,6 +150,10 @@ states:
|
|
|
146
150
|
prompt: |
|
|
147
151
|
Integration test failed. Analyze what broke and fix it.
|
|
148
152
|
|
|
153
|
+
A small, already-diagnosed fix → edit inline YOURSELF; do NOT hand it to
|
|
154
|
+
a background SendMessage-resume and idle-wait — that path is
|
|
155
|
+
background-only and can't gate synchronously (see task-delegation
|
|
156
|
+
Lifecycle). Delegate only a large/coupled fix.
|
|
149
157
|
After fixing, transition back to re-run integration.
|
|
150
158
|
|
|
151
159
|
Choose transition:
|
|
@@ -203,7 +211,10 @@ states:
|
|
|
203
211
|
fix_user_issue:
|
|
204
212
|
prompt: |
|
|
205
213
|
The user found an issue during manual testing. Ask what exactly is
|
|
206
|
-
wrong if unclear. Fix the code,
|
|
214
|
+
wrong if unclear. Fix the code — a small, already-diagnosed fix → edit
|
|
215
|
+
inline YOURSELF; do NOT hand it to a background SendMessage-resume and
|
|
216
|
+
idle-wait, that path is background-only and can't gate synchronously
|
|
217
|
+
(see task-delegation Lifecycle). Delegate only a large/coupled fix. Then:
|
|
207
218
|
|
|
208
219
|
- `retry` → re-assess verification (unit tests if the fix touched
|
|
209
220
|
logic, then integration/manual verify → user testing again)
|