specweave 1.0.579 → 1.0.581

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 (115) hide show
  1. package/dist/dashboard/assets/{index-C434W7yF.js → index-Dpn4T2Mx.js} +7 -7
  2. package/dist/dashboard/index.html +1 -1
  3. package/dist/src/core/hooks/LifecycleHookDispatcher.d.ts +6 -1
  4. package/dist/src/core/hooks/LifecycleHookDispatcher.d.ts.map +1 -1
  5. package/dist/src/core/hooks/LifecycleHookDispatcher.js +66 -8
  6. package/dist/src/core/hooks/LifecycleHookDispatcher.js.map +1 -1
  7. package/dist/src/core/increment/completion-validator.d.ts +18 -0
  8. package/dist/src/core/increment/completion-validator.d.ts.map +1 -1
  9. package/dist/src/core/increment/completion-validator.js +75 -0
  10. package/dist/src/core/increment/completion-validator.js.map +1 -1
  11. package/dist/src/core/increment/status-commands.d.ts.map +1 -1
  12. package/dist/src/core/increment/status-commands.js +16 -1
  13. package/dist/src/core/increment/status-commands.js.map +1 -1
  14. package/dist/src/core/reflect-nudge/aggregator.d.ts +33 -0
  15. package/dist/src/core/reflect-nudge/aggregator.d.ts.map +1 -0
  16. package/dist/src/core/reflect-nudge/aggregator.js +80 -0
  17. package/dist/src/core/reflect-nudge/aggregator.js.map +1 -0
  18. package/dist/src/core/reflect-nudge/eligibility.d.ts +27 -0
  19. package/dist/src/core/reflect-nudge/eligibility.d.ts.map +1 -0
  20. package/dist/src/core/reflect-nudge/eligibility.js +114 -0
  21. package/dist/src/core/reflect-nudge/eligibility.js.map +1 -0
  22. package/dist/src/core/reflect-nudge/index.d.ts +14 -0
  23. package/dist/src/core/reflect-nudge/index.d.ts.map +1 -0
  24. package/dist/src/core/reflect-nudge/index.js +14 -0
  25. package/dist/src/core/reflect-nudge/index.js.map +1 -0
  26. package/dist/src/core/reflect-nudge/interactive-prompt.d.ts +28 -0
  27. package/dist/src/core/reflect-nudge/interactive-prompt.d.ts.map +1 -0
  28. package/dist/src/core/reflect-nudge/interactive-prompt.js +52 -0
  29. package/dist/src/core/reflect-nudge/interactive-prompt.js.map +1 -0
  30. package/dist/src/core/reflect-nudge/prompt-renderer.d.ts +23 -0
  31. package/dist/src/core/reflect-nudge/prompt-renderer.d.ts.map +1 -0
  32. package/dist/src/core/reflect-nudge/prompt-renderer.js +26 -0
  33. package/dist/src/core/reflect-nudge/prompt-renderer.js.map +1 -0
  34. package/dist/src/core/reflect-nudge/session-end-nudge.d.ts +31 -0
  35. package/dist/src/core/reflect-nudge/session-end-nudge.d.ts.map +1 -0
  36. package/dist/src/core/reflect-nudge/session-end-nudge.js +44 -0
  37. package/dist/src/core/reflect-nudge/session-end-nudge.js.map +1 -0
  38. package/dist/src/core/reflection/reflect-handler.d.ts +2 -0
  39. package/dist/src/core/reflection/reflect-handler.d.ts.map +1 -1
  40. package/dist/src/core/reflection/reflect-handler.js +4 -0
  41. package/dist/src/core/reflection/reflect-handler.js.map +1 -1
  42. package/dist/src/core/rubric/rubric-evaluator.d.ts +15 -0
  43. package/dist/src/core/rubric/rubric-evaluator.d.ts.map +1 -1
  44. package/dist/src/core/rubric/rubric-evaluator.js +59 -0
  45. package/dist/src/core/rubric/rubric-evaluator.js.map +1 -1
  46. package/dist/src/core/skill-attribution.d.ts +78 -0
  47. package/dist/src/core/skill-attribution.d.ts.map +1 -0
  48. package/dist/src/core/skill-attribution.js +168 -0
  49. package/dist/src/core/skill-attribution.js.map +1 -0
  50. package/dist/src/core/skill-refine/aggregator.d.ts +36 -0
  51. package/dist/src/core/skill-refine/aggregator.d.ts.map +1 -0
  52. package/dist/src/core/skill-refine/aggregator.js +58 -0
  53. package/dist/src/core/skill-refine/aggregator.js.map +1 -0
  54. package/dist/src/core/skill-refine/apply.d.ts +48 -0
  55. package/dist/src/core/skill-refine/apply.d.ts.map +1 -0
  56. package/dist/src/core/skill-refine/apply.js +97 -0
  57. package/dist/src/core/skill-refine/apply.js.map +1 -0
  58. package/dist/src/core/skill-refine/approval.d.ts +71 -0
  59. package/dist/src/core/skill-refine/approval.d.ts.map +1 -0
  60. package/dist/src/core/skill-refine/approval.js +113 -0
  61. package/dist/src/core/skill-refine/approval.js.map +1 -0
  62. package/dist/src/core/skill-refine/haiku-diff.d.ts +66 -0
  63. package/dist/src/core/skill-refine/haiku-diff.d.ts.map +1 -0
  64. package/dist/src/core/skill-refine/haiku-diff.js +111 -0
  65. package/dist/src/core/skill-refine/haiku-diff.js.map +1 -0
  66. package/dist/src/core/skill-refine/ledger.d.ts +34 -0
  67. package/dist/src/core/skill-refine/ledger.d.ts.map +1 -0
  68. package/dist/src/core/skill-refine/ledger.js +81 -0
  69. package/dist/src/core/skill-refine/ledger.js.map +1 -0
  70. package/dist/src/core/skill-signal-emit.d.ts +46 -0
  71. package/dist/src/core/skill-signal-emit.d.ts.map +1 -0
  72. package/dist/src/core/skill-signal-emit.js +59 -0
  73. package/dist/src/core/skill-signal-emit.js.map +1 -0
  74. package/dist/src/core/skill-signals/index.d.ts +9 -0
  75. package/dist/src/core/skill-signals/index.d.ts.map +1 -0
  76. package/dist/src/core/skill-signals/index.js +9 -0
  77. package/dist/src/core/skill-signals/index.js.map +1 -0
  78. package/dist/src/core/skill-signals/reader.d.ts +30 -0
  79. package/dist/src/core/skill-signals/reader.d.ts.map +1 -0
  80. package/dist/src/core/skill-signals/reader.js +102 -0
  81. package/dist/src/core/skill-signals/reader.js.map +1 -0
  82. package/dist/src/core/skill-signals/writer.d.ts +34 -0
  83. package/dist/src/core/skill-signals/writer.d.ts.map +1 -0
  84. package/dist/src/core/skill-signals/writer.js +62 -0
  85. package/dist/src/core/skill-signals/writer.js.map +1 -0
  86. package/dist/src/core/skills/skill-judge.d.ts +8 -0
  87. package/dist/src/core/skills/skill-judge.d.ts.map +1 -1
  88. package/dist/src/core/skills/skill-judge.js +55 -0
  89. package/dist/src/core/skills/skill-judge.js.map +1 -1
  90. package/dist/src/skills/reflect-status.d.ts +23 -0
  91. package/dist/src/skills/reflect-status.d.ts.map +1 -0
  92. package/dist/src/skills/reflect-status.js +55 -0
  93. package/dist/src/skills/reflect-status.js.map +1 -0
  94. package/dist/src/skills/skill-refine.d.ts +81 -0
  95. package/dist/src/skills/skill-refine.d.ts.map +1 -0
  96. package/dist/src/skills/skill-refine.js +226 -0
  97. package/dist/src/skills/skill-refine.js.map +1 -0
  98. package/dist/src/sync/sync-coordinator.d.ts +14 -4
  99. package/dist/src/sync/sync-coordinator.d.ts.map +1 -1
  100. package/dist/src/sync/sync-coordinator.js +100 -38
  101. package/dist/src/sync/sync-coordinator.js.map +1 -1
  102. package/dist/src/types/skill-refinements.d.ts +75 -0
  103. package/dist/src/types/skill-refinements.d.ts.map +1 -0
  104. package/dist/src/types/skill-refinements.js +43 -0
  105. package/dist/src/types/skill-refinements.js.map +1 -0
  106. package/dist/src/types/skill-signals.d.ts +200 -0
  107. package/dist/src/types/skill-signals.d.ts.map +1 -0
  108. package/dist/src/types/skill-signals.js +115 -0
  109. package/dist/src/types/skill-signals.js.map +1 -0
  110. package/package.json +2 -2
  111. package/plugins/specweave/commands/reflect.md +48 -0
  112. package/plugins/specweave/skills/code-reviewer/SKILL.md +4 -0
  113. package/plugins/specweave/skills/judge-llm/SKILL.md +4 -0
  114. package/plugins/specweave/skills/skill-gen/SKILL.md +8 -0
  115. package/plugins/specweave/skills/skill-refine/SKILL.md +96 -0
@@ -0,0 +1,55 @@
1
+ /**
2
+ * `sw:reflect --status` dashboard renderer — produces the markdown output
3
+ * for the status command, including the new `## Skill Refinement
4
+ * Suggestions` section (AC-US4-01 … AC-US4-03).
5
+ *
6
+ * The skill's command.md invokes this through a thin CLI shim; the markdown
7
+ * layer does not generate the dashboard on its own anymore.
8
+ *
9
+ * @module skills/reflect-status
10
+ */
11
+ import * as path from 'path';
12
+ import { aggregateSuggestions, REFINEMENT_SUGGESTION_THRESHOLD, } from '../core/reflect-nudge/aggregator.js';
13
+ /**
14
+ * Build the `## Skill Refinement Suggestions` section.
15
+ *
16
+ * Returns `null` when no skills meet the threshold — callers must NOT emit
17
+ * any heading in that case (AC-US4-03).
18
+ */
19
+ export async function renderRefinementSuggestionsSection(opts = {}) {
20
+ const root = opts.projectRoot ?? process.cwd();
21
+ const signalsPath = path.join(root, '.specweave', 'state', 'skill-signals.json');
22
+ const threshold = opts.threshold ?? REFINEMENT_SUGGESTION_THRESHOLD;
23
+ const suggestions = await aggregateSuggestions(signalsPath, { threshold }).catch(() => []);
24
+ if (suggestions.length === 0)
25
+ return null;
26
+ const lines = [];
27
+ lines.push('## Skill Refinement Suggestions');
28
+ lines.push('');
29
+ lines.push('Skills with accumulated refinement signals — sorted by severity × recency.');
30
+ lines.push('');
31
+ for (const s of suggestions) {
32
+ const sources = formatCountsBySource(s);
33
+ lines.push(`- **${s.slug}** — ${s.totalCount} signals (${sources})`);
34
+ lines.push(` - last signal: ${formatTimestamp(s.lastDetectedAt)}`);
35
+ lines.push(` - severity: ${s.highestSeverity}`);
36
+ lines.push(` - run: \`sw:skill-refine ${s.slug}\``);
37
+ }
38
+ lines.push('');
39
+ return lines.join('\n');
40
+ }
41
+ function formatCountsBySource(s) {
42
+ const parts = [];
43
+ if (s.countsBySource['judge-llm'])
44
+ parts.push(`judge-llm: ${s.countsBySource['judge-llm']}`);
45
+ if (s.countsBySource.rubric)
46
+ parts.push(`rubric: ${s.countsBySource.rubric}`);
47
+ if (s.countsBySource['code-reviewer'])
48
+ parts.push(`code-review: ${s.countsBySource['code-reviewer']}`);
49
+ return parts.join(', ');
50
+ }
51
+ function formatTimestamp(iso) {
52
+ // Keep the ISO date-time for machine readability; callers format if needed.
53
+ return iso;
54
+ }
55
+ //# sourceMappingURL=reflect-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reflect-status.js","sourceRoot":"","sources":["../../../src/skills/reflect-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EACL,oBAAoB,EAEpB,+BAA+B,GAChC,MAAM,qCAAqC,CAAC;AAQ7C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kCAAkC,CACtD,OAA6B,EAAE;IAE/B,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,oBAAoB,CAAC,CAAC;IACjF,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,+BAA+B,CAAC;IAEpE,MAAM,WAAW,GAAG,MAAM,oBAAoB,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,KAAK,CAC9E,GAAG,EAAE,CAAC,EAAuB,CAC9B,CAAC;IAEF,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAE1C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IAC9C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;IACzF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,UAAU,aAAa,OAAO,GAAG,CAAC,CAAC;QACrE,KAAK,CAAC,IAAI,CAAC,oBAAoB,eAAe,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;QACpE,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QACjD,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,oBAAoB,CAAC,CAAkB;IAC9C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,CAAC,CAAC,cAAc,CAAC,WAAW,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IAC7F,IAAI,CAAC,CAAC,cAAc,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9E,IAAI,CAAC,CAAC,cAAc,CAAC,eAAe,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,cAAc,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;IACvG,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;IAClC,4EAA4E;IAC5E,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * `sw:skill-refine` CLI entry point.
3
+ *
4
+ * Orchestrates:
5
+ * 1. Flag parsing (--dry-run, --show-signals, --scope project|user)
6
+ * 2. Session-lock guard (ADR-0671-01 — never mutate during /sw:do or /sw:done)
7
+ * 3. Resolve skill file path based on scope
8
+ * 4. Aggregate refinement signals (aggregator.ts)
9
+ * 5. --show-signals: print + exit
10
+ * 6. Haiku diff proposal (haiku-diff.ts)
11
+ * 7. --dry-run: print diff + exit
12
+ * 8. Interactive approve/reject/edit (approval.ts)
13
+ * 9. On approve: write + git commit + ledger (apply.ts)
14
+ * On reject: ledger rejection entry only
15
+ *
16
+ * This module is exported as a library function `runSkillRefine` so it is
17
+ * testable in isolation. CLI wiring happens in `bin/specweave.js` separately.
18
+ *
19
+ * @module skills/skill-refine
20
+ */
21
+ import { type AggregateResult } from '../core/skill-refine/aggregator';
22
+ import { type HaikuClientLike } from '../core/skill-refine/haiku-diff';
23
+ import { type PromptFns } from '../core/skill-refine/approval';
24
+ export type Scope = 'project' | 'user';
25
+ export interface ParsedArgs {
26
+ skillSlug: string;
27
+ dryRun: boolean;
28
+ showSignals: boolean;
29
+ scope: Scope;
30
+ lastN?: number;
31
+ }
32
+ export interface RunOptions {
33
+ /** CWD used as the project root (for `scope=project` and signals/ledger paths). */
34
+ projectRoot: string;
35
+ /** Raw CLI argv (after the subcommand name). */
36
+ argv: string[];
37
+ /** Anthropic client for Haiku calls. Omit to skip network in tests. */
38
+ client?: HaikuClientLike;
39
+ /** Stream to write user-facing text to. Defaults to stdout. */
40
+ stdout?: {
41
+ write: (s: string) => void;
42
+ };
43
+ /** Prompt stubs for tests. Omit to use terminal prompts. */
44
+ prompts?: PromptFns;
45
+ /** Override env for session-lock detection (tests). */
46
+ env?: NodeJS.ProcessEnv;
47
+ }
48
+ export interface RunResult {
49
+ status: 'shown-signals' | 'dry-run' | 'applied' | 'rejected' | 'no-signals' | 'no-diff';
50
+ message: string;
51
+ commitSha?: string;
52
+ }
53
+ /**
54
+ * Parse `argv` into structured flags. Throws on invalid usage so the CLI
55
+ * can surface a single helpful error line.
56
+ */
57
+ export declare function parseArgs(argv: string[]): ParsedArgs;
58
+ /**
59
+ * Returns a human-readable reason string when the current process is inside
60
+ * an active /sw:do or /sw:done session (ADR-0671-01 red line). Null means
61
+ * safe to proceed.
62
+ */
63
+ export declare function detectSessionLock(projectRoot: string, env: NodeJS.ProcessEnv): string | null;
64
+ /**
65
+ * Resolve the SKILL.md path to refine. `project` scope targets
66
+ * `<projectRoot>/.claude/skills/<slugDir>/SKILL.md`; `user` scope targets
67
+ * `~/.claude/skills/<slugDir>/SKILL.md`. The slug's leading namespace
68
+ * (e.g. `sw:` → `sw-`) is mapped to a flat directory name, matching the
69
+ * existing flat-dir convention (see feedback_skill_naming_flat_dirs).
70
+ */
71
+ export declare function resolveSkillPath(slug: string, scope: Scope, projectRoot: string): string;
72
+ /**
73
+ * Main entry. Returns a structured result instead of throwing for known
74
+ * non-error outcomes (no signals, dry-run, rejected). Unknown errors propagate.
75
+ */
76
+ export declare function runSkillRefine(opts: RunOptions): Promise<RunResult>;
77
+ /**
78
+ * Pretty-print an aggregate for `--show-signals`. Deterministic output shape.
79
+ */
80
+ export declare function renderSignalReport(agg: AggregateResult): string;
81
+ //# sourceMappingURL=skill-refine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-refine.d.ts","sourceRoot":"","sources":["../../../src/skills/skill-refine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClF,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,+BAA+B,CAAC;AAIvC,MAAM,MAAM,KAAK,GAAG,SAAS,GAAG,MAAM,CAAC;AAEvC,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,mFAAmF;IACnF,WAAW,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,uEAAuE;IACvE,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,+DAA+D;IAC/D,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;IACxC,4DAA4D;IAC5D,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,uDAAuD;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,eAAe,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,CAAC;IACxF,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAiDpD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB,MAAM,GAAG,IAAI,CASf;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAIxF;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAyGzE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAmB/D"}
@@ -0,0 +1,226 @@
1
+ /**
2
+ * `sw:skill-refine` CLI entry point.
3
+ *
4
+ * Orchestrates:
5
+ * 1. Flag parsing (--dry-run, --show-signals, --scope project|user)
6
+ * 2. Session-lock guard (ADR-0671-01 — never mutate during /sw:do or /sw:done)
7
+ * 3. Resolve skill file path based on scope
8
+ * 4. Aggregate refinement signals (aggregator.ts)
9
+ * 5. --show-signals: print + exit
10
+ * 6. Haiku diff proposal (haiku-diff.ts)
11
+ * 7. --dry-run: print diff + exit
12
+ * 8. Interactive approve/reject/edit (approval.ts)
13
+ * 9. On approve: write + git commit + ledger (apply.ts)
14
+ * On reject: ledger rejection entry only
15
+ *
16
+ * This module is exported as a library function `runSkillRefine` so it is
17
+ * testable in isolation. CLI wiring happens in `bin/specweave.js` separately.
18
+ *
19
+ * @module skills/skill-refine
20
+ */
21
+ import { existsSync, promises as fs } from 'fs';
22
+ import { homedir } from 'os';
23
+ import { join } from 'path';
24
+ import { aggregate } from '../core/skill-refine/aggregator';
25
+ import { proposeDiff } from '../core/skill-refine/haiku-diff';
26
+ import { runApprovalFlow, defaultPromptFns, } from '../core/skill-refine/approval';
27
+ import { applyRefinement } from '../core/skill-refine/apply';
28
+ import { appendRejected } from '../core/skill-refine/ledger';
29
+ /**
30
+ * Parse `argv` into structured flags. Throws on invalid usage so the CLI
31
+ * can surface a single helpful error line.
32
+ */
33
+ export function parseArgs(argv) {
34
+ const flags = {
35
+ dryRun: false,
36
+ showSignals: false,
37
+ scope: 'project',
38
+ lastN: undefined,
39
+ };
40
+ const positionals = [];
41
+ for (let i = 0; i < argv.length; i++) {
42
+ const a = argv[i];
43
+ if (a === '--dry-run')
44
+ flags.dryRun = true;
45
+ else if (a === '--show-signals')
46
+ flags.showSignals = true;
47
+ else if (a === '--scope') {
48
+ const v = argv[++i];
49
+ if (v !== 'project' && v !== 'user') {
50
+ throw new Error(`--scope must be 'project' or 'user' (got: ${v ?? '<missing>'})`);
51
+ }
52
+ flags.scope = v;
53
+ }
54
+ else if (a === '--last-n') {
55
+ const v = argv[++i];
56
+ const n = Number(v);
57
+ if (!Number.isInteger(n) || n <= 0) {
58
+ throw new Error(`--last-n must be a positive integer (got: ${v ?? '<missing>'})`);
59
+ }
60
+ flags.lastN = n;
61
+ }
62
+ else if (a.startsWith('--')) {
63
+ throw new Error(`unknown flag: ${a}`);
64
+ }
65
+ else {
66
+ positionals.push(a);
67
+ }
68
+ }
69
+ if (positionals.length === 0) {
70
+ throw new Error('missing required argument: <skill-slug>');
71
+ }
72
+ if (positionals.length > 1) {
73
+ throw new Error(`sw:skill-refine accepts exactly one skill (got: ${positionals.join(', ')}) — refine one skill per invocation.`);
74
+ }
75
+ return {
76
+ skillSlug: positionals[0],
77
+ dryRun: flags.dryRun,
78
+ showSignals: flags.showSignals,
79
+ scope: flags.scope,
80
+ lastN: flags.lastN,
81
+ };
82
+ }
83
+ /**
84
+ * Returns a human-readable reason string when the current process is inside
85
+ * an active /sw:do or /sw:done session (ADR-0671-01 red line). Null means
86
+ * safe to proceed.
87
+ */
88
+ export function detectSessionLock(projectRoot, env) {
89
+ if (env.SPECWEAVE_SESSION_ACTIVE && env.SPECWEAVE_SESSION_ACTIVE !== '0') {
90
+ return `SPECWEAVE_SESSION_ACTIVE=${env.SPECWEAVE_SESSION_ACTIVE} — refinements are forbidden inside a /sw:do or /sw:done session (ADR-0671-01).`;
91
+ }
92
+ const lockPath = join(projectRoot, '.specweave/state/active-session.lock');
93
+ if (existsSync(lockPath)) {
94
+ return `active session lock present at ${lockPath} — refinements are forbidden inside a /sw:do or /sw:done session (ADR-0671-01).`;
95
+ }
96
+ return null;
97
+ }
98
+ /**
99
+ * Resolve the SKILL.md path to refine. `project` scope targets
100
+ * `<projectRoot>/.claude/skills/<slugDir>/SKILL.md`; `user` scope targets
101
+ * `~/.claude/skills/<slugDir>/SKILL.md`. The slug's leading namespace
102
+ * (e.g. `sw:` → `sw-`) is mapped to a flat directory name, matching the
103
+ * existing flat-dir convention (see feedback_skill_naming_flat_dirs).
104
+ */
105
+ export function resolveSkillPath(slug, scope, projectRoot) {
106
+ const dir = slug.replace(/:/g, '-');
107
+ const base = scope === 'user' ? join(homedir(), '.claude/skills') : join(projectRoot, '.claude/skills');
108
+ return join(base, dir, 'SKILL.md');
109
+ }
110
+ /**
111
+ * Main entry. Returns a structured result instead of throwing for known
112
+ * non-error outcomes (no signals, dry-run, rejected). Unknown errors propagate.
113
+ */
114
+ export async function runSkillRefine(opts) {
115
+ const out = opts.stdout ?? process.stdout;
116
+ const env = opts.env ?? process.env;
117
+ const args = parseArgs(opts.argv);
118
+ // ── Session-lock guard (ADR-0671-01) ───────────────────────────────
119
+ const lockReason = detectSessionLock(opts.projectRoot, env);
120
+ if (lockReason) {
121
+ out.write(`sw:skill-refine: refusing to run — ${lockReason}\n`);
122
+ return { status: 'rejected', message: lockReason };
123
+ }
124
+ // ── Resolve SKILL.md path ──────────────────────────────────────────
125
+ const skillPath = resolveSkillPath(args.skillSlug, args.scope, opts.projectRoot);
126
+ if (!existsSync(skillPath)) {
127
+ const msg = `SKILL.md not found at ${skillPath} (scope=${args.scope}). Nothing to refine.`;
128
+ out.write(msg + '\n');
129
+ return { status: 'no-diff', message: msg };
130
+ }
131
+ // ── Aggregate signals ──────────────────────────────────────────────
132
+ const signalsPath = join(opts.projectRoot, '.specweave/state/skill-signals.json');
133
+ const agg = await aggregate(signalsPath, args.skillSlug, {
134
+ lastNIncrements: args.lastN,
135
+ });
136
+ // --show-signals short-circuits before any LLM call.
137
+ if (args.showSignals) {
138
+ out.write(renderSignalReport(agg) + '\n');
139
+ return { status: 'shown-signals', message: `rendered ${agg.totalSignals} signals` };
140
+ }
141
+ if (agg.totalSignals === 0) {
142
+ const msg = `No refinement signals found for ${args.skillSlug} in the last ${agg.window.lastNIncrements} increments.`;
143
+ out.write(msg + '\n');
144
+ return { status: 'no-signals', message: msg };
145
+ }
146
+ // ── Haiku diff proposal ────────────────────────────────────────────
147
+ if (!opts.client) {
148
+ throw new Error('sw:skill-refine requires an Anthropic client. Set ANTHROPIC_API_KEY and retry.');
149
+ }
150
+ const skillMd = await fs.readFile(skillPath, 'utf-8');
151
+ const proposal = await proposeDiff({
152
+ client: opts.client,
153
+ skillMd,
154
+ aggregate: agg,
155
+ });
156
+ if (!proposal.diff.trim()) {
157
+ const msg = `Haiku: ${proposal.rationale} (empty diff — nothing to apply).`;
158
+ out.write(msg + '\n');
159
+ return { status: 'no-diff', message: msg };
160
+ }
161
+ // --dry-run short-circuits before approval/writes.
162
+ if (args.dryRun) {
163
+ out.write(`Rationale: ${proposal.rationale}\n`);
164
+ out.write(proposal.diff + '\n');
165
+ return { status: 'dry-run', message: 'diff printed; no writes performed.' };
166
+ }
167
+ // ── Interactive approval ───────────────────────────────────────────
168
+ const prompts = opts.prompts ?? (await defaultPromptFns());
169
+ const decision = await runApprovalFlow({
170
+ targetSkill: args.skillSlug,
171
+ rationale: proposal.rationale,
172
+ diff: proposal.diff,
173
+ }, prompts);
174
+ const ledgerPath = join(opts.projectRoot, '.specweave/state/skill-refinements.json');
175
+ const signalIds = agg.signals.map((s) => s.id);
176
+ if (decision.action === 'reject') {
177
+ await appendRejected(ledgerPath, {
178
+ targetSkill: args.skillSlug,
179
+ author: 'user',
180
+ signalIds,
181
+ rationale: proposal.rationale,
182
+ rejectionReason: decision.reason,
183
+ });
184
+ const msg = `Rejected: ${decision.reason}`;
185
+ out.write(msg + '\n');
186
+ return { status: 'rejected', message: msg };
187
+ }
188
+ // ── Apply + commit + ledger ────────────────────────────────────────
189
+ const result = await applyRefinement({
190
+ skillPath,
191
+ diff: decision.diff,
192
+ rationale: proposal.rationale,
193
+ signalIds,
194
+ targetSkill: args.skillSlug,
195
+ ledgerPath,
196
+ repoRoot: opts.projectRoot,
197
+ });
198
+ const msg = `Applied: ${result.commitSha} — ${proposal.rationale}`;
199
+ out.write(msg + '\n');
200
+ return { status: 'applied', message: msg, commitSha: result.commitSha };
201
+ }
202
+ /**
203
+ * Pretty-print an aggregate for `--show-signals`. Deterministic output shape.
204
+ */
205
+ export function renderSignalReport(agg) {
206
+ const lines = [
207
+ `## sw:skill-refine — signals for ${agg.targetSkill}`,
208
+ `Window: last ${agg.window.lastNIncrements} increments`,
209
+ `Total: ${agg.totalSignals}`,
210
+ `By source: judge-llm=${agg.bySource['judge-llm']} rubric=${agg.bySource.rubric} code-reviewer=${agg.bySource['code-reviewer']}`,
211
+ `By severity: high=${agg.bySeverity.high} medium=${agg.bySeverity.medium} low=${agg.bySeverity.low}`,
212
+ `Increments: ${agg.incrementIds.join(', ') || '(none)'}`,
213
+ '',
214
+ 'Evidence:',
215
+ ];
216
+ if (agg.signals.length === 0) {
217
+ lines.push(' (none)');
218
+ }
219
+ else {
220
+ for (const s of agg.signals) {
221
+ lines.push(` - [${s.severity}/${s.source}/${s.incrementId}] ${s.evidence}`);
222
+ }
223
+ }
224
+ return lines.join('\n');
225
+ }
226
+ //# sourceMappingURL=skill-refine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-refine.js","sourceRoot":"","sources":["../../../src/skills/skill-refine.ts"],"names":[],"mappings":"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"}
@@ -58,22 +58,32 @@ export declare class SyncCoordinator {
58
58
  * Close JIRA issues for completed user stories
59
59
  *
60
60
  * Transitions JIRA issues to "Done" status when increment is completed.
61
- * Reads issue references from user story frontmatter (external.jira.issue_key).
61
+ * Reads issue references from four fallback sources (0696 hotfix):
62
+ * 1. per-US frontmatter `external_tools.jira.key`
63
+ * 2. per-US `external_id`
64
+ * 3. `metadata.jira.issue` (legacy)
65
+ * 4. `metadata.externalLinks.jira.epicKey` (current standard)
62
66
  *
63
67
  * @param config - Project config with JIRA settings
68
+ * @param errorsOut - Optional sink for per-issue error messages (0696)
64
69
  * @returns Number of closed JIRA issues
65
70
  */
66
- closeJiraIssuesForUserStories(config: SpecWeaveConfig): Promise<number>;
71
+ closeJiraIssuesForUserStories(config: SpecWeaveConfig, errorsOut?: string[]): Promise<number>;
67
72
  /**
68
73
  * Close ADO work items for completed user stories
69
74
  *
70
75
  * Transitions ADO work items to "Closed" state when increment is completed.
71
- * Reads work item references from user story frontmatter (external.ado.id).
76
+ * Reads work item references from four fallback sources (0696 hotfix):
77
+ * 1. per-US frontmatter `external_tools.ado.id`
78
+ * 2. per-US `external_id`
79
+ * 3. `metadata.external_tools.ado.id` / `metadata.ado.work_item_id` (legacy)
80
+ * 4. `metadata.externalLinks.ado.workItemId` / `.featureId` (current standard)
72
81
  *
73
82
  * @param config - Project config with ADO settings
83
+ * @param errorsOut - Optional sink for per-item error messages (0696)
74
84
  * @returns Number of closed ADO work items
75
85
  */
76
- closeAdoWorkItemsForUserStories(config: SpecWeaveConfig): Promise<number>;
86
+ closeAdoWorkItemsForUserStories(config: SpecWeaveConfig, errorsOut?: string[]): Promise<number>;
77
87
  /**
78
88
  * Sync increment closure to external tools (NEW in v0.28.1)
79
89
  *
@@ -1 +1 @@
1
- {"version":3,"file":"sync-coordinator.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-coordinator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,EAAE,MAAM,EAAiB,MAAM,oBAAoB,CAAC;AAI3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAG/E,OAAO,EAAE,cAAc,EAAwB,MAAM,sBAAsB,CAAC;AAE5E,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,yBAAyB,CAAC;AAcjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAWvD,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,UAAU,CAAC,EAAE,kBAAkB,CAAC;CACjC;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,cAAc,GAAG,WAAW,GAAG,WAAW,GAAG,aAAa,GAAG,kBAAkB,GAAG,mBAAmB,CAAC;IAChH,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAC,CAAqB;IACxC,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,cAAc,CAAiB;gBAE3B,OAAO,EAAE,sBAAsB;IAkB3C;;;;;OAKG;IACH,iBAAiB,IAAI,UAAU,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;IAI7D;;OAEG;IACH,0BAA0B,IAAI,MAAM;IAKpC;;OAEG;IACG,gCAAgC,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAKhF;;OAEG;IACG,+BAA+B,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAKlF;;;;;;;;OAQG;IACG,6BAA6B,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAoG7E;;;;;;;;OAQG;IACG,+BAA+B,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAoI/E;;;;;;;;;;;;OAYG;IACG,oBAAoB,IAAI,OAAO,CAAC,UAAU,GAAG;QAAE,YAAY,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IA2J9E;;OAEG;IACG,uBAAuB,IAAI,OAAO,CAAC,UAAU,CAAC;IAuHpD;;OAEG;YACW,aAAa;IA2N3B;;OAEG;YACW,kBAAkB;IAoEhC;;OAEG;YACW,2BAA2B;IAyGzC;;;;OAIG;IACH,OAAO,CAAC,wBAAwB;IA0BhC;;OAEG;YACW,UAAU;IAWxB;;;OAGG;YACW,gBAAgB;IAI9B;;OAEG;IACH,OAAO,CAAC,0BAA0B;IA0ClC;;;;;;OAMG;IACH,OAAO,CAAC,2BAA2B;CA4CpC"}
1
+ {"version":3,"file":"sync-coordinator.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-coordinator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,EAAE,MAAM,EAAiB,MAAM,oBAAoB,CAAC;AAI3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAG/E,OAAO,EAAE,cAAc,EAAwB,MAAM,sBAAsB,CAAC;AAE5E,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,yBAAyB,CAAC;AAcjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAWvD,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,UAAU,CAAC,EAAE,kBAAkB,CAAC;CACjC;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,cAAc,GAAG,WAAW,GAAG,WAAW,GAAG,aAAa,GAAG,kBAAkB,GAAG,mBAAmB,CAAC;IAChH,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAC,CAAqB;IACxC,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,cAAc,CAAiB;gBAE3B,OAAO,EAAE,sBAAsB;IAkB3C;;;;;OAKG;IACH,iBAAiB,IAAI,UAAU,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;IAI7D;;OAEG;IACH,0BAA0B,IAAI,MAAM;IAKpC;;OAEG;IACG,gCAAgC,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAKhF;;OAEG;IACG,+BAA+B,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAKlF;;;;;;;;;;;;;OAaG;IACG,6BAA6B,CAAC,MAAM,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IA0HnG;;;;;;;;;;;;;OAaG;IACG,+BAA+B,CAAC,MAAM,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAoJrG;;;;;;;;;;;;OAYG;IACG,oBAAoB,IAAI,OAAO,CAAC,UAAU,GAAG;QAAE,YAAY,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IA6J9E;;OAEG;IACG,uBAAuB,IAAI,OAAO,CAAC,UAAU,CAAC;IAuHpD;;OAEG;YACW,aAAa;IA2N3B;;OAEG;YACW,kBAAkB;IAoEhC;;OAEG;YACW,2BAA2B;IAyGzC;;;;OAIG;IACH,OAAO,CAAC,wBAAwB;IA0BhC;;OAEG;YACW,UAAU;IAWxB;;;OAGG;YACW,gBAAgB;IAI9B;;OAEG;IACH,OAAO,CAAC,0BAA0B;IA0ClC;;;;;;OAMG;IACH,OAAO,CAAC,2BAA2B;CA4CpC"}