@specforge/canary-cli 0.1.10 → 0.1.12

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.
Files changed (51) hide show
  1. package/dist/cli/commands/scaffold/agent-types.js +1 -1
  2. package/dist/cli/commands/scaffold/agent-types.js.map +1 -1
  3. package/dist/cli/config/agent-teams.types.d.ts +35 -12
  4. package/dist/cli/config/agent-teams.types.d.ts.map +1 -1
  5. package/dist/cli/config/agent-teams.types.js.map +1 -1
  6. package/dist/cli/templates/agents/content/core/sfag-orchestrator.d.ts +21 -3
  7. package/dist/cli/templates/agents/content/core/sfag-orchestrator.d.ts.map +1 -1
  8. package/dist/cli/templates/agents/content/core/sfag-orchestrator.js +114 -48
  9. package/dist/cli/templates/agents/content/core/sfag-orchestrator.js.map +1 -1
  10. package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.d.ts +22 -3
  11. package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.d.ts.map +1 -1
  12. package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.js +225 -160
  13. package/dist/cli/templates/agents/content/core/sfag-ticket-implementer.js.map +1 -1
  14. package/dist/cli/templates/agents/content/core/sfag-work-resolver.d.ts +16 -0
  15. package/dist/cli/templates/agents/content/core/sfag-work-resolver.d.ts.map +1 -0
  16. package/dist/cli/templates/agents/content/core/sfag-work-resolver.js +199 -0
  17. package/dist/cli/templates/agents/content/core/sfag-work-resolver.js.map +1 -0
  18. package/dist/cli/templates/agents/index.d.ts.map +1 -1
  19. package/dist/cli/templates/agents/index.js +2 -0
  20. package/dist/cli/templates/agents/index.js.map +1 -1
  21. package/dist/cli/templates/content/sf-reset.d.ts +5 -2
  22. package/dist/cli/templates/content/sf-reset.d.ts.map +1 -1
  23. package/dist/cli/templates/content/sf-reset.js +41 -27
  24. package/dist/cli/templates/content/sf-reset.js.map +1 -1
  25. package/dist/lib/prompt-generator.d.ts +15 -3
  26. package/dist/lib/prompt-generator.d.ts.map +1 -1
  27. package/dist/lib/prompt-generator.js +14 -6
  28. package/dist/lib/prompt-generator.js.map +1 -1
  29. package/dist/tools/core/__tests__/git-injection.test.d.ts +2 -0
  30. package/dist/tools/core/__tests__/git-injection.test.d.ts.map +1 -0
  31. package/dist/tools/core/git-injection.d.ts +50 -0
  32. package/dist/tools/core/git-injection.d.ts.map +1 -0
  33. package/dist/tools/core/git-injection.js +74 -0
  34. package/dist/tools/core/git-injection.js.map +1 -0
  35. package/dist/tools/index.d.ts.map +1 -1
  36. package/dist/tools/index.js +68 -81
  37. package/dist/tools/index.js.map +1 -1
  38. package/dist/types/index.d.ts +1 -20
  39. package/dist/types/index.d.ts.map +1 -1
  40. package/dist/types/index.js.map +1 -1
  41. package/dist/validation/index.d.ts.map +1 -1
  42. package/dist/validation/index.js +0 -6
  43. package/dist/validation/index.js.map +1 -1
  44. package/package.json +4 -3
  45. package/src/cli/templates/agents/content/core/sfag-orchestrator.ts +135 -51
  46. package/src/cli/templates/agents/content/core/sfag-ticket-implementer.ts +247 -163
  47. package/src/cli/templates/agents/content/core/sfag-work-resolver.ts +211 -0
  48. package/src/cli/templates/agents/index.ts +2 -0
  49. package/src/cli/templates/content/sf-reset.ts +45 -28
  50. package/src/cli/templates/skills/specforge-orchestrator.md +14 -9
  51. package/src/cli/templates/skills/specforge-worker.md +3 -2
@@ -0,0 +1,50 @@
1
+ /** Runs a `git` sub-command; returns trimmed stdout, or `null` on any failure. */
2
+ export type GitRunner = (args: string[]) => string | null;
3
+ /** Default runner: spawn `git`, return trimmed stdout, `null` on any failure. */
4
+ export declare const defaultGitRunner: GitRunner;
5
+ export interface WorktreeGitEvidence {
6
+ /**
7
+ * `true` when the worktree has no uncommitted changes — OR when the caller is
8
+ * not inside a git repo (a non-git caller is never "dirty", so SWS still runs).
9
+ */
10
+ gitClean: boolean;
11
+ /** Worktree root (`git rev-parse --show-toplevel`); `null` when not in a worktree. */
12
+ worktreePath: string | null;
13
+ /** Current branch (`git rev-parse --abbrev-ref HEAD`); `null` when not in a worktree. */
14
+ branch: string | null;
15
+ }
16
+ /**
17
+ * SWS git evidence — the clean-status precondition input + the worktree
18
+ * provenance (M23.2). Emits `null` provenance (and `gitClean: true`) when the
19
+ * agent is not inside a git worktree, so SWS still records the WorkSession.
20
+ */
21
+ export declare function readWorktreeGitEvidence(run?: GitRunner): WorktreeGitEvidence;
22
+ /** One injected file-change action (a subset of the AWS `record_file_change` payload). */
23
+ export interface LocalFileChangeAction {
24
+ action: 'record_file_change';
25
+ workSessionId: string;
26
+ ticketId: string;
27
+ expectedPath: string;
28
+ expectedAction: 'create' | 'modify' | 'delete';
29
+ actualAction: 'created' | 'modified' | 'deleted';
30
+ status: 'matched';
31
+ }
32
+ interface DeriveCtx {
33
+ workSessionId: string;
34
+ ticketId: string;
35
+ }
36
+ /**
37
+ * Parse `git status --porcelain` into the `record_file_change` set the MCP-local
38
+ * injects in `validateFiles: 'local'` mode — one action per created/modified/
39
+ * deleted path (the agent reports the `referenced` files itself). A rename (`R`)
40
+ * surfaces as a create of the new path.
41
+ */
42
+ export declare function deriveLocalFileChanges(statusPorcelain: string | null, ctx: DeriveCtx): LocalFileChangeAction[];
43
+ /**
44
+ * Read the worktree's changed-file set (`git status --porcelain`) and map it to
45
+ * the `record_file_change` actions the MCP-local injects (AWS `validateFiles:
46
+ * 'local'`). Empty when not inside a git worktree.
47
+ */
48
+ export declare function readLocalFileChanges(ctx: DeriveCtx, run?: GitRunner): LocalFileChangeAction[];
49
+ export {};
50
+ //# sourceMappingURL=git-injection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-injection.d.ts","sourceRoot":"","sources":["../../../src/tools/core/git-injection.ts"],"names":[],"mappings":"AA2BA,kFAAkF;AAClF,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,GAAG,IAAI,CAAC;AAE1D,iFAAiF;AACjF,eAAO,MAAM,gBAAgB,EAAE,SAU9B,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,sFAAsF;IACtF,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,yFAAyF;IACzF,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,GAAE,SAA4B,GAAG,mBAAmB,CAc9F;AAED,0FAA0F;AAC1F,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,oBAAoB,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC/C,YAAY,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;IACjD,MAAM,EAAE,SAAS,CAAC;CACnB;AAED,UAAU,SAAS;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,eAAe,EAAE,MAAM,GAAG,IAAI,EAC9B,GAAG,EAAE,SAAS,GACb,qBAAqB,EAAE,CA4BzB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,GAAE,SAA4B,GAAG,qBAAqB,EAAE,CAE/G"}
@@ -0,0 +1,74 @@
1
+ import { execFileSync } from "node:child_process";
2
+ const defaultGitRunner = (args) => {
3
+ try {
4
+ const out = execFileSync("git", args, {
5
+ encoding: "utf8",
6
+ stdio: ["ignore", "pipe", "ignore"]
7
+ });
8
+ return out.trim();
9
+ } catch {
10
+ return null;
11
+ }
12
+ };
13
+ function readWorktreeGitEvidence(run = defaultGitRunner) {
14
+ const worktreePath = run(["rev-parse", "--show-toplevel"]);
15
+ if (worktreePath === null || worktreePath === "") {
16
+ return { gitClean: true, worktreePath: null, branch: null };
17
+ }
18
+ const branch = run(["rev-parse", "--abbrev-ref", "HEAD"]);
19
+ const status = run(["status", "--porcelain"]);
20
+ return {
21
+ // A failed `git status` (null) must not block SWS → treat as clean.
22
+ gitClean: status === null ? true : status.trim() === "",
23
+ worktreePath,
24
+ branch: branch === null || branch === "" ? null : branch
25
+ };
26
+ }
27
+ function deriveLocalFileChanges(statusPorcelain, ctx) {
28
+ if (!statusPorcelain) return [];
29
+ const actions = [];
30
+ for (const raw of statusPorcelain.split("\n")) {
31
+ const line = raw.replace(/\r$/, "");
32
+ if (line.trim() === "") continue;
33
+ const xy = line.slice(0, 2);
34
+ let path = line.slice(3).trim();
35
+ const arrow = path.indexOf(" -> ");
36
+ if (arrow >= 0) path = path.slice(arrow + 4).trim();
37
+ if (path.startsWith('"') && path.endsWith('"')) path = path.slice(1, -1);
38
+ if (path === "") continue;
39
+ const kind = classifyPorcelain(xy);
40
+ if (!kind) continue;
41
+ actions.push({
42
+ action: "record_file_change",
43
+ workSessionId: ctx.workSessionId,
44
+ ticketId: ctx.ticketId,
45
+ expectedPath: path,
46
+ expectedAction: kind.expected,
47
+ actualAction: kind.actual,
48
+ status: "matched"
49
+ });
50
+ }
51
+ return actions;
52
+ }
53
+ function readLocalFileChanges(ctx, run = defaultGitRunner) {
54
+ return deriveLocalFileChanges(run(["status", "--porcelain"]), ctx);
55
+ }
56
+ function classifyPorcelain(xy) {
57
+ const s = xy.trim();
58
+ if (s === "") return null;
59
+ if (s === "??" || s.includes("A") || s.includes("R") || s.includes("C")) {
60
+ return { expected: "create", actual: "created" };
61
+ }
62
+ if (s.includes("D")) return { expected: "delete", actual: "deleted" };
63
+ if (s.includes("M") || s.includes("T") || s.includes("U")) {
64
+ return { expected: "modify", actual: "modified" };
65
+ }
66
+ return null;
67
+ }
68
+ export {
69
+ defaultGitRunner,
70
+ deriveLocalFileChanges,
71
+ readLocalFileChanges,
72
+ readWorktreeGitEvidence
73
+ };
74
+ //# sourceMappingURL=git-injection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/tools/core/git-injection.ts"],"sourcesContent":["/**\n * MCP-local git-evidence injection (M23.2).\n *\n * The work lifecycle's SWS/AWS verbs need worktree git evidence that only the\n * MCP-LOCAL (this CLI, running on the agent's machine — the deployed Lambda has\n * NO worktree) can observe. Per `docs/architecture/work-lifecycle-flow.md` §0 +\n * [[project_coherence_score]]:\n *\n * - **SWS** (`start_work_session`): runs `git status` for the clean-workspace\n * precondition (`gitClean`) and reports the worktree provenance —\n * `worktreePath` via `git rev-parse --show-toplevel` + `branch` via\n * `git rev-parse --abbrev-ref HEAD` — so SWS persists\n * `WorkSession.worktreePath`/`branch` (M16.2). When the agent is NOT inside a\n * git worktree (\"caso esteja em uma\") the provenance is `null` (SWS still\n * records the WorkSession) and `gitClean` defaults to `true` (a non-git caller\n * is never \"dirty\" — it must not be blocked by the precondition).\n * - **AWS** (`action_work_session`, `validateFiles: 'local'`): runs\n * `git status --porcelain` and injects one `record_file_change` action per\n * created/modified/deleted file (the agent only reports the `referenced`\n * files git cannot see).\n *\n * The git commands run through an injectable `GitRunner` (defaults to a real,\n * non-throwing `git` spawn) so the layer is unit-testable without a live repo and\n * never throws inside a tool handler.\n */\nimport { execFileSync } from 'node:child_process';\n\n/** Runs a `git` sub-command; returns trimmed stdout, or `null` on any failure. */\nexport type GitRunner = (args: string[]) => string | null;\n\n/** Default runner: spawn `git`, return trimmed stdout, `null` on any failure. */\nexport const defaultGitRunner: GitRunner = (args) => {\n try {\n const out = execFileSync('git', args, {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n });\n return out.trim();\n } catch {\n return null;\n }\n};\n\nexport interface WorktreeGitEvidence {\n /**\n * `true` when the worktree has no uncommitted changes — OR when the caller is\n * not inside a git repo (a non-git caller is never \"dirty\", so SWS still runs).\n */\n gitClean: boolean;\n /** Worktree root (`git rev-parse --show-toplevel`); `null` when not in a worktree. */\n worktreePath: string | null;\n /** Current branch (`git rev-parse --abbrev-ref HEAD`); `null` when not in a worktree. */\n branch: string | null;\n}\n\n/**\n * SWS git evidence — the clean-status precondition input + the worktree\n * provenance (M23.2). Emits `null` provenance (and `gitClean: true`) when the\n * agent is not inside a git worktree, so SWS still records the WorkSession.\n */\nexport function readWorktreeGitEvidence(run: GitRunner = defaultGitRunner): WorktreeGitEvidence {\n const worktreePath = run(['rev-parse', '--show-toplevel']);\n if (worktreePath === null || worktreePath === '') {\n // Not inside a git worktree — SWS still records the WorkSession.\n return { gitClean: true, worktreePath: null, branch: null };\n }\n const branch = run(['rev-parse', '--abbrev-ref', 'HEAD']);\n const status = run(['status', '--porcelain']);\n return {\n // A failed `git status` (null) must not block SWS → treat as clean.\n gitClean: status === null ? true : status.trim() === '',\n worktreePath,\n branch: branch === null || branch === '' ? null : branch,\n };\n}\n\n/** One injected file-change action (a subset of the AWS `record_file_change` payload). */\nexport interface LocalFileChangeAction {\n action: 'record_file_change';\n workSessionId: string;\n ticketId: string;\n expectedPath: string;\n expectedAction: 'create' | 'modify' | 'delete';\n actualAction: 'created' | 'modified' | 'deleted';\n status: 'matched';\n}\n\ninterface DeriveCtx {\n workSessionId: string;\n ticketId: string;\n}\n\n/**\n * Parse `git status --porcelain` into the `record_file_change` set the MCP-local\n * injects in `validateFiles: 'local'` mode — one action per created/modified/\n * deleted path (the agent reports the `referenced` files itself). A rename (`R`)\n * surfaces as a create of the new path.\n */\nexport function deriveLocalFileChanges(\n statusPorcelain: string | null,\n ctx: DeriveCtx,\n): LocalFileChangeAction[] {\n if (!statusPorcelain) return [];\n const actions: LocalFileChangeAction[] = [];\n for (const raw of statusPorcelain.split('\\n')) {\n const line = raw.replace(/\\r$/, '');\n if (line.trim() === '') continue;\n // porcelain v1: `XY<space>path` — XY is the 2-char status, path starts at col 3.\n const xy = line.slice(0, 2);\n let path = line.slice(3).trim();\n // Rename/copy renders as `old -> new`; record the new path.\n const arrow = path.indexOf(' -> ');\n if (arrow >= 0) path = path.slice(arrow + 4).trim();\n // git quotes paths with special chars.\n if (path.startsWith('\"') && path.endsWith('\"')) path = path.slice(1, -1);\n if (path === '') continue;\n const kind = classifyPorcelain(xy);\n if (!kind) continue;\n actions.push({\n action: 'record_file_change',\n workSessionId: ctx.workSessionId,\n ticketId: ctx.ticketId,\n expectedPath: path,\n expectedAction: kind.expected,\n actualAction: kind.actual,\n status: 'matched',\n });\n }\n return actions;\n}\n\n/**\n * Read the worktree's changed-file set (`git status --porcelain`) and map it to\n * the `record_file_change` actions the MCP-local injects (AWS `validateFiles:\n * 'local'`). Empty when not inside a git worktree.\n */\nexport function readLocalFileChanges(ctx: DeriveCtx, run: GitRunner = defaultGitRunner): LocalFileChangeAction[] {\n return deriveLocalFileChanges(run(['status', '--porcelain']), ctx);\n}\n\nfunction classifyPorcelain(\n xy: string,\n): { expected: 'create' | 'modify' | 'delete'; actual: 'created' | 'modified' | 'deleted' } | null {\n const s = xy.trim();\n if (s === '') return null;\n // Untracked / added / renamed / copied → a new (created) file.\n if (s === '??' || s.includes('A') || s.includes('R') || s.includes('C')) {\n return { expected: 'create', actual: 'created' };\n }\n if (s.includes('D')) return { expected: 'delete', actual: 'deleted' };\n if (s.includes('M') || s.includes('T') || s.includes('U')) {\n return { expected: 'modify', actual: 'modified' };\n }\n return null;\n}\n"],"mappings":"AAyBA,SAAS,oBAAoB;AAMtB,MAAM,mBAA8B,CAAC,SAAS;AACnD,MAAI;AACF,UAAM,MAAM,aAAa,OAAO,MAAM;AAAA,MACpC,UAAU;AAAA,MACV,OAAO,CAAC,UAAU,QAAQ,QAAQ;AAAA,IACpC,CAAC;AACD,WAAO,IAAI,KAAK;AAAA,EAClB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAmBO,SAAS,wBAAwB,MAAiB,kBAAuC;AAC9F,QAAM,eAAe,IAAI,CAAC,aAAa,iBAAiB,CAAC;AACzD,MAAI,iBAAiB,QAAQ,iBAAiB,IAAI;AAEhD,WAAO,EAAE,UAAU,MAAM,cAAc,MAAM,QAAQ,KAAK;AAAA,EAC5D;AACA,QAAM,SAAS,IAAI,CAAC,aAAa,gBAAgB,MAAM,CAAC;AACxD,QAAM,SAAS,IAAI,CAAC,UAAU,aAAa,CAAC;AAC5C,SAAO;AAAA;AAAA,IAEL,UAAU,WAAW,OAAO,OAAO,OAAO,KAAK,MAAM;AAAA,IACrD;AAAA,IACA,QAAQ,WAAW,QAAQ,WAAW,KAAK,OAAO;AAAA,EACpD;AACF;AAwBO,SAAS,uBACd,iBACA,KACyB;AACzB,MAAI,CAAC,gBAAiB,QAAO,CAAC;AAC9B,QAAM,UAAmC,CAAC;AAC1C,aAAW,OAAO,gBAAgB,MAAM,IAAI,GAAG;AAC7C,UAAM,OAAO,IAAI,QAAQ,OAAO,EAAE;AAClC,QAAI,KAAK,KAAK,MAAM,GAAI;AAExB,UAAM,KAAK,KAAK,MAAM,GAAG,CAAC;AAC1B,QAAI,OAAO,KAAK,MAAM,CAAC,EAAE,KAAK;AAE9B,UAAM,QAAQ,KAAK,QAAQ,MAAM;AACjC,QAAI,SAAS,EAAG,QAAO,KAAK,MAAM,QAAQ,CAAC,EAAE,KAAK;AAElD,QAAI,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,GAAG,EAAG,QAAO,KAAK,MAAM,GAAG,EAAE;AACvE,QAAI,SAAS,GAAI;AACjB,UAAM,OAAO,kBAAkB,EAAE;AACjC,QAAI,CAAC,KAAM;AACX,YAAQ,KAAK;AAAA,MACX,QAAQ;AAAA,MACR,eAAe,IAAI;AAAA,MACnB,UAAU,IAAI;AAAA,MACd,cAAc;AAAA,MACd,gBAAgB,KAAK;AAAA,MACrB,cAAc,KAAK;AAAA,MACnB,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAOO,SAAS,qBAAqB,KAAgB,MAAiB,kBAA2C;AAC/G,SAAO,uBAAuB,IAAI,CAAC,UAAU,aAAa,CAAC,GAAG,GAAG;AACnE;AAEA,SAAS,kBACP,IACiG;AACjG,QAAM,IAAI,GAAG,KAAK;AAClB,MAAI,MAAM,GAAI,QAAO;AAErB,MAAI,MAAM,QAAQ,EAAE,SAAS,GAAG,KAAK,EAAE,SAAS,GAAG,KAAK,EAAE,SAAS,GAAG,GAAG;AACvE,WAAO,EAAE,UAAU,UAAU,QAAQ,UAAU;AAAA,EACjD;AACA,MAAI,EAAE,SAAS,GAAG,EAAG,QAAO,EAAE,UAAU,UAAU,QAAQ,UAAU;AACpE,MAAI,EAAE,SAAS,GAAG,KAAK,EAAE,SAAS,GAAG,KAAK,EAAE,SAAS,GAAG,GAAG;AACzD,WAAO,EAAE,UAAU,UAAU,QAAQ,WAAW;AAAA,EAClD;AACA,SAAO;AACT;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAML,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAShC;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACH;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,IAAI,IAAI,EAAE,CAgnCjC;AAED;;GAEG;AACH,KAAK,WAAW,GAAG,CACjB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1B,OAAO,CAAC,OAAO,CAAC,CAAC;AA6EtB;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,SAAS,GACnB,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAkU7B;AAiBD;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,GAAE,OAAe,GACrB,OAAO,CAAC,OAAO,CAAC,CA4DlB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,GAAE,OAAe,GACrB,OAAO,CAAC,OAAO,GAAG,gBAAgB,CAAC,CAOrC;AAGD,OAAO,EACL,eAAe,EACf,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAML,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAUhC;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACH;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,IAAI,IAAI,EAAE,CA4nCjC;AAED;;GAEG;AACH,KAAK,WAAW,GAAG,CACjB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1B,OAAO,CAAC,OAAO,CAAC,CAAC;AA6EtB;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,SAAS,GACnB,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAoT7B;AAiBD;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,GAAE,OAAe,GACrB,OAAO,CAAC,OAAO,CAAC,CA4DlB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,GAAE,OAAe,GACrB,OAAO,CAAC,OAAO,GAAG,gBAAgB,CAAC,CAOrC;AAGD,OAAO,EACL,eAAe,EACf,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAC"}
@@ -7,6 +7,7 @@ import {
7
7
  } from "../validation/index.js";
8
8
  import { injectContext, injectContextRequired } from "./core/context-helper.js";
9
9
  import { probeExistingFiles } from "./core/file-existence-injection.js";
10
+ import { readWorktreeGitEvidence } from "./core/git-injection.js";
10
11
  import { tryLoadProjectConfig, saveProjectConfig } from "../cli/config/index.js";
11
12
  import {
12
13
  appendPlanningSessionRegistry,
@@ -105,7 +106,7 @@ At least one scope filter (projectId, specificationId, or epicId) is required.`,
105
106
  type: "array",
106
107
  items: {
107
108
  type: "string",
108
- enum: ["pending", "ready", "active", "done"]
109
+ enum: ["pending", "ready", "active", "done", "blocked"]
109
110
  },
110
111
  description: "Filter by status"
111
112
  },
@@ -136,6 +137,37 @@ At least one scope filter (projectId, specificationId, or epicId) is required.`,
136
137
  offset: {
137
138
  type: "number",
138
139
  description: "Pagination offset (default: 0)"
140
+ },
141
+ fields: {
142
+ type: "array",
143
+ items: {
144
+ type: "string",
145
+ enum: [
146
+ "id",
147
+ "epicId",
148
+ "ticketNumber",
149
+ "title",
150
+ "description",
151
+ "status",
152
+ "priority",
153
+ "complexity",
154
+ "estimatedHours",
155
+ "actualHours",
156
+ "acceptanceCriteria",
157
+ "implementation",
158
+ "technicalDetails",
159
+ "notes",
160
+ "tags",
161
+ "progress",
162
+ "testsPassed",
163
+ "order",
164
+ "startedAt",
165
+ "completedAt",
166
+ "createdAt",
167
+ "updatedAt"
168
+ ]
169
+ },
170
+ description: "Select specific fields to return. Returns all fields if not specified. id is always included."
139
171
  }
140
172
  }
141
173
  }
@@ -535,8 +567,8 @@ Format options:
535
567
  description: `Update checklist state during an active WorkSession. Combines step completion, AC validation, test result reporting, file tracking, reference review confirmation, and discovery reporting into a single atomic operation. All state changes are recorded on the WorkSession and its related validation/completion records.
536
568
 
537
569
  Use this instead of calling update_ticket for checklist changes. Provides:
538
- - Step completion (individual or bulk via WorkSessionStepCompletion)
539
- - Acceptance criteria validation (individual or bulk via WorkSessionACValidation)
570
+ - Step completion (individual or bulk via WorkSessionImplStepCompletion)
571
+ - Acceptance criteria validation (individual or bulk via WorkSessionAcceptanceCheck)
540
572
  - Test result reporting (merged by test type via WorkSessionTestResult)
541
573
  - File tracking (created, modified, deleted on WorkSession)
542
574
  - Discovery reporting (create discoveries for blockers, bugs, tech debt)
@@ -557,6 +589,33 @@ Set getTicket: true to fetch full ticket details in the response \u2014 useful f
557
589
  type: "string",
558
590
  description: "The ID of the ticket being worked on (must be in active status)"
559
591
  },
592
+ action: {
593
+ type: "object",
594
+ description: "The assay action to record \u2014 the AWS action vocabulary. `action` (the discriminator) is one of: mark_implementation_step_completion, mark_acceptance_check, record_test_result, add_skip_justification, amend_skip_justification, add_failure_justification, amend_failure_justification, record_file_change, add_file_change_justification, amend_file_change_justification, create_discovery (with `blocking`), update_discovery, set_discovery_resolved. Include `workSessionId` and the per-action fields. Forwarded verbatim as the lifecycle inner payload.",
595
+ properties: {
596
+ action: {
597
+ type: "string",
598
+ enum: [
599
+ "mark_implementation_step_completion",
600
+ "mark_acceptance_check",
601
+ "record_test_result",
602
+ "add_skip_justification",
603
+ "amend_skip_justification",
604
+ "add_failure_justification",
605
+ "amend_failure_justification",
606
+ "record_file_change",
607
+ "add_file_change_justification",
608
+ "amend_file_change_justification",
609
+ "create_discovery",
610
+ "update_discovery",
611
+ "set_discovery_resolved"
612
+ ],
613
+ description: "The AWS action discriminator."
614
+ },
615
+ workSessionId: { type: "string", description: "The active WorkSession id (from start_work_session)." }
616
+ },
617
+ required: ["action"]
618
+ },
560
619
  steps: {
561
620
  type: "array",
562
621
  description: "Individual step completion updates",
@@ -1000,53 +1059,6 @@ Set getTicket: true to fetch full ticket details in the response \u2014 useful f
1000
1059
  required: ["operation"]
1001
1060
  }
1002
1061
  },
1003
- {
1004
- name: "reset_work_session",
1005
- description: "Reset tickets to pending/ready status (calculated from dependencies). Returns statusCalculation showing how many became pending vs ready.",
1006
- inputSchema: {
1007
- type: "object",
1008
- properties: {
1009
- specificationId: {
1010
- type: "string",
1011
- description: "The specification containing the tickets"
1012
- },
1013
- ticketIds: {
1014
- type: "array",
1015
- items: { type: "string" },
1016
- description: "Specific ticket IDs to reset"
1017
- },
1018
- fromTicketId: {
1019
- type: "string",
1020
- description: "Reset this ticket and all its dependents"
1021
- },
1022
- epicId: {
1023
- type: "string",
1024
- description: "Reset all tickets in this epic"
1025
- },
1026
- allTickets: {
1027
- type: "boolean",
1028
- description: "Reset all tickets in the specification"
1029
- },
1030
- resetDependents: {
1031
- type: "boolean",
1032
- description: "Also reset tickets that depend on the specified tickets (default: false)"
1033
- },
1034
- includeCompleted: {
1035
- type: "boolean",
1036
- description: "Include tickets with done status in the reset (default: false)"
1037
- },
1038
- preserveNotes: {
1039
- type: "boolean",
1040
- description: "Keep existing notes on tickets (default: true)"
1041
- },
1042
- clearTestResults: {
1043
- type: "boolean",
1044
- description: "Clear test result history (default: false)"
1045
- }
1046
- },
1047
- required: ["specificationId"]
1048
- }
1049
- },
1050
1062
  {
1051
1063
  name: "link_pull_request",
1052
1064
  description: "Associate a pull request with a ticket",
@@ -1117,7 +1129,6 @@ Set getTicket: true to fetch full ticket details in the response \u2014 useful f
1117
1129
  start_work_session: "0.2.0",
1118
1130
  action_work_session: "0.2.0",
1119
1131
  complete_work_session: "0.2.0",
1120
- reset_work_session: "0.2.0",
1121
1132
  start_review_session: "0.3.0",
1122
1133
  action_review_session: "0.3.0",
1123
1134
  complete_review_session: "0.3.0"
@@ -1326,29 +1337,19 @@ function createToolHandlers(apiClient) {
1326
1337
  },
1327
1338
  start_work_session: async (_client, args) => {
1328
1339
  validateRequired(args, "ticketId");
1340
+ const git = readWorktreeGitEvidence();
1329
1341
  return await callLocal("start_work_session", {
1330
- ticketId: args.ticketId
1342
+ ticketId: args.ticketId,
1343
+ gitClean: git.gitClean,
1344
+ worktreePath: git.worktreePath,
1345
+ branch: git.branch
1331
1346
  });
1332
1347
  },
1333
1348
  action_work_session: async (_client, args) => {
1334
1349
  validateRequired(args, "ticketId");
1335
1350
  return await callLocal("action_work_session", {
1336
1351
  ticketId: args.ticketId,
1337
- steps: args.steps,
1338
- allStepsDone: args.allStepsDone,
1339
- acceptanceCriteria: args.acceptanceCriteria,
1340
- allACValidated: args.allACValidated,
1341
- testResults: args.testResults,
1342
- notes: args.notes,
1343
- filesCreated: args.filesCreated,
1344
- filesModified: args.filesModified,
1345
- filesDeleted: args.filesDeleted,
1346
- discovery: args.discovery,
1347
- blockReason: args.blockReason,
1348
- getTicket: args.getTicket,
1349
- includeFullContext: args.includeFullContext,
1350
- codeSnippetsReviewed: args.codeSnippetsReviewed,
1351
- typeReferencesReviewed: args.typeReferencesReviewed
1352
+ payload: args.action ?? args.payload
1352
1353
  });
1353
1354
  },
1354
1355
  complete_work_session: async (_client, args) => {
@@ -1402,20 +1403,6 @@ function createToolHandlers(apiClient) {
1402
1403
  feedback: async (_client, args) => {
1403
1404
  return await callLocal("feedback", args);
1404
1405
  },
1405
- reset_work_session: async (_client, args) => {
1406
- validateRequired(args, "specificationId");
1407
- return await callLocal("reset_work_session", {
1408
- specificationId: args.specificationId,
1409
- ticketIds: args.ticketIds,
1410
- fromTicketId: args.fromTicketId,
1411
- epicId: args.epicId,
1412
- allTickets: args.allTickets,
1413
- resetDependents: args.resetDependents,
1414
- includeCompleted: args.includeCompleted,
1415
- preserveNotes: args.preserveNotes,
1416
- clearTestResults: args.clearTestResults
1417
- });
1418
- },
1419
1406
  link_pull_request: async (_client, args) => {
1420
1407
  validateRequired(args, "ticketId");
1421
1408
  if (!args.prNumber && !args.prUrl) {