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.
- package/bin/specweave.js +30 -0
- package/dist/dashboard/assets/{index-DdI7mc7Y.js → index-DH3l1QBV.js} +6 -6
- package/dist/dashboard/assets/index-vkwF92tD.css +1 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/plugins/specweave/lib/integrations/github/github-access-error.d.ts +48 -0
- package/dist/plugins/specweave/lib/integrations/github/github-access-error.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-access-error.js +69 -0
- package/dist/plugins/specweave/lib/integrations/github/github-access-error.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-client-v2.d.ts +8 -0
- package/dist/plugins/specweave/lib/integrations/github/github-client-v2.d.ts.map +1 -1
- package/dist/plugins/specweave/lib/integrations/github/github-client-v2.js +22 -2
- package/dist/plugins/specweave/lib/integrations/github/github-client-v2.js.map +1 -1
- package/dist/plugins/specweave/lib/utils/fs-native.d.ts +1 -1
- package/dist/plugins/specweave/lib/vendor/generators/spec/task-parser.js +38 -16
- package/dist/plugins/specweave/lib/vendor/generators/spec/task-parser.js.map +1 -1
- package/dist/plugins/specweave/lib/vendor/utils/fs-native.d.ts +1 -1
- package/dist/src/cli/commands/handoff.d.ts +54 -0
- package/dist/src/cli/commands/handoff.d.ts.map +1 -0
- package/dist/src/cli/commands/handoff.js +82 -0
- package/dist/src/cli/commands/handoff.js.map +1 -0
- package/dist/src/cli/helpers/init/external-import.js.map +1 -1
- package/dist/src/cli/helpers/init/gitignore-generator.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/gitignore-generator.js +3 -0
- package/dist/src/cli/helpers/init/gitignore-generator.js.map +1 -1
- package/dist/src/core/hooks/handlers/hook-router.d.ts.map +1 -1
- package/dist/src/core/hooks/handlers/hook-router.js +5 -0
- package/dist/src/core/hooks/handlers/hook-router.js.map +1 -1
- package/dist/src/core/hooks/handlers/pre-compact.d.ts +33 -0
- package/dist/src/core/hooks/handlers/pre-compact.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/pre-compact.js +109 -0
- package/dist/src/core/hooks/handlers/pre-compact.js.map +1 -0
- package/dist/src/core/hooks/handlers/types.d.ts +1 -1
- package/dist/src/core/hooks/handlers/types.d.ts.map +1 -1
- package/dist/src/core/hooks/handlers/types.js +3 -0
- package/dist/src/core/hooks/handlers/types.js.map +1 -1
- package/dist/src/core/session/handoff-doc-format.d.ts +164 -0
- package/dist/src/core/session/handoff-doc-format.d.ts.map +1 -0
- package/dist/src/core/session/handoff-doc-format.js +292 -0
- package/dist/src/core/session/handoff-doc-format.js.map +1 -0
- package/dist/src/core/session/handoff-git-state.d.ts +49 -0
- package/dist/src/core/session/handoff-git-state.d.ts.map +1 -0
- package/dist/src/core/session/handoff-git-state.js +164 -0
- package/dist/src/core/session/handoff-git-state.js.map +1 -0
- package/dist/src/core/session/handoff-secret-scrub.d.ts +59 -0
- package/dist/src/core/session/handoff-secret-scrub.d.ts.map +1 -0
- package/dist/src/core/session/handoff-secret-scrub.js +72 -0
- package/dist/src/core/session/handoff-secret-scrub.js.map +1 -0
- package/dist/src/core/session/{handoff-context.d.ts → install-handoff-context.d.ts} +7 -3
- package/dist/src/core/session/install-handoff-context.d.ts.map +1 -0
- package/dist/src/core/session/{handoff-context.js → install-handoff-context.js} +7 -3
- package/dist/src/core/session/install-handoff-context.js.map +1 -0
- package/dist/src/core/session/work-handoff.d.ts +88 -0
- package/dist/src/core/session/work-handoff.d.ts.map +1 -0
- package/dist/src/core/session/work-handoff.js +412 -0
- package/dist/src/core/session/work-handoff.js.map +1 -0
- package/dist/src/generators/spec/task-parser.d.ts.map +1 -1
- package/dist/src/generators/spec/task-parser.js +38 -16
- package/dist/src/generators/spec/task-parser.js.map +1 -1
- package/dist/src/utils/fs-native.d.ts +1 -1
- package/package.json +2 -2
- package/plugins/specweave/commands/handoff.md +54 -0
- package/plugins/specweave/lib/integrations/github/github-access-error.js +43 -0
- package/plugins/specweave/lib/integrations/github/github-access-error.ts +103 -0
- package/plugins/specweave/lib/integrations/github/github-client-v2.js +24 -4
- package/plugins/specweave/lib/integrations/github/github-client-v2.ts +26 -4
- package/plugins/specweave/lib/vendor/generators/spec/task-parser.js +38 -16
- package/plugins/specweave/lib/vendor/generators/spec/task-parser.js.map +1 -1
- package/plugins/specweave/lib/vendor/utils/fs-native.d.ts +1 -1
- package/plugins/specweave/skills/handoff/SKILL.md +59 -0
- package/dist/dashboard/assets/index-YkogWPHY.css +0 -1
- package/dist/src/core/session/handoff-context.d.ts.map +0 -1
- package/dist/src/core/session/handoff-context.js.map +0 -1
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Work Handoff Builder
|
|
3
|
+
*
|
|
4
|
+
* Assembles a portable, secret-scrubbed handoff document (+ a full diff of
|
|
5
|
+
* uncommitted edits) from durable on-disk state, so a developer can stop work
|
|
6
|
+
* in one AI tool and resume in another. This is the single deterministic engine
|
|
7
|
+
* behind the `specweave handoff` CLI, the `/sw:handoff` command, and the
|
|
8
|
+
* PreCompact hook — all of which call {@link buildWorkHandoff}.
|
|
9
|
+
*
|
|
10
|
+
* Workspace detection is intentionally NOT a raw `.specweave/` directory test:
|
|
11
|
+
* a stale child-repo `.specweave/` (no real state) would misclassify. We resolve
|
|
12
|
+
* the effective root then require an `active-increment.json` that actually
|
|
13
|
+
* lists increments. Metadata reads are gated with `MetadataManager.exists()`
|
|
14
|
+
* because `MetadataManager.read()` LAZILY CREATES default metadata — a side
|
|
15
|
+
* effect a read-only handoff must never trigger.
|
|
16
|
+
*
|
|
17
|
+
* All increment/task/AC/workspace logic is REUSED from existing modules (DRY):
|
|
18
|
+
* `parseTasksWithUSLinks`, `calculateProgressFromTasksFile`,
|
|
19
|
+
* `ActiveIncrementManager.getActive()`, `MetadataManager`, `resolveEffectiveRoot`.
|
|
20
|
+
*
|
|
21
|
+
* Part of increment 0867: Cross-Tool Work Handoff
|
|
22
|
+
* (AC-US1-03..07, AC-US3-01..05, AC-US4-*, AC-US6-01/02/05).
|
|
23
|
+
*
|
|
24
|
+
* @module core/session/work-handoff
|
|
25
|
+
*/
|
|
26
|
+
import * as fs from 'fs';
|
|
27
|
+
import * as path from 'path';
|
|
28
|
+
import { resolveEffectiveRoot } from '../../utils/find-project-root.js';
|
|
29
|
+
import { ActiveIncrementManager } from '../increment/active-increment-manager.js';
|
|
30
|
+
import { MetadataManager } from '../increment/metadata-manager.js';
|
|
31
|
+
import { parseTasksWithUSLinks } from '../../generators/spec/task-parser.js';
|
|
32
|
+
import { calculateProgressFromTasksFile } from '../../progress/us-progress-tracker.js';
|
|
33
|
+
import { captureGitState } from './handoff-git-state.js';
|
|
34
|
+
import { scrubSecrets } from './handoff-secret-scrub.js';
|
|
35
|
+
import { renderHandoffDoc, renderPastePrompt, DOC_FORMAT_MARKER, } from './handoff-doc-format.js';
|
|
36
|
+
/**
|
|
37
|
+
* Thrown when 2+ increments are active and no explicit id was supplied.
|
|
38
|
+
* Carries the candidate ids so the CLI can list them.
|
|
39
|
+
*/
|
|
40
|
+
export class AmbiguousActiveIncrementError extends Error {
|
|
41
|
+
constructor(candidates) {
|
|
42
|
+
super(`Multiple active increments — pass an explicit id. Candidates: ${candidates.join(', ')}`);
|
|
43
|
+
this.candidates = candidates;
|
|
44
|
+
this.name = 'AmbiguousActiveIncrementError';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Build a handoff for `repoRoot`.
|
|
49
|
+
*
|
|
50
|
+
* @param repoRoot - Where to start workspace resolution from (usually cwd).
|
|
51
|
+
* @param opts - {@link WorkHandoffOptions}.
|
|
52
|
+
* @returns {@link WorkHandoffResult}.
|
|
53
|
+
* @throws {AmbiguousActiveIncrementError} when 2+ active increments + no id.
|
|
54
|
+
*/
|
|
55
|
+
export async function buildWorkHandoff(repoRoot, opts = {}) {
|
|
56
|
+
// Resolve the effective workspace root. `resolveEffectiveRoot` returns
|
|
57
|
+
// process.cwd() as a last resort when the start dir is not inside any
|
|
58
|
+
// SpecWeave/umbrella tree — which would wrongly anchor a plain repo to the
|
|
59
|
+
// caller's cwd. So we only ACCEPT the resolved root when it actually carries
|
|
60
|
+
// SpecWeave state; otherwise we anchor to the passed `repoRoot` itself.
|
|
61
|
+
const resolved = resolveEffectiveRoot(repoRoot);
|
|
62
|
+
const resolvedHasState = fs.existsSync(path.join(resolved, '.specweave', 'state', 'active-increment.json'));
|
|
63
|
+
const passedRoot = path.resolve(repoRoot);
|
|
64
|
+
const effectiveRoot = !opts.nonSpecweave && resolvedHasState ? resolved : passedRoot;
|
|
65
|
+
// ── Workspace classification ──────────────────────────────────────────────
|
|
66
|
+
// SpecWeave only if (a) not forced off and (b) a real active-increment.json
|
|
67
|
+
// exists at the effective root. A stale .specweave/ with empty/missing
|
|
68
|
+
// active-increment.json classifies as non-SpecWeave.
|
|
69
|
+
const hasSpecweaveState = opts.nonSpecweave
|
|
70
|
+
? false
|
|
71
|
+
: fs.existsSync(path.join(effectiveRoot, '.specweave', 'state', 'active-increment.json'));
|
|
72
|
+
const activeIds = hasSpecweaveState ? readActiveIds(effectiveRoot) : [];
|
|
73
|
+
// ── Resolve which increment (if any) ──────────────────────────────────────
|
|
74
|
+
let incrementId;
|
|
75
|
+
if (hasSpecweaveState && activeIds.length > 0) {
|
|
76
|
+
if (activeIds.length === 1) {
|
|
77
|
+
incrementId = activeIds[0];
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
// 2+ active.
|
|
81
|
+
if (!opts.incrementId)
|
|
82
|
+
throw new AmbiguousActiveIncrementError(activeIds);
|
|
83
|
+
incrementId = opts.incrementId;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// A workspace is "SpecWeave" for doc purposes when it has SpecWeave state.
|
|
87
|
+
// (0 active still uses the SpecWeave write paths but with a git+config doc.)
|
|
88
|
+
const isSpecWeave = hasSpecweaveState && !opts.nonSpecweave;
|
|
89
|
+
// ── Assemble increment facts (gated, no side effects) ─────────────────────
|
|
90
|
+
let increment;
|
|
91
|
+
let planDecisions = [];
|
|
92
|
+
if (incrementId && MetadataManager.exists(incrementId, effectiveRoot)) {
|
|
93
|
+
const incDir = path.join(effectiveRoot, '.specweave', 'increments', incrementId);
|
|
94
|
+
increment = await assembleIncrementInfo(incDir, incrementId, effectiveRoot);
|
|
95
|
+
planDecisions = readPlanDecisions(path.join(incDir, 'plan.md'));
|
|
96
|
+
}
|
|
97
|
+
// ── Ambient rules from config.json ────────────────────────────────────────
|
|
98
|
+
const ambient = isSpecWeave ? readAmbientRules(effectiveRoot) : undefined;
|
|
99
|
+
// ── Decide write paths (ownership sentinel for non-SpecWeave) ─────────────
|
|
100
|
+
const { docPath, diffPath } = resolveWritePaths(effectiveRoot, isSpecWeave, incrementId, opts.out);
|
|
101
|
+
// ── Git state + full diff dump (free, no tokens) ──────────────────────────
|
|
102
|
+
const git = captureGitState(effectiveRoot, diffPath);
|
|
103
|
+
// ── Scrub free-text + the captured diff before any write ──────────────────
|
|
104
|
+
const mergedDecisions = [...planDecisions, ...(opts.decisions ?? [])];
|
|
105
|
+
const scrubbedText = scrubFields({
|
|
106
|
+
reason: opts.reason,
|
|
107
|
+
summary: opts.summary,
|
|
108
|
+
next: opts.next,
|
|
109
|
+
gotcha: opts.gotcha,
|
|
110
|
+
decisions: mergedDecisions,
|
|
111
|
+
});
|
|
112
|
+
const redactionCounts = scrubbedText.counts;
|
|
113
|
+
// Re-scrub the diff file in place (captureGitState wrote the raw diff).
|
|
114
|
+
scrubDiffFileInPlace(diffPath, redactionCounts);
|
|
115
|
+
// ── Render ────────────────────────────────────────────────────────────────
|
|
116
|
+
const docInput = {
|
|
117
|
+
docPath,
|
|
118
|
+
diffPath,
|
|
119
|
+
repoRoot: effectiveRoot,
|
|
120
|
+
generatedAt: new Date().toISOString(),
|
|
121
|
+
isSpecWeave,
|
|
122
|
+
reason: scrubbedText.reason,
|
|
123
|
+
summary: scrubbedText.summary,
|
|
124
|
+
next: scrubbedText.next,
|
|
125
|
+
gotcha: scrubbedText.gotcha,
|
|
126
|
+
decisions: scrubbedText.decisions,
|
|
127
|
+
increment,
|
|
128
|
+
ambient,
|
|
129
|
+
git,
|
|
130
|
+
redactionCounts,
|
|
131
|
+
};
|
|
132
|
+
const docMarkdown = renderHandoffDoc(docInput);
|
|
133
|
+
const pastePrompt = renderPastePrompt(docInput, { inline: opts.inline });
|
|
134
|
+
// ── Write doc(s) ──────────────────────────────────────────────────────────
|
|
135
|
+
writeDoc(docPath, docMarkdown);
|
|
136
|
+
// SpecWeave + active increment: also write the stable convenience copy.
|
|
137
|
+
if (isSpecWeave && incrementId && !opts.out) {
|
|
138
|
+
const latest = path.join(effectiveRoot, '.specweave', 'state', 'handoff-latest.md');
|
|
139
|
+
writeDoc(latest, docMarkdown);
|
|
140
|
+
}
|
|
141
|
+
return { docPath, diffPath, docMarkdown, pastePrompt, isSpecWeave };
|
|
142
|
+
}
|
|
143
|
+
// ───────────────────────────────────────────────────────────────────────────
|
|
144
|
+
// Internals
|
|
145
|
+
// ───────────────────────────────────────────────────────────────────────────
|
|
146
|
+
/** Read active increment ids straight from the state file (no lazy create). */
|
|
147
|
+
function readActiveIds(effectiveRoot) {
|
|
148
|
+
try {
|
|
149
|
+
const mgr = new ActiveIncrementManager(effectiveRoot);
|
|
150
|
+
return mgr.getActive();
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return [];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Assemble per-increment facts: status, current/next task, task% and AC counts,
|
|
158
|
+
* acSyncEvents drift. Reuses the shared parsers; never lazily creates metadata.
|
|
159
|
+
*/
|
|
160
|
+
async function assembleIncrementInfo(incDir, incrementId, effectiveRoot) {
|
|
161
|
+
// Status comes from the already-existing metadata file (exists()-gated by caller).
|
|
162
|
+
let status = 'unknown';
|
|
163
|
+
let acSyncEvents = [];
|
|
164
|
+
try {
|
|
165
|
+
const metaRaw = JSON.parse(fs.readFileSync(path.join(incDir, 'metadata.json'), 'utf-8'));
|
|
166
|
+
if (metaRaw.status)
|
|
167
|
+
status = metaRaw.status;
|
|
168
|
+
// acSyncEvents is stored dynamically (not in the typed interface) — read defensively.
|
|
169
|
+
if (Array.isArray(metaRaw.acSyncEvents)) {
|
|
170
|
+
acSyncEvents = metaRaw.acSyncEvents.slice(0, 5).map((ev) => {
|
|
171
|
+
const updated = ev.updated?.length ?? ev.changesCount ?? 0;
|
|
172
|
+
const conflicts = ev.conflicts?.length ?? 0;
|
|
173
|
+
return `${ev.timestamp}: ${updated} ACs updated, ${conflicts} conflicts`;
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
// Metadata unreadable — leave defaults.
|
|
179
|
+
}
|
|
180
|
+
const title = readSpecTitle(path.join(incDir, 'spec.md'));
|
|
181
|
+
// Tasks: counts/% via the shared progress fn; current = first non-completed,
|
|
182
|
+
// next = the one after it (from the same parser's status — fixed in 0867 to
|
|
183
|
+
// read the canonical one-line `… | **Status**: [x] …` format correctly).
|
|
184
|
+
const tasksPath = path.join(incDir, 'tasks.md');
|
|
185
|
+
let currentTask;
|
|
186
|
+
let nextTask;
|
|
187
|
+
let doneTasks = 0;
|
|
188
|
+
let totalTasks = 0;
|
|
189
|
+
let taskPercentage = 0;
|
|
190
|
+
if (fs.existsSync(tasksPath)) {
|
|
191
|
+
const progress = await calculateProgressFromTasksFile(tasksPath);
|
|
192
|
+
doneTasks = progress.completedTasks;
|
|
193
|
+
totalTasks = progress.totalTasks;
|
|
194
|
+
taskPercentage = progress.percentage;
|
|
195
|
+
const allTasks = Object.values(parseTasksWithUSLinks(tasksPath)).flat();
|
|
196
|
+
const pending = allTasks
|
|
197
|
+
.filter((t) => t.status !== 'completed' && t.status !== 'canceled')
|
|
198
|
+
// parseTasksWithUSLinks groups by user story, so the flattened order is
|
|
199
|
+
// US-major, not T-id order. Sort by numeric T-id so "current"/"next"
|
|
200
|
+
// reflect real task sequence even with interleaved per-US numbering.
|
|
201
|
+
.sort((a, b) => taskIdNum(a.id) - taskIdNum(b.id));
|
|
202
|
+
if (pending.length > 0)
|
|
203
|
+
currentTask = `${pending[0].id}: ${pending[0].title}`;
|
|
204
|
+
if (pending.length > 1)
|
|
205
|
+
nextTask = `${pending[1].id}: ${pending[1].title}`;
|
|
206
|
+
}
|
|
207
|
+
// ACs from spec.md checkboxes.
|
|
208
|
+
const { doneAcs, totalAcs } = countSpecAcs(path.join(incDir, 'spec.md'));
|
|
209
|
+
return {
|
|
210
|
+
id: incrementId,
|
|
211
|
+
status,
|
|
212
|
+
title,
|
|
213
|
+
currentTask,
|
|
214
|
+
nextTask,
|
|
215
|
+
doneTasks,
|
|
216
|
+
totalTasks,
|
|
217
|
+
taskPercentage,
|
|
218
|
+
doneAcs,
|
|
219
|
+
totalAcs,
|
|
220
|
+
acSyncEvents,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
/** Numeric portion of a `T-007` / `T-012E` task id, for ordering. */
|
|
224
|
+
function taskIdNum(id) {
|
|
225
|
+
const m = id.match(/T-(\d+)/);
|
|
226
|
+
return m ? parseInt(m[1], 10) : Number.MAX_SAFE_INTEGER;
|
|
227
|
+
}
|
|
228
|
+
/** Count `- [ ] AC-...` / `- [x] AC-...` checkboxes in spec.md. */
|
|
229
|
+
function countSpecAcs(specPath) {
|
|
230
|
+
if (!fs.existsSync(specPath))
|
|
231
|
+
return { doneAcs: 0, totalAcs: 0 };
|
|
232
|
+
const acRegex = /^-\s+\[([ x])\]\s+\*{0,2}(AC-[A-Z0-9-]+)\*{0,2}/;
|
|
233
|
+
let done = 0;
|
|
234
|
+
let total = 0;
|
|
235
|
+
for (const line of fs.readFileSync(specPath, 'utf-8').split('\n')) {
|
|
236
|
+
const m = line.match(acRegex);
|
|
237
|
+
if (m) {
|
|
238
|
+
total += 1;
|
|
239
|
+
if (m[1] === 'x')
|
|
240
|
+
done += 1;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return { doneAcs: done, totalAcs: total };
|
|
244
|
+
}
|
|
245
|
+
/** Read the `title:` from spec.md frontmatter, if present. */
|
|
246
|
+
function readSpecTitle(specPath) {
|
|
247
|
+
if (!fs.existsSync(specPath))
|
|
248
|
+
return undefined;
|
|
249
|
+
const content = fs.readFileSync(specPath, 'utf-8');
|
|
250
|
+
const m = content.match(/^title:\s*["']?(.+?)["']?\s*$/m);
|
|
251
|
+
return m ? m[1] : undefined;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Extract decision-ish bullets from plan.md `## Approach`, `## Components`,
|
|
255
|
+
* `## Risks` sections. Best-effort: each bullet line becomes a decision.
|
|
256
|
+
*/
|
|
257
|
+
function readPlanDecisions(planPath) {
|
|
258
|
+
if (!fs.existsSync(planPath))
|
|
259
|
+
return [];
|
|
260
|
+
const lines = fs.readFileSync(planPath, 'utf-8').split('\n');
|
|
261
|
+
const wanted = new Set(['approach', 'risks', 'key decisions', 'decisions']);
|
|
262
|
+
const decisions = [];
|
|
263
|
+
let capture = false;
|
|
264
|
+
for (const line of lines) {
|
|
265
|
+
const heading = line.match(/^##\s+(.+?)\s*$/);
|
|
266
|
+
if (heading) {
|
|
267
|
+
capture = wanted.has(heading[1].trim().toLowerCase());
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
if (capture) {
|
|
271
|
+
const bullet = line.match(/^[-*]\s+(.+)/);
|
|
272
|
+
if (bullet)
|
|
273
|
+
decisions.push(bullet[1].trim());
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return decisions.slice(0, 10);
|
|
277
|
+
}
|
|
278
|
+
/** Read ambient rules (test mode / coverage target / WIP limit) from config.json. */
|
|
279
|
+
function readAmbientRules(effectiveRoot) {
|
|
280
|
+
try {
|
|
281
|
+
const cfg = JSON.parse(fs.readFileSync(path.join(effectiveRoot, '.specweave', 'config.json'), 'utf-8'));
|
|
282
|
+
return {
|
|
283
|
+
testMode: cfg.testing?.defaultTestMode,
|
|
284
|
+
coverageTarget: cfg.testing?.defaultCoverageTarget,
|
|
285
|
+
wipLimit: cfg.limits?.maxActiveIncrements,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
return {};
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Decide doc + diff paths.
|
|
294
|
+
*
|
|
295
|
+
* - explicit `out`: use it (diff is a sibling `.diff`).
|
|
296
|
+
* - SpecWeave + active increment: `reports/handoff.md` (the stable copy is
|
|
297
|
+
* written separately by the caller).
|
|
298
|
+
* - SpecWeave, no active increment: `state/handoff-latest.md`.
|
|
299
|
+
* - non-SpecWeave: `.handoff/HANDOFF.md`, unless a foreign root `./HANDOFF.md`
|
|
300
|
+
* without the marker exists (ownership sentinel still routes to `.handoff/`).
|
|
301
|
+
*/
|
|
302
|
+
function resolveWritePaths(effectiveRoot, isSpecWeave, incrementId, out) {
|
|
303
|
+
if (out) {
|
|
304
|
+
const abs = path.isAbsolute(out) ? out : path.join(effectiveRoot, out);
|
|
305
|
+
return { docPath: abs, diffPath: siblingDiff(abs) };
|
|
306
|
+
}
|
|
307
|
+
if (isSpecWeave && incrementId) {
|
|
308
|
+
const docPath = path.join(effectiveRoot, '.specweave', 'increments', incrementId, 'reports', 'handoff.md');
|
|
309
|
+
const diffPath = path.join(effectiveRoot, '.specweave', 'state', 'handoff-latest.diff');
|
|
310
|
+
return { docPath, diffPath };
|
|
311
|
+
}
|
|
312
|
+
if (isSpecWeave) {
|
|
313
|
+
const docPath = path.join(effectiveRoot, '.specweave', 'state', 'handoff-latest.md');
|
|
314
|
+
const diffPath = path.join(effectiveRoot, '.specweave', 'state', 'handoff-latest.diff');
|
|
315
|
+
return { docPath, diffPath };
|
|
316
|
+
}
|
|
317
|
+
// Non-SpecWeave. Default target is the repo-root ./HANDOFF.md, but only if it
|
|
318
|
+
// is OURS: a root ./HANDOFF.md that already carries the Doc format v1 marker
|
|
319
|
+
// is a prior handoff we may overwrite in-place. A root ./HANDOFF.md WITHOUT
|
|
320
|
+
// the marker is a foreign file (a project's own HANDOFF) — the ownership
|
|
321
|
+
// sentinel refuses to clobber it and routes to .handoff/ instead.
|
|
322
|
+
const rootHandoff = path.join(effectiveRoot, 'HANDOFF.md');
|
|
323
|
+
if (fs.existsSync(rootHandoff) && !isForeignHandoffFile(rootHandoff)) {
|
|
324
|
+
return { docPath: rootHandoff, diffPath: siblingDiff(rootHandoff) };
|
|
325
|
+
}
|
|
326
|
+
// No (safe) root file → write under .handoff/ (also the foreign-file case).
|
|
327
|
+
ensureHandoffDir(effectiveRoot);
|
|
328
|
+
const docPath = path.join(effectiveRoot, '.handoff', 'HANDOFF.md');
|
|
329
|
+
const diffPath = path.join(effectiveRoot, '.handoff', 'handoff.diff');
|
|
330
|
+
return { docPath, diffPath };
|
|
331
|
+
}
|
|
332
|
+
/** Sibling `<name>.diff` for an arbitrary doc path. */
|
|
333
|
+
function siblingDiff(docPath) {
|
|
334
|
+
const ext = path.extname(docPath);
|
|
335
|
+
return docPath.slice(0, docPath.length - ext.length) + '.diff';
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Create `.handoff/` + a `.gitignore` containing `*` so the doc, diff, and any
|
|
339
|
+
* scrubbed-but-still-sensitive content never enter git by default.
|
|
340
|
+
*/
|
|
341
|
+
function ensureHandoffDir(effectiveRoot) {
|
|
342
|
+
const dir = path.join(effectiveRoot, '.handoff');
|
|
343
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
344
|
+
const gi = path.join(dir, '.gitignore');
|
|
345
|
+
if (!fs.existsSync(gi))
|
|
346
|
+
fs.writeFileSync(gi, '*\n', 'utf-8');
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Ownership sentinel: is a root `./HANDOFF.md` a foreign file (lacks the
|
|
350
|
+
* `Doc format v1` marker)? Exposed for the builder + tests. When foreign, the
|
|
351
|
+
* caller must NOT overwrite it.
|
|
352
|
+
*/
|
|
353
|
+
export function isForeignHandoffFile(handoffPath) {
|
|
354
|
+
if (!fs.existsSync(handoffPath))
|
|
355
|
+
return false;
|
|
356
|
+
const content = fs.readFileSync(handoffPath, 'utf-8');
|
|
357
|
+
return !content.includes(DOC_FORMAT_MARKER);
|
|
358
|
+
}
|
|
359
|
+
/** Write a doc, creating parent dirs. */
|
|
360
|
+
function writeDoc(docPath, markdown) {
|
|
361
|
+
fs.mkdirSync(path.dirname(docPath), { recursive: true });
|
|
362
|
+
fs.writeFileSync(docPath, markdown, 'utf-8');
|
|
363
|
+
}
|
|
364
|
+
/** Scrub the free-text fields, accumulating per-pattern counts. */
|
|
365
|
+
function scrubFields(fields) {
|
|
366
|
+
const counts = {};
|
|
367
|
+
const add = (c) => {
|
|
368
|
+
for (const [k, v] of Object.entries(c))
|
|
369
|
+
counts[k] = (counts[k] ?? 0) + v;
|
|
370
|
+
};
|
|
371
|
+
const one = (s) => {
|
|
372
|
+
if (s == null)
|
|
373
|
+
return s;
|
|
374
|
+
const r = scrubSecrets(s);
|
|
375
|
+
add(r.counts);
|
|
376
|
+
return r.scrubbed;
|
|
377
|
+
};
|
|
378
|
+
const decisions = fields.decisions.map((d) => {
|
|
379
|
+
const r = scrubSecrets(d);
|
|
380
|
+
add(r.counts);
|
|
381
|
+
return r.scrubbed;
|
|
382
|
+
});
|
|
383
|
+
return {
|
|
384
|
+
reason: one(fields.reason),
|
|
385
|
+
summary: one(fields.summary),
|
|
386
|
+
next: one(fields.next),
|
|
387
|
+
gotcha: one(fields.gotcha),
|
|
388
|
+
decisions,
|
|
389
|
+
counts,
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Re-read the raw diff file captureGitState wrote, scrub it, write it back, and
|
|
394
|
+
* fold its redaction counts into the running totals.
|
|
395
|
+
*/
|
|
396
|
+
function scrubDiffFileInPlace(diffPath, counts) {
|
|
397
|
+
try {
|
|
398
|
+
if (!fs.existsSync(diffPath))
|
|
399
|
+
return;
|
|
400
|
+
const raw = fs.readFileSync(diffPath, 'utf-8');
|
|
401
|
+
if (!raw)
|
|
402
|
+
return;
|
|
403
|
+
const { scrubbed, counts: diffCounts } = scrubSecrets(raw);
|
|
404
|
+
fs.writeFileSync(diffPath, scrubbed, 'utf-8');
|
|
405
|
+
for (const [k, v] of Object.entries(diffCounts))
|
|
406
|
+
counts[k] = (counts[k] ?? 0) + v;
|
|
407
|
+
}
|
|
408
|
+
catch {
|
|
409
|
+
// Best-effort.
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
//# sourceMappingURL=work-handoff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"work-handoff.js","sourceRoot":"","sources":["../../../../src/core/session/work-handoff.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-parser.d.ts","sourceRoot":"","sources":["../../../../src/generators/spec/task-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB,8BAA8B;IAC9B,EAAE,EAAE,MAAM,CAAC;IAEX,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAC;IAEd,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB,6BAA6B;IAC7B,MAAM,EAAE,UAAU,CAAC;IAEnB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB,4BAA4B;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,kCAAkC;IAClC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,aAAa,GAAG,WAAW,GAAG,aAAa,GAAG,UAAU,CAAC;AAE9F;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,WAAW,GAAG,cAAc,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAaD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,
|
|
1
|
+
{"version":3,"file":"task-parser.d.ts","sourceRoot":"","sources":["../../../../src/generators/spec/task-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB,8BAA8B;IAC9B,EAAE,EAAE,MAAM,CAAC;IAEX,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAC;IAEd,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB,6BAA6B;IAC7B,MAAM,EAAE,UAAU,CAAC;IAEnB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB,4BAA4B;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,kCAAkC;IAClC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,aAAa,GAAG,WAAW,GAAG,aAAa,GAAG,UAAU,CAAC;AAE9F;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,WAAW,GAAG,cAAc,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAaD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,CAiKzE;AAoBD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,MAAM,EAAE,EACpB,UAAU,EAAE,MAAM,EAAE,GACnB,gBAAgB,EAAE,CAyEpB;AAkBD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,gBAAgB,GAAG,IAAI,EAAE,CAE/D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,gBAAgB,GAAG,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAc1F;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,SAAS,EAAE,gBAAgB,GAAG,MAAM,CAMjF"}
|
|
@@ -37,13 +37,27 @@ export function parseTasksWithUSLinks(tasksPath) {
|
|
|
37
37
|
const lines = content.split('\n');
|
|
38
38
|
// Regex patterns for task parsing (T-029: Support E suffix for external IDs)
|
|
39
39
|
// Updated: Support 3+ digits for T-XXX and US-XXX (Y2K fix)
|
|
40
|
+
//
|
|
41
|
+
// 0867: These field regexes are NOT `^`-anchored. The canonical task format
|
|
42
|
+
// combines several fields on ONE line separated by `|`:
|
|
43
|
+
// **User Story**: US-001 | **Satisfies ACs**: AC-US1-01 | **Status**: [x] completed
|
|
44
|
+
// The line is split on `|` and each segment matched independently (see
|
|
45
|
+
// below). Previously these were `^`-anchored and the userStory match
|
|
46
|
+
// early-`continue`d, silently dropping same-line `Satisfies ACs`/`Status` —
|
|
47
|
+
// making every combined-format task read as `pending` (whole-codebase bug).
|
|
48
|
+
// The multi-line format (each `**Field**:` on its own line) still parses
|
|
49
|
+
// because each line is a single segment.
|
|
40
50
|
const taskHeaderRegex = /^###\s+(T-\d{3,}E?):\s*(.+)$/;
|
|
41
|
-
const userStoryRegex =
|
|
42
|
-
const satisfiesACsRegex =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
const userStoryRegex = /\*\*User Story\*\*:\s*(US-\d{3,}E?)/;
|
|
52
|
+
const satisfiesACsRegex = /\*\*Satisfies ACs\*\*:\s*(AC-US\d+E?-\d{2}(?:,\s*AC-US\d+E?-\d{2})*)/;
|
|
53
|
+
// Trailing status word is OPTIONAL: a checkbox-only `**Status**: [x]` is a
|
|
54
|
+
// valid completed task. The checkbox is the source of truth (see
|
|
55
|
+
// parseTaskStatus), so requiring `(\w+)` here would silently under-report a
|
|
56
|
+
// bare-checkbox task as pending — the same drop-class T-019 fixed.
|
|
57
|
+
const statusRegex = /\*\*Status\*\*:\s*\[([x ])\]\s*(\w+)?/;
|
|
58
|
+
const priorityRegex = /\*\*Priority\*\*:\s*([^|]+)/;
|
|
59
|
+
const estimatedEffortRegex = /\*\*Estimated Effort\*\*:\s*([^|]+)/;
|
|
60
|
+
const dependenciesRegex = /\*\*Dependencies\*\*:\s*([^|]+)/;
|
|
47
61
|
let currentTask = null;
|
|
48
62
|
let currentDescription = [];
|
|
49
63
|
let currentSection = 'none';
|
|
@@ -71,11 +85,16 @@ export function parseTasksWithUSLinks(tasksPath) {
|
|
|
71
85
|
// Skip if no current task
|
|
72
86
|
if (!currentTask)
|
|
73
87
|
continue;
|
|
74
|
-
// Parse task fields
|
|
88
|
+
// Parse task fields. A single line may carry MULTIPLE `**Field**:`
|
|
89
|
+
// segments separated by `|`, so we extract EVERY recognized field from
|
|
90
|
+
// the line instead of early-`continue`ing after the first match. The
|
|
91
|
+
// regexes are unanchored (above), and value-capturing fields stop at `|`
|
|
92
|
+
// so a later segment's value isn't swallowed.
|
|
93
|
+
let matchedAnyField = false;
|
|
75
94
|
const userStoryMatch = line.match(userStoryRegex);
|
|
76
95
|
if (userStoryMatch) {
|
|
77
96
|
currentTask.userStory = userStoryMatch[1];
|
|
78
|
-
|
|
97
|
+
matchedAnyField = true;
|
|
79
98
|
}
|
|
80
99
|
const satisfiesACsMatch = line.match(satisfiesACsRegex);
|
|
81
100
|
if (satisfiesACsMatch) {
|
|
@@ -83,24 +102,25 @@ export function parseTasksWithUSLinks(tasksPath) {
|
|
|
83
102
|
currentTask.satisfiesACs = satisfiesACsMatch[1]
|
|
84
103
|
.split(',')
|
|
85
104
|
.map(ac => ac.trim());
|
|
86
|
-
|
|
105
|
+
matchedAnyField = true;
|
|
87
106
|
}
|
|
88
107
|
const statusMatch = line.match(statusRegex);
|
|
89
108
|
if (statusMatch) {
|
|
90
109
|
const checkbox = statusMatch[1];
|
|
91
|
-
|
|
110
|
+
// statusMatch[2] is optional (bare `[x]` has no trailing word).
|
|
111
|
+
const statusText = (statusMatch[2] ?? '').toLowerCase();
|
|
92
112
|
currentTask.status = parseTaskStatus(checkbox, statusText);
|
|
93
|
-
|
|
113
|
+
matchedAnyField = true;
|
|
94
114
|
}
|
|
95
115
|
const priorityMatch = line.match(priorityRegex);
|
|
96
116
|
if (priorityMatch) {
|
|
97
|
-
currentTask.priority = priorityMatch[1];
|
|
98
|
-
|
|
117
|
+
currentTask.priority = priorityMatch[1].trim();
|
|
118
|
+
matchedAnyField = true;
|
|
99
119
|
}
|
|
100
120
|
const estimatedEffortMatch = line.match(estimatedEffortRegex);
|
|
101
121
|
if (estimatedEffortMatch) {
|
|
102
|
-
currentTask.estimatedEffort = estimatedEffortMatch[1];
|
|
103
|
-
|
|
122
|
+
currentTask.estimatedEffort = estimatedEffortMatch[1].trim();
|
|
123
|
+
matchedAnyField = true;
|
|
104
124
|
}
|
|
105
125
|
const dependenciesMatch = line.match(dependenciesRegex);
|
|
106
126
|
if (dependenciesMatch) {
|
|
@@ -109,8 +129,10 @@ export function parseTasksWithUSLinks(tasksPath) {
|
|
|
109
129
|
.split(',')
|
|
110
130
|
.map(dep => dep.trim())
|
|
111
131
|
.filter(dep => dep.match(/^T-\d{3,}$/));
|
|
112
|
-
|
|
132
|
+
matchedAnyField = true;
|
|
113
133
|
}
|
|
134
|
+
if (matchedAnyField)
|
|
135
|
+
continue;
|
|
114
136
|
// Track sections for description parsing
|
|
115
137
|
if (line.startsWith('**Description**:')) {
|
|
116
138
|
currentSection = 'description';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-parser.js","sourceRoot":"","sources":["../../../../src/generators/spec/task-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAgElC;;GAEG;AACH,SAAS,eAAe,CAAC,QAAgB,EAAE,UAAkB;IAC3D,IAAI,QAAQ,KAAK,GAAG;QAAE,OAAO,WAAW,CAAC;IACzC,IAAI,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC;QAAE,OAAO,aAAa,CAAC;IAC1D,IAAI,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC;QAAE,OAAO,aAAa,CAAC;IAC1D,IAAI,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,UAAU,CAAC;IACrD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,SAAiB;IACrD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACjD,MAAM,KAAK,GAAqB,EAAE,CAAC;QAEnC,oDAAoD;QACpD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,6EAA6E;QAC7E,4DAA4D;QAC5D,MAAM,eAAe,GAAG,8BAA8B,CAAC;QACvD,MAAM,cAAc,GAAG,
|
|
1
|
+
{"version":3,"file":"task-parser.js","sourceRoot":"","sources":["../../../../src/generators/spec/task-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -201,7 +201,7 @@ declare const _default: {
|
|
|
201
201
|
ensureFileSync: typeof ensureFileSync;
|
|
202
202
|
readFileSync: typeof readFileSync;
|
|
203
203
|
writeFileSync: typeof writeFileSync;
|
|
204
|
-
statSync:
|
|
204
|
+
statSync: typeof statSync;
|
|
205
205
|
readdirSync: typeof readdirSync;
|
|
206
206
|
unlinkSync: typeof unlinkSync;
|
|
207
207
|
mkdirSync: typeof mkdirSync;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specweave",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.588",
|
|
4
4
|
"description": "100+ domain-expert AI skills — PM, Architect, Frontend, QA, Security and more. Skills learn your team's patterns permanently. Spec-first planning, autonomous execution, multi-agent teams, synced to GitHub/JIRA. Claude Code, Cursor, Copilot & more.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"LICENSE"
|
|
92
92
|
],
|
|
93
93
|
"dependencies": {
|
|
94
|
-
"@anthropic-ai/sdk": "^0.
|
|
94
|
+
"@anthropic-ai/sdk": "^0.100.1",
|
|
95
95
|
"@inquirer/prompts": "^8.1.0",
|
|
96
96
|
"@octokit/rest": "^22.0.1",
|
|
97
97
|
"@types/handlebars": "^4.0.40",
|