specweave 1.0.586 → 1.0.588

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 (72) hide show
  1. package/bin/specweave.js +30 -0
  2. package/dist/dashboard/assets/{index-DdI7mc7Y.js → index-DH3l1QBV.js} +6 -6
  3. package/dist/dashboard/assets/index-vkwF92tD.css +1 -0
  4. package/dist/dashboard/index.html +2 -2
  5. package/dist/plugins/specweave/lib/integrations/github/github-access-error.d.ts +48 -0
  6. package/dist/plugins/specweave/lib/integrations/github/github-access-error.d.ts.map +1 -0
  7. package/dist/plugins/specweave/lib/integrations/github/github-access-error.js +69 -0
  8. package/dist/plugins/specweave/lib/integrations/github/github-access-error.js.map +1 -0
  9. package/dist/plugins/specweave/lib/integrations/github/github-client-v2.d.ts +8 -0
  10. package/dist/plugins/specweave/lib/integrations/github/github-client-v2.d.ts.map +1 -1
  11. package/dist/plugins/specweave/lib/integrations/github/github-client-v2.js +22 -2
  12. package/dist/plugins/specweave/lib/integrations/github/github-client-v2.js.map +1 -1
  13. package/dist/plugins/specweave/lib/utils/fs-native.d.ts +1 -1
  14. package/dist/plugins/specweave/lib/vendor/generators/spec/task-parser.js +38 -16
  15. package/dist/plugins/specweave/lib/vendor/generators/spec/task-parser.js.map +1 -1
  16. package/dist/plugins/specweave/lib/vendor/utils/fs-native.d.ts +1 -1
  17. package/dist/src/cli/commands/handoff.d.ts +54 -0
  18. package/dist/src/cli/commands/handoff.d.ts.map +1 -0
  19. package/dist/src/cli/commands/handoff.js +82 -0
  20. package/dist/src/cli/commands/handoff.js.map +1 -0
  21. package/dist/src/cli/helpers/init/external-import.js.map +1 -1
  22. package/dist/src/cli/helpers/init/gitignore-generator.d.ts.map +1 -1
  23. package/dist/src/cli/helpers/init/gitignore-generator.js +3 -0
  24. package/dist/src/cli/helpers/init/gitignore-generator.js.map +1 -1
  25. package/dist/src/core/hooks/handlers/hook-router.d.ts.map +1 -1
  26. package/dist/src/core/hooks/handlers/hook-router.js +5 -0
  27. package/dist/src/core/hooks/handlers/hook-router.js.map +1 -1
  28. package/dist/src/core/hooks/handlers/pre-compact.d.ts +33 -0
  29. package/dist/src/core/hooks/handlers/pre-compact.d.ts.map +1 -0
  30. package/dist/src/core/hooks/handlers/pre-compact.js +109 -0
  31. package/dist/src/core/hooks/handlers/pre-compact.js.map +1 -0
  32. package/dist/src/core/hooks/handlers/types.d.ts +1 -1
  33. package/dist/src/core/hooks/handlers/types.d.ts.map +1 -1
  34. package/dist/src/core/hooks/handlers/types.js +3 -0
  35. package/dist/src/core/hooks/handlers/types.js.map +1 -1
  36. package/dist/src/core/session/handoff-doc-format.d.ts +164 -0
  37. package/dist/src/core/session/handoff-doc-format.d.ts.map +1 -0
  38. package/dist/src/core/session/handoff-doc-format.js +292 -0
  39. package/dist/src/core/session/handoff-doc-format.js.map +1 -0
  40. package/dist/src/core/session/handoff-git-state.d.ts +49 -0
  41. package/dist/src/core/session/handoff-git-state.d.ts.map +1 -0
  42. package/dist/src/core/session/handoff-git-state.js +164 -0
  43. package/dist/src/core/session/handoff-git-state.js.map +1 -0
  44. package/dist/src/core/session/handoff-secret-scrub.d.ts +59 -0
  45. package/dist/src/core/session/handoff-secret-scrub.d.ts.map +1 -0
  46. package/dist/src/core/session/handoff-secret-scrub.js +72 -0
  47. package/dist/src/core/session/handoff-secret-scrub.js.map +1 -0
  48. package/dist/src/core/session/{handoff-context.d.ts → install-handoff-context.d.ts} +7 -3
  49. package/dist/src/core/session/install-handoff-context.d.ts.map +1 -0
  50. package/dist/src/core/session/{handoff-context.js → install-handoff-context.js} +7 -3
  51. package/dist/src/core/session/install-handoff-context.js.map +1 -0
  52. package/dist/src/core/session/work-handoff.d.ts +88 -0
  53. package/dist/src/core/session/work-handoff.d.ts.map +1 -0
  54. package/dist/src/core/session/work-handoff.js +412 -0
  55. package/dist/src/core/session/work-handoff.js.map +1 -0
  56. package/dist/src/generators/spec/task-parser.d.ts.map +1 -1
  57. package/dist/src/generators/spec/task-parser.js +38 -16
  58. package/dist/src/generators/spec/task-parser.js.map +1 -1
  59. package/dist/src/utils/fs-native.d.ts +1 -1
  60. package/package.json +2 -2
  61. package/plugins/specweave/commands/handoff.md +54 -0
  62. package/plugins/specweave/lib/integrations/github/github-access-error.js +43 -0
  63. package/plugins/specweave/lib/integrations/github/github-access-error.ts +103 -0
  64. package/plugins/specweave/lib/integrations/github/github-client-v2.js +24 -4
  65. package/plugins/specweave/lib/integrations/github/github-client-v2.ts +26 -4
  66. package/plugins/specweave/lib/vendor/generators/spec/task-parser.js +38 -16
  67. package/plugins/specweave/lib/vendor/generators/spec/task-parser.js.map +1 -1
  68. package/plugins/specweave/lib/vendor/utils/fs-native.d.ts +1 -1
  69. package/plugins/specweave/skills/handoff/SKILL.md +59 -0
  70. package/dist/dashboard/assets/index-YkogWPHY.css +0 -1
  71. package/dist/src/core/session/handoff-context.d.ts.map +0 -1
  72. package/dist/src/core/session/handoff-context.js.map +0 -1
@@ -0,0 +1,109 @@
1
+ /**
2
+ * PreCompact (+ gated Stop) hook handler.
3
+ *
4
+ * Fires when Claude Code is about to compact the context window (PreCompact) —
5
+ * the last safe moment to capture in-flight work before it is summarized away.
6
+ * The handler auto-writes a work-handoff doc + `.diff` via the SAME
7
+ * {@link buildWorkHandoff} builder the `specweave handoff` CLI uses, so an
8
+ * auto-generated handoff is byte-compatible with a manual one (AC-US7-03).
9
+ *
10
+ * Design contract (AC-US7-01..04):
11
+ * - Cheap at context exhaustion: the agent passes only ~5 short string fields
12
+ * (reason, summary, next, gotcha, decision) via the hook stdin JSON; all the
13
+ * expensive deterministic assembly + the free diff dump happen in the builder.
14
+ * - Failure-tolerant: a handoff failure must NEVER break compaction. Everything
15
+ * is wrapped so the handler always returns the safe `{ continue: true }` shape.
16
+ * - The Stop variant (`exports.handleStop`) is GATED on an auto/handoff session
17
+ * flag (`.specweave/state/auto-mode.json`): PreCompact always writes; Stop only
18
+ * writes under an active auto session, so ordinary turn-ends stay quiet
19
+ * (AC-US7-02).
20
+ *
21
+ * @module core/hooks/handlers/pre-compact
22
+ */
23
+ import * as fs from 'fs';
24
+ import * as path from 'path';
25
+ import { logHook } from './utils.js';
26
+ /** The compaction-safe response — never block. */
27
+ const SAFE = { continue: true };
28
+ /**
29
+ * Pull the ~5 short free-text fields the agent may have stated, off the hook
30
+ * stdin JSON. Tolerant of both snake_case and camelCase keys and of total
31
+ * absence (the common case at a real token crash — all may be empty).
32
+ */
33
+ function readShortFields(input) {
34
+ const get = (...keys) => {
35
+ for (const k of keys) {
36
+ const v = input[k];
37
+ if (typeof v === 'string' && v.trim())
38
+ return v;
39
+ }
40
+ return undefined;
41
+ };
42
+ const decisionRaw = input.decision ?? input.decisions;
43
+ const decisions = Array.isArray(decisionRaw)
44
+ ? decisionRaw.filter((d) => typeof d === 'string' && d.trim().length > 0)
45
+ : typeof decisionRaw === 'string' && decisionRaw.trim()
46
+ ? [decisionRaw]
47
+ : undefined;
48
+ return {
49
+ reason: get('reason'),
50
+ summary: get('summary'),
51
+ next: get('next', 'next_step', 'nextStep'),
52
+ gotcha: get('gotcha'),
53
+ decisions,
54
+ };
55
+ }
56
+ /** Is an auto/handoff session currently active? (Stop gating, AC-US7-02.) */
57
+ function isAutoSessionActive(context) {
58
+ try {
59
+ return fs.existsSync(path.join(context.stateDir, 'auto-mode.json'));
60
+ }
61
+ catch {
62
+ return false;
63
+ }
64
+ }
65
+ /**
66
+ * Write an auto-handoff. Wrapped so any failure is swallowed — compaction /
67
+ * turn-end must proceed regardless.
68
+ */
69
+ async function writeAutoHandoff(context, defaultReason, input) {
70
+ try {
71
+ // Lazy import so the handler stays cheap and the builder's deps only load
72
+ // when a handoff is actually written.
73
+ const { buildWorkHandoff } = await import('../../session/work-handoff.js');
74
+ const fields = readShortFields(input);
75
+ const result = await buildWorkHandoff(context.projectRoot, {
76
+ // Honor an agent-supplied reason (AC-US7-04); fall back to the
77
+ // hook-specific default so the CLI and hook paths stay consistent.
78
+ reason: fields.reason ?? defaultReason,
79
+ summary: fields.summary,
80
+ next: fields.next,
81
+ gotcha: fields.gotcha,
82
+ decisions: fields.decisions,
83
+ });
84
+ logHook(context, 'pre-compact', `auto-handoff written: ${result.docPath}`);
85
+ }
86
+ catch (err) {
87
+ const msg = err instanceof Error ? err.message : String(err);
88
+ logHook(context, 'pre-compact', `[ERROR] auto-handoff failed (ignored): ${msg}`);
89
+ }
90
+ }
91
+ /**
92
+ * PreCompact handler — always writes a handoff, never blocks compaction.
93
+ */
94
+ export const handle = async (input, context) => {
95
+ await writeAutoHandoff(context, 'auto: pre-compact', input);
96
+ return SAFE;
97
+ };
98
+ /**
99
+ * Stop handler — gated on an active auto/handoff session. Fires only when
100
+ * `auto-mode.json` is present so ordinary turn-ends are not noisy (AC-US7-02).
101
+ */
102
+ export const handleStop = async (input, context) => {
103
+ if (!isAutoSessionActive(context)) {
104
+ return SAFE;
105
+ }
106
+ await writeAutoHandoff(context, 'auto: stop', input);
107
+ return SAFE;
108
+ };
109
+ //# sourceMappingURL=pre-compact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pre-compact.js","sourceRoot":"","sources":["../../../../../src/core/hooks/handlers/pre-compact.ts"],"names":[],"mappings":"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"}
@@ -55,7 +55,7 @@ export interface HookContext {
55
55
  /** Handler function signature — every handler exports a `handle` matching this */
56
56
  export type HandlerFn = (input: HookInput, context: HookContext) => Promise<HookResult>;
57
57
  /** Event types supported by the hook router */
58
- export type HookEventType = 'user-prompt-submit' | 'pre-tool-use';
58
+ export type HookEventType = 'user-prompt-submit' | 'pre-tool-use' | 'pre-compact' | 'stop';
59
59
  /** Map of event types to their safe fallback responses */
60
60
  export declare const SAFE_DEFAULTS: Record<string, HookResult>;
61
61
  /** Get safe default response for an event type */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/core/hooks/handlers/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,oDAAoD;AACpD,MAAM,WAAW,SAAS;IACxB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,0CAA0C;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,+CAA+C;AAC/C,MAAM,WAAW,UAAU;IACzB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;IACzC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,kBAAkB,CAAC,EAAE;QACnB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,sCAAsC;IACtC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,8DAA8D;AAC9D,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,kFAAkF;AAClF,MAAM,MAAM,SAAS,GAAG,CACtB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,WAAW,KACjB,OAAO,CAAC,UAAU,CAAC,CAAC;AAEzB,+CAA+C;AAC/C,MAAM,MAAM,aAAa,GACrB,oBAAoB,GACpB,cAAc,CAAC;AAEnB,0DAA0D;AAC1D,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAGpD,CAAC;AAEF,kDAAkD;AAClD,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAE5D"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/core/hooks/handlers/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,oDAAoD;AACpD,MAAM,WAAW,SAAS;IACxB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,0CAA0C;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,+CAA+C;AAC/C,MAAM,WAAW,UAAU;IACzB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;IACzC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,kBAAkB,CAAC,EAAE;QACnB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,sCAAsC;IACtC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,8DAA8D;AAC9D,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,kFAAkF;AAClF,MAAM,MAAM,SAAS,GAAG,CACtB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,WAAW,KACjB,OAAO,CAAC,UAAU,CAAC,CAAC;AAEzB,+CAA+C;AAC/C,MAAM,MAAM,aAAa,GACrB,oBAAoB,GACpB,cAAc,GACd,aAAa,GACb,MAAM,CAAC;AAEX,0DAA0D;AAC1D,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAMpD,CAAC;AAEF,kDAAkD;AAClD,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAE5D"}
@@ -12,6 +12,9 @@
12
12
  export const SAFE_DEFAULTS = {
13
13
  'user-prompt-submit': { decision: 'approve' },
14
14
  'pre-tool-use': { continue: true },
15
+ // Compaction / turn-end must never be blocked by a handoff failure.
16
+ 'pre-compact': { continue: true },
17
+ 'stop': { continue: true },
15
18
  };
16
19
  /** Get safe default response for an event type */
17
20
  export function getSafeDefault(eventType) {
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../src/core/hooks/handlers/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA4DH,0DAA0D;AAC1D,MAAM,CAAC,MAAM,aAAa,GAA+B;IACvD,oBAAoB,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE;IAC7C,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;CACnC,CAAC;AAEF,kDAAkD;AAClD,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,OAAO,aAAa,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACxD,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../src/core/hooks/handlers/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA8DH,0DAA0D;AAC1D,MAAM,CAAC,MAAM,aAAa,GAA+B;IACvD,oBAAoB,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE;IAC7C,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;IAClC,oEAAoE;IACpE,aAAa,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;IACjC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;CAC3B,CAAC;AAEF,kDAAkD;AAClD,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,OAAO,aAAa,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACxD,CAAC"}
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Handoff Doc Format — single source of truth
3
+ *
4
+ * Renders BOTH the durable handoff document and the copy-paste resume prompt
5
+ * from one {@link HandoffDocInput}. The CLI command, the PreCompact hook
6
+ * handler, and the vitest parity test all render through this module, so the
7
+ * doc format and paste-prompt cannot drift between code paths. The vskill
8
+ * self-contained skill inlines a byte-compatible template that references the
9
+ * same canonical section order + footer marker exported here.
10
+ *
11
+ * Design rules:
12
+ * - This module is PURE rendering. It does no IO, no git, no workspace
13
+ * detection — callers pass already-captured + already-scrubbed data in.
14
+ * - The absolute doc path, the `.diff` path, and the per-tool resume matrix are
15
+ * inputs/constants so the renderer is deterministic and testable.
16
+ * - The `Doc format v1` footer marker (DOC_FORMAT_MARKER) is the ownership
17
+ * sentinel that lets the builder know a file is a prior handoff it may
18
+ * overwrite, and the version handle for future format migrations.
19
+ *
20
+ * Part of increment 0867: Cross-Tool Work Handoff
21
+ * (AC-US1-02, AC-US2-04, AC-US5-01..04, AC-US6-02, AC-US6-05).
22
+ *
23
+ * @module core/session/handoff-doc-format
24
+ */
25
+ /**
26
+ * Footer marker stamped at the bottom of every handoff doc.
27
+ *
28
+ * Doubles as the ownership sentinel: a root `./HANDOFF.md` containing this
29
+ * string is treated as a prior handoff (safe to overwrite); one lacking it is a
30
+ * foreign file the builder must not clobber.
31
+ */
32
+ export declare const DOC_FORMAT_MARKER = "Doc format v1";
33
+ /**
34
+ * Delimiters wrapping the self-contained body in `--inline` paste-prompts.
35
+ * A resuming agent reads everything between these markers as the handoff.
36
+ */
37
+ export declare const INLINE_BEGIN_MARKER = "BEGIN HANDOFF";
38
+ export declare const INLINE_END_MARKER = "END HANDOFF";
39
+ /**
40
+ * Canonical section headers, in render order. Exported so the vskill inlined
41
+ * template and the format-parity test (T-017) reference ONE source and fail at
42
+ * build time if either side reorders or renames a section.
43
+ */
44
+ export declare const HANDOFF_SECTION_ORDER: readonly string[];
45
+ /**
46
+ * Per-tool resume guidance. The `findSession` + `resumeCmd` strings are
47
+ * VERIFIED against the live CLIs and pinned by cross-tool-commands.test.ts
48
+ * (T-016) so the matrix cannot silently drift when a tool updates.
49
+ */
50
+ export interface ToolResumeEntry {
51
+ /** Display name. */
52
+ tool: string;
53
+ /** How to locate the source session on disk / in the tool. */
54
+ findSession: string;
55
+ /** Native resume command(s). */
56
+ resumeCmd: string;
57
+ }
58
+ /**
59
+ * The cross-tool resume matrix (AC-US5-01, AC-US5-02).
60
+ *
61
+ * NOTE on Claude: session files live under
62
+ * `~/.claude/projects/<munged-cwd>/<uuid>.jsonl`, where the cwd is munged by
63
+ * replacing EVERY non-alphanumeric char with `-` and NOT collapsing runs — so a
64
+ * leading slash and adjacent separators each become their own dash. Example:
65
+ * /Users/.../specweave-umb/.claude-worktrees/x
66
+ * → -Users-...-specweave-umb--claude-worktrees-x
67
+ * (the `/.` between `umb` and `claude-worktrees` yields a double dash).
68
+ */
69
+ export declare const CLAUDE_MUNGE_EXAMPLE: string;
70
+ export declare const TOOL_RESUME_MATRIX: readonly ToolResumeEntry[];
71
+ /**
72
+ * Increment-derived facts (present only on the SpecWeave high-fidelity path).
73
+ */
74
+ export interface HandoffIncrementInfo {
75
+ id: string;
76
+ status: string;
77
+ /** Title from spec.md frontmatter, if available. */
78
+ title?: string;
79
+ /** The current (first incomplete / in-progress) task line, if any. */
80
+ currentTask?: string;
81
+ /** The next pending task line after the current one, if any. */
82
+ nextTask?: string;
83
+ doneTasks: number;
84
+ totalTasks: number;
85
+ taskPercentage: number;
86
+ doneAcs: number;
87
+ totalAcs: number;
88
+ /** Human-readable AC/task drift summary lines from acSyncEvents. */
89
+ acSyncEvents: string[];
90
+ }
91
+ /**
92
+ * Ambient project rules merged from config.json.
93
+ */
94
+ export interface HandoffAmbientRules {
95
+ testMode?: string;
96
+ coverageTarget?: number;
97
+ wipLimit?: number;
98
+ }
99
+ /**
100
+ * Git facts for the doc body (mirrors GitState minus the diff file contents).
101
+ */
102
+ export interface HandoffGitInfo {
103
+ isGitRepo: boolean;
104
+ branch: string;
105
+ shortSha: string;
106
+ statusPorcelain: string;
107
+ diffStat: string;
108
+ hasUncommittedChanges: boolean;
109
+ }
110
+ /**
111
+ * The complete, already-scrubbed input to the renderer.
112
+ */
113
+ export interface HandoffDocInput {
114
+ /** Absolute path the doc itself will be written to (printed first by CLI). */
115
+ docPath: string;
116
+ /** Absolute path of the sibling full-diff file. */
117
+ diffPath: string;
118
+ /** Repo / workspace root. */
119
+ repoRoot: string;
120
+ /** ISO timestamp of generation. */
121
+ generatedAt: string;
122
+ /** Whether this is the SpecWeave high-fidelity path. */
123
+ isSpecWeave: boolean;
124
+ /** Free-text "why I'm handing off" (e.g. "out of tokens"). */
125
+ reason?: string;
126
+ /** Free-text summary of where things stand. */
127
+ summary?: string;
128
+ /** Free-text exact next step. */
129
+ next?: string;
130
+ /** Free-text gotcha / warning for the next agent. */
131
+ gotcha?: string;
132
+ /** Key decisions (from plan.md + agent-supplied, already merged). */
133
+ decisions: string[];
134
+ /** Increment facts (SpecWeave path only). */
135
+ increment?: HandoffIncrementInfo;
136
+ /** Ambient rules from config.json. */
137
+ ambient?: HandoffAmbientRules;
138
+ /** Git facts. */
139
+ git: HandoffGitInfo;
140
+ /** Per-pattern redaction counts from the secret scrub. */
141
+ redactionCounts: Record<string, number>;
142
+ }
143
+ /**
144
+ * Render the per-tool "find your source session" block.
145
+ */
146
+ export declare function renderResumeMatrix(): string;
147
+ /**
148
+ * Render the full handoff document body (markdown).
149
+ *
150
+ * Section order is locked to {@link HANDOFF_SECTION_ORDER}; the `Doc format v1`
151
+ * footer marker is always last.
152
+ */
153
+ export declare function renderHandoffDoc(input: HandoffDocInput): string;
154
+ /**
155
+ * Render the copy-paste resume prompt.
156
+ *
157
+ * Default (file-reachable) mode points the next agent at the doc path. The
158
+ * `inline` mode embeds the FULL doc body between BEGIN/END markers for
159
+ * cross-machine resume where the file is unreachable (AC-US5-04).
160
+ */
161
+ export declare function renderPastePrompt(input: HandoffDocInput, opts?: {
162
+ inline?: boolean;
163
+ }): string;
164
+ //# sourceMappingURL=handoff-doc-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handoff-doc-format.d.ts","sourceRoot":"","sources":["../../../../src/core/session/handoff-doc-format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AACnD,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAE/C;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,SAAS,MAAM,EAQzC,CAAC;AAEX;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,QAEyC,CAAC;AAE3E,eAAO,MAAM,kBAAkB,EAAE,SAAS,eAAe,EAiC/C,CAAC;AAEX;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,oEAAoE;IACpE,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAC;IACjB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,WAAW,EAAE,OAAO,CAAC;IACrB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,sCAAsC;IACtC,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,iBAAiB;IACjB,GAAG,EAAE,cAAc,CAAC;IACpB,0DAA0D;IAC1D,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAYD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAgB3C;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAkI/D;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,eAAe,EAAE,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,MAAM,CAwBjG"}
@@ -0,0 +1,292 @@
1
+ /**
2
+ * Handoff Doc Format — single source of truth
3
+ *
4
+ * Renders BOTH the durable handoff document and the copy-paste resume prompt
5
+ * from one {@link HandoffDocInput}. The CLI command, the PreCompact hook
6
+ * handler, and the vitest parity test all render through this module, so the
7
+ * doc format and paste-prompt cannot drift between code paths. The vskill
8
+ * self-contained skill inlines a byte-compatible template that references the
9
+ * same canonical section order + footer marker exported here.
10
+ *
11
+ * Design rules:
12
+ * - This module is PURE rendering. It does no IO, no git, no workspace
13
+ * detection — callers pass already-captured + already-scrubbed data in.
14
+ * - The absolute doc path, the `.diff` path, and the per-tool resume matrix are
15
+ * inputs/constants so the renderer is deterministic and testable.
16
+ * - The `Doc format v1` footer marker (DOC_FORMAT_MARKER) is the ownership
17
+ * sentinel that lets the builder know a file is a prior handoff it may
18
+ * overwrite, and the version handle for future format migrations.
19
+ *
20
+ * Part of increment 0867: Cross-Tool Work Handoff
21
+ * (AC-US1-02, AC-US2-04, AC-US5-01..04, AC-US6-02, AC-US6-05).
22
+ *
23
+ * @module core/session/handoff-doc-format
24
+ */
25
+ /**
26
+ * Footer marker stamped at the bottom of every handoff doc.
27
+ *
28
+ * Doubles as the ownership sentinel: a root `./HANDOFF.md` containing this
29
+ * string is treated as a prior handoff (safe to overwrite); one lacking it is a
30
+ * foreign file the builder must not clobber.
31
+ */
32
+ export const DOC_FORMAT_MARKER = 'Doc format v1';
33
+ /**
34
+ * Delimiters wrapping the self-contained body in `--inline` paste-prompts.
35
+ * A resuming agent reads everything between these markers as the handoff.
36
+ */
37
+ export const INLINE_BEGIN_MARKER = 'BEGIN HANDOFF';
38
+ export const INLINE_END_MARKER = 'END HANDOFF';
39
+ /**
40
+ * Canonical section headers, in render order. Exported so the vskill inlined
41
+ * template and the format-parity test (T-017) reference ONE source and fail at
42
+ * build time if either side reorders or renames a section.
43
+ */
44
+ export const HANDOFF_SECTION_ORDER = [
45
+ 'Where I Left Off',
46
+ 'Done / Pending',
47
+ 'Key Decisions & Gotchas',
48
+ 'Files Touched',
49
+ 'Exact Next Steps',
50
+ 'How To Resume',
51
+ 'Redaction',
52
+ ];
53
+ /**
54
+ * The cross-tool resume matrix (AC-US5-01, AC-US5-02).
55
+ *
56
+ * NOTE on Claude: session files live under
57
+ * `~/.claude/projects/<munged-cwd>/<uuid>.jsonl`, where the cwd is munged by
58
+ * replacing EVERY non-alphanumeric char with `-` and NOT collapsing runs — so a
59
+ * leading slash and adjacent separators each become their own dash. Example:
60
+ * /Users/.../specweave-umb/.claude-worktrees/x
61
+ * → -Users-...-specweave-umb--claude-worktrees-x
62
+ * (the `/.` between `umb` and `claude-worktrees` yields a double dash).
63
+ */
64
+ export const CLAUDE_MUNGE_EXAMPLE = '/Users/antonabyzov/Projects/github/specweave-umb/.claude-worktrees/x ' +
65
+ '→ -Users-antonabyzov-Projects-github-specweave-umb--claude-worktrees-x';
66
+ export const TOOL_RESUME_MATRIX = [
67
+ {
68
+ tool: 'Claude Code',
69
+ findSession: 'ls ~/.claude/projects/<munged-cwd>/ (munge: every non-alphanumeric char → "-", runs NOT collapsed; e.g. ' +
70
+ CLAUDE_MUNGE_EXAMPLE + ')',
71
+ resumeCmd: 'claude -r <uuid>',
72
+ },
73
+ {
74
+ tool: 'Codex',
75
+ findSession: 'ls ~/.codex/sessions/ (newest dir = most recent session)',
76
+ resumeCmd: 'codex resume <uuid> (or: codex resume --last)',
77
+ },
78
+ {
79
+ tool: 'OpenCode',
80
+ findSession: 'opencode sessions list',
81
+ resumeCmd: 'opencode -s <id> (long form: opencode --session <id>)',
82
+ },
83
+ {
84
+ tool: 'Gemini CLI',
85
+ findSession: 'run /chat list inside the Gemini session to see saved tags',
86
+ resumeCmd: '/chat resume <tag>',
87
+ },
88
+ {
89
+ tool: 'Antigravity',
90
+ findSession: 'open the Antigravity Agent Manager and pick the prior task thread',
91
+ resumeCmd: 'resume the thread from the Antigravity Agent Manager',
92
+ },
93
+ {
94
+ tool: 'Aider',
95
+ findSession: 'aider keeps .aider.chat.history.md in the repo root',
96
+ resumeCmd: 'aider --restore-chat-history',
97
+ },
98
+ ];
99
+ function fmtCount(counts) {
100
+ const entries = Object.entries(counts);
101
+ if (entries.length === 0) {
102
+ return '_No token-like strings were detected._';
103
+ }
104
+ return entries
105
+ .map(([type, n]) => `- ${n} \`${type}\` ${n === 1 ? 'string' : 'strings'} masked`)
106
+ .join('\n');
107
+ }
108
+ /**
109
+ * Render the per-tool "find your source session" block.
110
+ */
111
+ export function renderResumeMatrix() {
112
+ const lines = ['## How To Resume', ''];
113
+ lines.push('If the doc path above does NOT exist on the machine you are reading this on, ' +
114
+ 'STOP and ask the user to paste the handoff — do not improvise context.');
115
+ lines.push('');
116
+ lines.push('To recover the ORIGINAL transcript (optional), find your source session per tool:');
117
+ lines.push('');
118
+ for (const e of TOOL_RESUME_MATRIX) {
119
+ lines.push(`### ${e.tool}`);
120
+ lines.push(`- Find session: ${e.findSession}`);
121
+ lines.push(`- Resume: \`${e.resumeCmd}\``);
122
+ lines.push('');
123
+ }
124
+ return lines.join('\n').trimEnd();
125
+ }
126
+ /**
127
+ * Render the full handoff document body (markdown).
128
+ *
129
+ * Section order is locked to {@link HANDOFF_SECTION_ORDER}; the `Doc format v1`
130
+ * footer marker is always last.
131
+ */
132
+ export function renderHandoffDoc(input) {
133
+ const L = [];
134
+ // ── Header ──────────────────────────────────────────────────────────────
135
+ const titleBit = input.increment?.title ? `: ${input.increment.title}` : '';
136
+ L.push(`# Work Handoff${titleBit}`);
137
+ L.push('');
138
+ L.push(`- Doc path: ${input.docPath}`);
139
+ L.push(`- Doc link: [${input.docPath}](${input.docPath})`);
140
+ L.push(`- Diff file: ${input.diffPath}`);
141
+ L.push(`- Generated: ${input.generatedAt}`);
142
+ L.push(`- Workspace: ${input.repoRoot} ${input.isSpecWeave ? '(SpecWeave)' : '(non-SpecWeave)'}`);
143
+ if (input.git.isGitRepo) {
144
+ L.push(`- Git: branch \`${input.git.branch || '(detached)'}\` @ \`${input.git.shortSha || '(no commits)'}\``);
145
+ }
146
+ L.push('');
147
+ // ── Where I Left Off ──────────────────────────────────────────────────────
148
+ L.push('## Where I Left Off');
149
+ L.push('');
150
+ if (input.reason)
151
+ L.push(`**Why handing off:** ${input.reason}`);
152
+ if (input.summary)
153
+ L.push(`**Summary:** ${input.summary}`);
154
+ if (input.increment) {
155
+ L.push(`**Increment:** ${input.increment.id} (status: ${input.increment.status})`);
156
+ if (input.increment.currentTask)
157
+ L.push(`**Current task:** ${input.increment.currentTask}`);
158
+ if (input.increment.nextTask)
159
+ L.push(`**Next task:** ${input.increment.nextTask}`);
160
+ }
161
+ else {
162
+ L.push('_No active SpecWeave increment — this is a git + interview handoff._');
163
+ }
164
+ L.push('');
165
+ // ── Done / Pending ──────────────────────────────────────────────────────
166
+ L.push('## Done / Pending');
167
+ L.push('');
168
+ if (input.increment) {
169
+ const inc = input.increment;
170
+ L.push(`- Tasks: ${inc.doneTasks}/${inc.totalTasks} done (${inc.taskPercentage}%), ` +
171
+ `${inc.totalTasks - inc.doneTasks} pending`);
172
+ L.push(`- ACs: ${inc.doneAcs}/${inc.totalAcs} checked`);
173
+ if (inc.acSyncEvents.length > 0) {
174
+ L.push('- AC/task drift (recent sync events):');
175
+ for (const ev of inc.acSyncEvents)
176
+ L.push(` - ${ev}`);
177
+ }
178
+ }
179
+ else {
180
+ L.push('_No increment task/AC state available._');
181
+ }
182
+ L.push('');
183
+ // ── Key Decisions & Gotchas ───────────────────────────────────────────────
184
+ L.push('## Key Decisions & Gotchas');
185
+ L.push('');
186
+ if (input.decisions.length > 0) {
187
+ for (const d of input.decisions)
188
+ L.push(`- ${d}`);
189
+ }
190
+ else {
191
+ L.push('_No decisions recorded._');
192
+ }
193
+ if (input.gotcha) {
194
+ L.push('');
195
+ L.push(`**Gotcha:** ${input.gotcha}`);
196
+ }
197
+ if (input.ambient && (input.ambient.testMode || input.ambient.coverageTarget != null || input.ambient.wipLimit != null)) {
198
+ L.push('');
199
+ L.push('**Ambient rules (config.json):**');
200
+ if (input.ambient.testMode)
201
+ L.push(`- Test mode: ${input.ambient.testMode}`);
202
+ if (input.ambient.coverageTarget != null)
203
+ L.push(`- Coverage target: ${input.ambient.coverageTarget}%`);
204
+ if (input.ambient.wipLimit != null)
205
+ L.push(`- WIP limit: ${input.ambient.wipLimit}`);
206
+ }
207
+ L.push('');
208
+ // ── Files Touched ─────────────────────────────────────────────────────────
209
+ L.push('## Files Touched');
210
+ L.push('');
211
+ if (input.git.hasUncommittedChanges) {
212
+ L.push('**UNCOMMITTED** — commit, stash, or keep editing BEFORE doing anything destructive.');
213
+ L.push('');
214
+ L.push('```');
215
+ L.push(input.git.statusPorcelain || '(no porcelain output)');
216
+ L.push('```');
217
+ if (input.git.diffStat) {
218
+ L.push('');
219
+ L.push('```');
220
+ L.push(input.git.diffStat);
221
+ L.push('```');
222
+ }
223
+ L.push('');
224
+ L.push(`Full uncommitted diff: \`${input.diffPath}\` — read it or run ` +
225
+ '`git apply --check` against it to see the exact edits.');
226
+ }
227
+ else if (input.git.isGitRepo) {
228
+ L.push('_Working tree clean — no uncommitted edits._');
229
+ }
230
+ else {
231
+ L.push('_Not a git repository — no diff captured._');
232
+ }
233
+ L.push('');
234
+ // ── Exact Next Steps ──────────────────────────────────────────────────────
235
+ L.push('## Exact Next Steps');
236
+ L.push('');
237
+ if (input.next) {
238
+ L.push(input.next);
239
+ }
240
+ else if (input.increment?.nextTask) {
241
+ L.push(`Continue with: ${input.increment.nextTask}`);
242
+ }
243
+ else {
244
+ L.push('_No explicit next step recorded — review the summary above._');
245
+ }
246
+ L.push('');
247
+ // ── How To Resume (+ per-tool matrix) ─────────────────────────────────────
248
+ L.push(renderResumeMatrix());
249
+ L.push('');
250
+ // ── Redaction ─────────────────────────────────────────────────────────────
251
+ L.push('## Redaction');
252
+ L.push('');
253
+ L.push(fmtCount(input.redactionCounts));
254
+ L.push('');
255
+ L.push('_Scrubbing is heuristic (regex baseline). An empty redaction list is NOT a ' +
256
+ 'guarantee this file is clean — review before sharing or committing._');
257
+ L.push('');
258
+ // ── Footer marker ─────────────────────────────────────────────────────────
259
+ L.push('---');
260
+ L.push(`<!-- ${DOC_FORMAT_MARKER} -->`);
261
+ return L.join('\n');
262
+ }
263
+ /**
264
+ * Render the copy-paste resume prompt.
265
+ *
266
+ * Default (file-reachable) mode points the next agent at the doc path. The
267
+ * `inline` mode embeds the FULL doc body between BEGIN/END markers for
268
+ * cross-machine resume where the file is unreachable (AC-US5-04).
269
+ */
270
+ export function renderPastePrompt(input, opts = {}) {
271
+ const P = [];
272
+ if (opts.inline) {
273
+ P.push('Resume my work using the self-contained handoff below.');
274
+ P.push('This is a full handoff doc — treat everything between the markers as ground truth. ' +
275
+ 'If it references a `.diff` path that does not exist on this machine, ask me to paste the diff.');
276
+ P.push('');
277
+ P.push(INLINE_BEGIN_MARKER);
278
+ P.push(renderHandoffDoc(input));
279
+ P.push(INLINE_END_MARKER);
280
+ }
281
+ else {
282
+ P.push(`Resume my work. Read the handoff doc at: ${input.docPath}`);
283
+ P.push('If that path does NOT exist on this machine, STOP and ask me to paste the handoff — ' +
284
+ 'do not improvise context.');
285
+ P.push(`The exact uncommitted edits are in: ${input.diffPath}`);
286
+ if (input.increment) {
287
+ P.push(`Active increment: ${input.increment.id}. Pick up at the next pending task.`);
288
+ }
289
+ }
290
+ return P.join('\n');
291
+ }
292
+ //# sourceMappingURL=handoff-doc-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handoff-doc-format.js","sourceRoot":"","sources":["../../../../src/core/session/handoff-doc-format.ts"],"names":[],"mappings":"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"}