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,200 @@
1
+ /**
2
+ * Skill Signals v2 — discriminated-union schema for .specweave/state/skill-signals.json
3
+ *
4
+ * v1 (legacy) was a generation-only store produced by SignalCollector
5
+ * (see src/core/skill-gen/types.ts). v2 adds refinement signals emitted by
6
+ * closure gates (judge-llm, rubric, code-reviewer) and keeps generation
7
+ * signals bit-identical except for an added `type: "generation"` discriminator.
8
+ *
9
+ * Migration is lazy: the reader detects a v1 file and returns a v2 view in
10
+ * memory; the next writer call persists v2 to disk.
11
+ *
12
+ * @module types/skill-signals
13
+ */
14
+ import { z } from 'zod';
15
+ export type SignalSource = 'judge-llm' | 'rubric' | 'code-reviewer';
16
+ export type SignalSeverity = 'low' | 'medium' | 'high';
17
+ export declare const SIGNAL_SOURCES: readonly SignalSource[];
18
+ export declare const SIGNAL_SEVERITIES: readonly SignalSeverity[];
19
+ /**
20
+ * Legacy generation signal produced by SignalCollector. All v1 fields are
21
+ * preserved; `type: "generation"` is added during migration.
22
+ */
23
+ export interface GenerationSignal {
24
+ type: 'generation';
25
+ id: string;
26
+ pattern: string;
27
+ category: string;
28
+ description: string;
29
+ incrementIds: string[];
30
+ firstSeen: string;
31
+ lastSeen: string;
32
+ confidence: number;
33
+ evidence: string[];
34
+ suggested: boolean;
35
+ declined: boolean;
36
+ generated: boolean;
37
+ uniqueSourceFiles?: string[];
38
+ }
39
+ export declare const GenerationSignalSchema: z.ZodObject<{
40
+ type: z.ZodLiteral<"generation">;
41
+ id: z.ZodString;
42
+ pattern: z.ZodString;
43
+ category: z.ZodString;
44
+ description: z.ZodString;
45
+ incrementIds: z.ZodArray<z.ZodString>;
46
+ firstSeen: z.ZodString;
47
+ lastSeen: z.ZodString;
48
+ confidence: z.ZodNumber;
49
+ evidence: z.ZodArray<z.ZodString>;
50
+ suggested: z.ZodBoolean;
51
+ declined: z.ZodBoolean;
52
+ generated: z.ZodBoolean;
53
+ uniqueSourceFiles: z.ZodOptional<z.ZodArray<z.ZodString>>;
54
+ }, z.core.$strip>;
55
+ /**
56
+ * Refinement signal emitted by a closure gate when a gate failure traces
57
+ * to a specific skill's instructions.
58
+ */
59
+ export interface RefinementSignal {
60
+ type: 'refinement';
61
+ id: string;
62
+ source: SignalSource;
63
+ targetSkill: string;
64
+ severity: SignalSeverity;
65
+ incrementId: string;
66
+ evidence: string;
67
+ detectedAt: string;
68
+ consumedBy: string | null;
69
+ }
70
+ export declare const RefinementSignalSchema: z.ZodObject<{
71
+ type: z.ZodLiteral<"refinement">;
72
+ id: z.ZodString;
73
+ source: z.ZodEnum<{
74
+ "judge-llm": "judge-llm";
75
+ rubric: "rubric";
76
+ "code-reviewer": "code-reviewer";
77
+ }>;
78
+ targetSkill: z.ZodString;
79
+ severity: z.ZodEnum<{
80
+ low: "low";
81
+ medium: "medium";
82
+ high: "high";
83
+ }>;
84
+ incrementId: z.ZodString;
85
+ evidence: z.ZodString;
86
+ detectedAt: z.ZodString;
87
+ consumedBy: z.ZodNullable<z.ZodString>;
88
+ }, z.core.$strip>;
89
+ export type SkillSignal = GenerationSignal | RefinementSignal;
90
+ export declare const SkillSignalSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
91
+ type: z.ZodLiteral<"generation">;
92
+ id: z.ZodString;
93
+ pattern: z.ZodString;
94
+ category: z.ZodString;
95
+ description: z.ZodString;
96
+ incrementIds: z.ZodArray<z.ZodString>;
97
+ firstSeen: z.ZodString;
98
+ lastSeen: z.ZodString;
99
+ confidence: z.ZodNumber;
100
+ evidence: z.ZodArray<z.ZodString>;
101
+ suggested: z.ZodBoolean;
102
+ declined: z.ZodBoolean;
103
+ generated: z.ZodBoolean;
104
+ uniqueSourceFiles: z.ZodOptional<z.ZodArray<z.ZodString>>;
105
+ }, z.core.$strip>, z.ZodObject<{
106
+ type: z.ZodLiteral<"refinement">;
107
+ id: z.ZodString;
108
+ source: z.ZodEnum<{
109
+ "judge-llm": "judge-llm";
110
+ rubric: "rubric";
111
+ "code-reviewer": "code-reviewer";
112
+ }>;
113
+ targetSkill: z.ZodString;
114
+ severity: z.ZodEnum<{
115
+ low: "low";
116
+ medium: "medium";
117
+ high: "high";
118
+ }>;
119
+ incrementId: z.ZodString;
120
+ evidence: z.ZodString;
121
+ detectedAt: z.ZodString;
122
+ consumedBy: z.ZodNullable<z.ZodString>;
123
+ }, z.core.$strip>], "type">;
124
+ /**
125
+ * v2 on-disk envelope for `.specweave/state/skill-signals.json`.
126
+ */
127
+ export interface SignalFile {
128
+ schemaVersion: 2;
129
+ signals: SkillSignal[];
130
+ }
131
+ export declare const SignalFileSchema: z.ZodObject<{
132
+ schemaVersion: z.ZodLiteral<2>;
133
+ signals: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
134
+ type: z.ZodLiteral<"generation">;
135
+ id: z.ZodString;
136
+ pattern: z.ZodString;
137
+ category: z.ZodString;
138
+ description: z.ZodString;
139
+ incrementIds: z.ZodArray<z.ZodString>;
140
+ firstSeen: z.ZodString;
141
+ lastSeen: z.ZodString;
142
+ confidence: z.ZodNumber;
143
+ evidence: z.ZodArray<z.ZodString>;
144
+ suggested: z.ZodBoolean;
145
+ declined: z.ZodBoolean;
146
+ generated: z.ZodBoolean;
147
+ uniqueSourceFiles: z.ZodOptional<z.ZodArray<z.ZodString>>;
148
+ }, z.core.$strip>, z.ZodObject<{
149
+ type: z.ZodLiteral<"refinement">;
150
+ id: z.ZodString;
151
+ source: z.ZodEnum<{
152
+ "judge-llm": "judge-llm";
153
+ rubric: "rubric";
154
+ "code-reviewer": "code-reviewer";
155
+ }>;
156
+ targetSkill: z.ZodString;
157
+ severity: z.ZodEnum<{
158
+ low: "low";
159
+ medium: "medium";
160
+ high: "high";
161
+ }>;
162
+ incrementId: z.ZodString;
163
+ evidence: z.ZodString;
164
+ detectedAt: z.ZodString;
165
+ consumedBy: z.ZodNullable<z.ZodString>;
166
+ }, z.core.$strip>], "type">>;
167
+ }, z.core.$strip>;
168
+ export declare const EMPTY_SIGNAL_FILE: SignalFile;
169
+ interface V1SignalEntry {
170
+ id: string;
171
+ pattern: string;
172
+ category: string;
173
+ description: string;
174
+ incrementIds: string[];
175
+ firstSeen: string;
176
+ lastSeen: string;
177
+ confidence: number;
178
+ evidence: string[];
179
+ suggested: boolean;
180
+ declined: boolean;
181
+ generated: boolean;
182
+ uniqueSourceFiles?: string[];
183
+ }
184
+ interface V1SignalStore {
185
+ version: string;
186
+ signals: V1SignalEntry[];
187
+ }
188
+ /**
189
+ * Returns true when `raw` conforms to the v1 on-disk shape.
190
+ * v1 is identified by a string `version` field (e.g. "1.0") and absent
191
+ * `schemaVersion`. v2 uses a numeric `schemaVersion: 2`.
192
+ */
193
+ export declare function isV1(raw: unknown): raw is V1SignalStore;
194
+ /**
195
+ * Migrate a v1 store to v2 without data loss. Adds `type: "generation"`
196
+ * to every existing entry; all other fields are preserved verbatim.
197
+ */
198
+ export declare function migrateV1toV2(v1: V1SignalStore): SignalFile;
199
+ export {};
200
+ //# sourceMappingURL=skill-signals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-signals.d.ts","sourceRoot":"","sources":["../../../src/types/skill-signals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,QAAQ,GAAG,eAAe,CAAC;AACpE,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEvD,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EAIjD,CAAC;AACF,eAAO,MAAM,iBAAiB,EAAE,SAAS,cAAc,EAA8B,CAAC;AAItF;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,YAAY,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;iBAejC,CAAC;AAIH;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,YAAY,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,YAAY,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,cAAc,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;iBAUjC,CAAC;AAIH,MAAM,MAAM,WAAW,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;AAE9D,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAG5B,CAAC;AAEH;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,CAAC,CAAC;IACjB,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAG3B,CAAC;AAEH,eAAO,MAAM,iBAAiB,EAAE,UAG/B,CAAC;AAIF,UAAU,aAAa;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,UAAU,aAAa;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAyBD;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,aAAa,CAEvD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,aAAa,GAAG,UAAU,CAsB3D"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Skill Signals v2 — discriminated-union schema for .specweave/state/skill-signals.json
3
+ *
4
+ * v1 (legacy) was a generation-only store produced by SignalCollector
5
+ * (see src/core/skill-gen/types.ts). v2 adds refinement signals emitted by
6
+ * closure gates (judge-llm, rubric, code-reviewer) and keeps generation
7
+ * signals bit-identical except for an added `type: "generation"` discriminator.
8
+ *
9
+ * Migration is lazy: the reader detects a v1 file and returns a v2 view in
10
+ * memory; the next writer call persists v2 to disk.
11
+ *
12
+ * @module types/skill-signals
13
+ */
14
+ import { z } from 'zod';
15
+ export const SIGNAL_SOURCES = [
16
+ 'judge-llm',
17
+ 'rubric',
18
+ 'code-reviewer',
19
+ ];
20
+ export const SIGNAL_SEVERITIES = ['low', 'medium', 'high'];
21
+ export const GenerationSignalSchema = z.object({
22
+ type: z.literal('generation'),
23
+ id: z.string(),
24
+ pattern: z.string(),
25
+ category: z.string(),
26
+ description: z.string(),
27
+ incrementIds: z.array(z.string()),
28
+ firstSeen: z.string(),
29
+ lastSeen: z.string(),
30
+ confidence: z.number(),
31
+ evidence: z.array(z.string()),
32
+ suggested: z.boolean(),
33
+ declined: z.boolean(),
34
+ generated: z.boolean(),
35
+ uniqueSourceFiles: z.array(z.string()).optional(),
36
+ });
37
+ export const RefinementSignalSchema = z.object({
38
+ type: z.literal('refinement'),
39
+ id: z.string(),
40
+ source: z.enum(['judge-llm', 'rubric', 'code-reviewer']),
41
+ targetSkill: z.string(),
42
+ severity: z.enum(['low', 'medium', 'high']),
43
+ incrementId: z.string(),
44
+ evidence: z.string(),
45
+ detectedAt: z.string(),
46
+ consumedBy: z.string().nullable(),
47
+ });
48
+ export const SkillSignalSchema = z.discriminatedUnion('type', [
49
+ GenerationSignalSchema,
50
+ RefinementSignalSchema,
51
+ ]);
52
+ export const SignalFileSchema = z.object({
53
+ schemaVersion: z.literal(2),
54
+ signals: z.array(SkillSignalSchema),
55
+ });
56
+ export const EMPTY_SIGNAL_FILE = {
57
+ schemaVersion: 2,
58
+ signals: [],
59
+ };
60
+ const V1SignalEntrySchema = z.object({
61
+ id: z.string(),
62
+ pattern: z.string(),
63
+ category: z.string(),
64
+ description: z.string(),
65
+ incrementIds: z.array(z.string()),
66
+ firstSeen: z.string(),
67
+ lastSeen: z.string(),
68
+ confidence: z.number(),
69
+ evidence: z.array(z.string()),
70
+ suggested: z.boolean(),
71
+ declined: z.boolean(),
72
+ generated: z.boolean(),
73
+ uniqueSourceFiles: z.array(z.string()).optional(),
74
+ });
75
+ const V1SignalStoreSchema = z.object({
76
+ version: z.string(),
77
+ signals: z.array(V1SignalEntrySchema),
78
+ });
79
+ // ── Migration ────────────────────────────────────────────────────────
80
+ /**
81
+ * Returns true when `raw` conforms to the v1 on-disk shape.
82
+ * v1 is identified by a string `version` field (e.g. "1.0") and absent
83
+ * `schemaVersion`. v2 uses a numeric `schemaVersion: 2`.
84
+ */
85
+ export function isV1(raw) {
86
+ return V1SignalStoreSchema.safeParse(raw).success;
87
+ }
88
+ /**
89
+ * Migrate a v1 store to v2 without data loss. Adds `type: "generation"`
90
+ * to every existing entry; all other fields are preserved verbatim.
91
+ */
92
+ export function migrateV1toV2(v1) {
93
+ return {
94
+ schemaVersion: 2,
95
+ signals: v1.signals.map((entry) => ({
96
+ type: 'generation',
97
+ id: entry.id,
98
+ pattern: entry.pattern,
99
+ category: entry.category,
100
+ description: entry.description,
101
+ incrementIds: [...entry.incrementIds],
102
+ firstSeen: entry.firstSeen,
103
+ lastSeen: entry.lastSeen,
104
+ confidence: entry.confidence,
105
+ evidence: [...entry.evidence],
106
+ suggested: entry.suggested,
107
+ declined: entry.declined,
108
+ generated: entry.generated,
109
+ ...(entry.uniqueSourceFiles !== undefined
110
+ ? { uniqueSourceFiles: [...entry.uniqueSourceFiles] }
111
+ : {}),
112
+ })),
113
+ };
114
+ }
115
+ //# sourceMappingURL=skill-signals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-signals.js","sourceRoot":"","sources":["../../../src/types/skill-signals.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specweave",
3
- "version": "1.0.579",
3
+ "version": "1.0.581",
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.88.0",
94
+ "@anthropic-ai/sdk": "^0.90.0",
95
95
  "@inquirer/prompts": "^8.1.0",
96
96
  "@octokit/rest": "^22.0.1",
97
97
  "@types/handlebars": "^4.0.40",
@@ -133,8 +133,17 @@ RECENT LEARNINGS
133
133
  - [devops] LSP requires ENABLE_LSP_TOOL=1 env var
134
134
  - [frontend] Use shadcn/ui Button component
135
135
  - [backend] Return 404 for missing resources
136
+
137
+ ## Skill Refinement Suggestions
138
+ Skill Signals (J/R/C) Severity Last seen Command
139
+ sw:architect 5 (3/1/1) high 2026-04-19 18:22 sw:skill-refine sw:architect
140
+ sw:pm 3 (2/1/0) medium 2026-04-18 09:07 sw:skill-refine sw:pm
136
141
  ```
137
142
 
143
+ Introduced in **increment 0671 — skill refinement loop**. Skills with ≥3 negative signals in `.specweave/state/skill-signals.json` (`type: "refinement"`) are ranked by severity × recency. Entries with `<3` signals are omitted from the list; the whole section is omitted when no skills qualify.
144
+
145
+ Signal sources (J/R/C = judge-llm / rubric / code-reviewer) come from closure gates. See [`sw:skill-refine`](./skill-refine.md) for flags, attribution heuristics, and the four red-line ADRs.
146
+
138
147
  ### `--clear` - Remove Learnings
139
148
 
140
149
  Remove specific learnings from CLAUDE.md Skill Memories section.
@@ -149,6 +158,44 @@ sw:reflect --clear --all # Clear ALL learnings (requires confirmati
149
158
  2. Show confirmation with what will be deleted
150
159
  3. Edit CLAUDE.md to remove matching learnings on confirmation
151
160
 
161
+ ## Session-end Nudge
162
+
163
+ Added in increment 0671. When `/sw:done` closes an increment, the reflect stop-hook checks whether the session accumulated either:
164
+
165
+ - ≥1 high-confidence learning (eligible for CLAUDE.md persistence), or
166
+ - ≥1 refinement signal in `.specweave/state/skill-signals.json` attributed to an existing skill.
167
+
168
+ If so, a **single-line** prompt is printed at closure time:
169
+
170
+ ```
171
+ Detected: 2 signals for sw:architect — run sw:skill-refine sw:architect? (y/N)
172
+ ```
173
+
174
+ or, for a learning nudge:
175
+
176
+ ```
177
+ Detected: 1 high-confidence learning — run sw:reflect? (y/N)
178
+ ```
179
+
180
+ **The nudge never auto-executes a command.** The user must explicitly run the suggested command. Declining (N or no input within 5s) logs no penalty; signals remain in `skill-signals.json` for later invocation.
181
+
182
+ Performance: the nudge check adds <100ms to `/sw:done` close time.
183
+
184
+ ### Disabling the nudge
185
+
186
+ Set `reflect.autoNudge: false` in `.specweave/config.json`:
187
+
188
+ ```json
189
+ {
190
+ "reflect": {
191
+ "enabled": true,
192
+ "autoNudge": false
193
+ }
194
+ }
195
+ ```
196
+
197
+ When `autoNudge` is false, no nudge is printed at close; `sw:reflect` and `sw:skill-refine` remain manually invocable.
198
+
152
199
  ## Configuration
153
200
 
154
201
  In `.specweave/config.json`:
@@ -168,6 +215,7 @@ In `.specweave/config.json`:
168
215
  | `enabled` | `true` | Master switch for reflection |
169
216
  | `model` | `"haiku"` | LLM model for extraction |
170
217
  | `maxLearningsPerSession` | `3` | Limit per session |
218
+ | `autoNudge` | `true` | Session-end nudge when learnings or refinement signals are detected (0671) |
171
219
 
172
220
  ## Skill Categories
173
221
 
@@ -511,6 +511,10 @@ Write structured JSON with all findings, metadata, and reviewer statuses.
511
511
 
512
512
  The `summary` object reflects post-validation counts. The completion-validator only reads `summary.*` fields -- all new fields are additive and backward-compatible.
513
513
 
514
+ ### Refinement Signal Emission (0671)
515
+
516
+ When the completion-validator parses `code-review-report.json`, it iterates `findings[]` and, for each CRITICAL or HIGH finding whose evidence references a specific skill slug (e.g. `sw:architect`) or matches a ≥6-word phrase from a `SKILL.md` under `plugins/specweave/skills/`, appends a refinement signal to `.specweave/state/skill-signals.json` (best-effort, never blocks closure). Source is `"code-reviewer"` and severity is always `"high"`. Reviewers do not need to do anything extra — include the offending skill slug or the SKILL.md-quoted instruction in the finding's `description`/`recommendation` and attribution is automatic. Signals are consumed later by `sw:skill-refine`.
517
+
514
518
  ---
515
519
 
516
520
  ## 5. Cross-Repo Mode
@@ -215,6 +215,10 @@ After evaluation (including consent-denied fallback), you **MUST** write a JSON
215
215
 
216
216
  A `WAIVED` verdict is accepted by the CLI — does not block closure.
217
217
 
218
+ ## Refinement Signal Emission (0671)
219
+
220
+ When the verdict is `REJECTED` or `CONCERNS` and a finding references a specific skill slug (e.g. `sw:architect` in `concerns`, `recommendations`, or `summary`), `SkillJudge.writeReport` appends a refinement signal to `.specweave/state/skill-signals.json` (best-effort, never blocks the gate). `REJECTED` → severity `high`; `CONCERNS` → `medium`. Signals are consumed later by `sw:skill-refine`.
221
+
218
222
  ## Visibility & Stuck Detection
219
223
 
220
224
  Progress logged to `.specweave/logs/judge-llm.log`. Default timeout 60s aborts if stuck (`timedOut: true`).
@@ -7,6 +7,14 @@ model: opus
7
7
 
8
8
  # sw:skill-gen — Project-Specific Skill Generation
9
9
 
10
+ ## Model Selection
11
+
12
+ This skill does not call an LLM directly — it delegates to Anthropic's `skill-creator` plugin, which runs inside the current Claude Code session and inherits its model. Skill generation is a structured-output task where description wording drives auto-activation for every future invocation, so quality matters more than cost.
13
+
14
+ - **Default (recommended)**: run the session on the newest Opus. If you are in Claude Code, switch with `/model opus` before starting. The frontmatter above declares `model: opus` so nested invocations prefer it when supported. "Newest Opus" is forward-compatible: today that is Opus 4.7, and the recommendation follows whichever Opus is current.
15
+ - **BYO path (GPT-5, Gemini 3, OpenRouter, LM Studio, Ollama)**: start `npx anymodel proxy --model <model> --port <port>` in a separate shell, then `export ANTHROPIC_BASE_URL=http://localhost:<port>` before launching Claude Code. This only affects downstream tools that honor `ANTHROPIC_BASE_URL` — Claude Code's own chat model is controlled via `/model`.
16
+ - **Rationale & registry**: see ADR `0676-01-skill-gen-model-selection.md`. The authoritative model registry lives in `vskill-platform` (`src/lib/eval/model-registry.ts`); update it there when a newer Opus ships.
17
+
10
18
  ## Project Overrides
11
19
 
12
20
  **Skill Memories**: If `.specweave/skill-memories/skill-gen.md` exists, read and apply its learnings.
@@ -0,0 +1,96 @@
1
+ ---
2
+ description: "Refine an existing skill's SKILL.md against accumulated gate-failure signals. Use when saying 'sw:skill-refine', 'refine skill', 'improve skill', 'skill refinement', or responding to a session-end nudge suggesting refinement. One skill per invocation; user approval required; never runs during an active /sw:do or /sw:done session (ADR-0671-01)."
3
+ argument-hint: "<skill-slug> [--dry-run] [--show-signals] [--scope project|user] [--last-n N]"
4
+ allowed-tools: Read, Bash
5
+ context: fork
6
+ model: opus
7
+ ---
8
+
9
+ # sw:skill-refine — Targeted Skill Refinement Loop
10
+
11
+ Propose and apply minimal, auditable edits to an existing `SKILL.md` using evidence collected by the closure gates (`sw:judge-llm`, `rubric`, `sw:code-reviewer`).
12
+
13
+ **Inputs:** `<skill-slug>` (e.g. `sw:architect`) + refinement signals under `.specweave/state/skill-signals.json`.
14
+ **Output:** a reviewed git commit on the local branch (never pushed) plus a ledger entry at `.specweave/state/skill-refinements.json`.
15
+
16
+ ## Red lines (inherited from ADR-0671-01..04)
17
+
18
+ 1. **No runtime mutation.** This skill refuses to run when `SPECWEAVE_SESSION_ACTIVE` is set or `.specweave/state/active-session.lock` exists. Refinements happen *between* sessions, as an explicit human action.
19
+ 2. **No auto-apply.** Every diff requires explicit approve / reject / edit from the human at the terminal. There is no `--yes` flag and none will be added.
20
+ 3. **One skill per invocation.** `sw:skill-refine sw:a sw:b` is a usage error. Refinements must stay scoped.
21
+ 4. **Never pushes.** `git commit` only — reviewing the commit and pushing stays with the user.
22
+
23
+ ## Usage
24
+
25
+ ```bash
26
+ # Inspect signals without proposing a diff (no LLM call)
27
+ sw:skill-refine sw:architect --show-signals
28
+
29
+ # Propose a diff, print it, do not write anything
30
+ sw:skill-refine sw:architect --dry-run
31
+
32
+ # Full interactive flow: aggregate → Haiku diff → approve/reject/edit → commit + ledger
33
+ sw:skill-refine sw:architect
34
+
35
+ # Refine a user-scoped skill at ~/.claude/skills/<dir>/SKILL.md
36
+ sw:skill-refine my-skill --scope user
37
+
38
+ # Override default N=5 increment window
39
+ sw:skill-refine sw:architect --last-n 3
40
+ ```
41
+
42
+ ## Workflow
43
+
44
+ 1. **Parse flags** — `<skill-slug>` (required), `--dry-run`, `--show-signals`, `--scope project|user`, `--last-n N`. Exactly one skill per invocation.
45
+ 2. **Session-lock guard** — refuse if in an active `/sw:do` or `/sw:done` session. See ADR-0671-01.
46
+ 3. **Resolve SKILL.md path** — `project` ⇒ `.claude/skills/<slug-dir>/SKILL.md`; `user` ⇒ `~/.claude/skills/<slug-dir>/SKILL.md`. Slug `sw:foo` maps to directory `sw-foo` (flat-dir convention).
47
+ 4. **Aggregate signals** — read `.specweave/state/skill-signals.json`, filter to refinements targeting the given skill within the last N increments (default 5). Break down by source + severity.
48
+ 5. **`--show-signals` short-circuit** — pretty-print the aggregate and exit; no LLM call.
49
+ 6. **Haiku diff proposal** — call `claude-haiku-4-5-20251001` at `temperature=0` with `(current SKILL.md, signal aggregate)`. Return `{ diff, rationale }`. Determinism: repeat runs with identical inputs produce byte-identical output (AC-US2-02).
50
+ 7. **`--dry-run` short-circuit** — print diff + rationale; exit. No ledger entry, no commit.
51
+ 8. **Interactive approval** — show diff + rationale, prompt `approve / reject / edit`. Edit loops at most 3 times before auto-reject.
52
+ 9. **On approve** — `git apply` the patch, `git add -- <SKILL.md>`, `git commit -m "refine(<skill>): <rationale>"`. Record the commit SHA in `.specweave/state/skill-refinements.json` with `status: "applied"`. Never pushes.
53
+ 10. **On reject** — write a rejection ledger entry with the user's reason. SKILL.md is untouched.
54
+
55
+ ## Signals
56
+
57
+ Refinement signals are emitted by the closure gates when a gate failure traces to a specific skill's instructions:
58
+
59
+ | Source | Emitted when |
60
+ |---|---|
61
+ | `judge-llm` | `judge-llm-report.json` finding cites a skill slug as the root cause |
62
+ | `rubric` | A rubric criterion fails and the rationale traces to a skill-directed behavior |
63
+ | `code-reviewer` | A critical finding is attributable to skill-directed behavior |
64
+
65
+ Attribution is intentionally high-precision / low-recall — a missing signal is better than a wrongly-blamed skill.
66
+
67
+ ## Files
68
+
69
+ - `plugins/specweave/skills/skill-refine/SKILL.md` — this file (the user-facing skill definition)
70
+ - `src/skills/skill-refine.ts` — CLI entry point (`runSkillRefine`)
71
+ - `src/core/skill-refine/aggregator.ts` — signal aggregation + breakdown
72
+ - `src/core/skill-refine/haiku-diff.ts` — Haiku-backed diff proposal (temperature 0, deterministic)
73
+ - `src/core/skill-refine/approval.ts` — interactive approve/reject/edit (via `@inquirer/prompts`)
74
+ - `src/core/skill-refine/apply.ts` — write + `git apply` + `git commit` + ledger append
75
+ - `src/core/skill-refine/ledger.ts` — append-only `.specweave/state/skill-refinements.json` writer
76
+ - `src/types/skill-refinements.ts` — ledger types + zod schema
77
+
78
+ ## When this skill activates
79
+
80
+ - User says `sw:skill-refine`, `refine skill`, `improve skill`, `skill refinement`.
81
+ - User responds to a session-end nudge (see `sw:reflect`) that suggests refining a specific skill.
82
+
83
+ ## ADRs
84
+
85
+ - [ADR-0671-01](../../../../.specweave/docs/internal/architecture/adr/0671-01-no-runtime-skill-mutation.md) — No runtime mutation of active skills.
86
+ - [ADR-0671-02](../../../../.specweave/docs/internal/architecture/adr/0671-02-registry-version-immutability.md) — Registry version immutability.
87
+ - [ADR-0671-03](../../../../.specweave/docs/internal/architecture/adr/0671-03-no-self-improving-marketing.md) — No "self-improving" marketing.
88
+ - [ADR-0671-04](../../../../.specweave/docs/internal/architecture/adr/0671-04-no-goodhart-loop.md) — No Goodhart loop on gate signals.
89
+
90
+ ## Error handling
91
+
92
+ - Missing SKILL.md → print the resolved path, exit with `no-diff` status.
93
+ - Zero signals → print "no signals for `<skill>` in the last N increments", exit cleanly.
94
+ - Haiku returns malformed JSON → surface the raw output, abort; the ledger is not touched.
95
+ - `git apply` fails → SKILL.md is restored from the pre-call snapshot, no commit, no ledger entry.
96
+ - `ANTHROPIC_API_KEY` unset → clear error before any prompt or write.