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.
- package/dist/dashboard/assets/{index-C434W7yF.js → index-Dpn4T2Mx.js} +7 -7
- package/dist/dashboard/index.html +1 -1
- package/dist/src/core/hooks/LifecycleHookDispatcher.d.ts +6 -1
- package/dist/src/core/hooks/LifecycleHookDispatcher.d.ts.map +1 -1
- package/dist/src/core/hooks/LifecycleHookDispatcher.js +66 -8
- package/dist/src/core/hooks/LifecycleHookDispatcher.js.map +1 -1
- package/dist/src/core/increment/completion-validator.d.ts +18 -0
- package/dist/src/core/increment/completion-validator.d.ts.map +1 -1
- package/dist/src/core/increment/completion-validator.js +75 -0
- package/dist/src/core/increment/completion-validator.js.map +1 -1
- package/dist/src/core/increment/status-commands.d.ts.map +1 -1
- package/dist/src/core/increment/status-commands.js +16 -1
- package/dist/src/core/increment/status-commands.js.map +1 -1
- package/dist/src/core/reflect-nudge/aggregator.d.ts +33 -0
- package/dist/src/core/reflect-nudge/aggregator.d.ts.map +1 -0
- package/dist/src/core/reflect-nudge/aggregator.js +80 -0
- package/dist/src/core/reflect-nudge/aggregator.js.map +1 -0
- package/dist/src/core/reflect-nudge/eligibility.d.ts +27 -0
- package/dist/src/core/reflect-nudge/eligibility.d.ts.map +1 -0
- package/dist/src/core/reflect-nudge/eligibility.js +114 -0
- package/dist/src/core/reflect-nudge/eligibility.js.map +1 -0
- package/dist/src/core/reflect-nudge/index.d.ts +14 -0
- package/dist/src/core/reflect-nudge/index.d.ts.map +1 -0
- package/dist/src/core/reflect-nudge/index.js +14 -0
- package/dist/src/core/reflect-nudge/index.js.map +1 -0
- package/dist/src/core/reflect-nudge/interactive-prompt.d.ts +28 -0
- package/dist/src/core/reflect-nudge/interactive-prompt.d.ts.map +1 -0
- package/dist/src/core/reflect-nudge/interactive-prompt.js +52 -0
- package/dist/src/core/reflect-nudge/interactive-prompt.js.map +1 -0
- package/dist/src/core/reflect-nudge/prompt-renderer.d.ts +23 -0
- package/dist/src/core/reflect-nudge/prompt-renderer.d.ts.map +1 -0
- package/dist/src/core/reflect-nudge/prompt-renderer.js +26 -0
- package/dist/src/core/reflect-nudge/prompt-renderer.js.map +1 -0
- package/dist/src/core/reflect-nudge/session-end-nudge.d.ts +31 -0
- package/dist/src/core/reflect-nudge/session-end-nudge.d.ts.map +1 -0
- package/dist/src/core/reflect-nudge/session-end-nudge.js +44 -0
- package/dist/src/core/reflect-nudge/session-end-nudge.js.map +1 -0
- package/dist/src/core/reflection/reflect-handler.d.ts +2 -0
- package/dist/src/core/reflection/reflect-handler.d.ts.map +1 -1
- package/dist/src/core/reflection/reflect-handler.js +4 -0
- package/dist/src/core/reflection/reflect-handler.js.map +1 -1
- package/dist/src/core/rubric/rubric-evaluator.d.ts +15 -0
- package/dist/src/core/rubric/rubric-evaluator.d.ts.map +1 -1
- package/dist/src/core/rubric/rubric-evaluator.js +59 -0
- package/dist/src/core/rubric/rubric-evaluator.js.map +1 -1
- package/dist/src/core/skill-attribution.d.ts +78 -0
- package/dist/src/core/skill-attribution.d.ts.map +1 -0
- package/dist/src/core/skill-attribution.js +168 -0
- package/dist/src/core/skill-attribution.js.map +1 -0
- package/dist/src/core/skill-refine/aggregator.d.ts +36 -0
- package/dist/src/core/skill-refine/aggregator.d.ts.map +1 -0
- package/dist/src/core/skill-refine/aggregator.js +58 -0
- package/dist/src/core/skill-refine/aggregator.js.map +1 -0
- package/dist/src/core/skill-refine/apply.d.ts +48 -0
- package/dist/src/core/skill-refine/apply.d.ts.map +1 -0
- package/dist/src/core/skill-refine/apply.js +97 -0
- package/dist/src/core/skill-refine/apply.js.map +1 -0
- package/dist/src/core/skill-refine/approval.d.ts +71 -0
- package/dist/src/core/skill-refine/approval.d.ts.map +1 -0
- package/dist/src/core/skill-refine/approval.js +113 -0
- package/dist/src/core/skill-refine/approval.js.map +1 -0
- package/dist/src/core/skill-refine/haiku-diff.d.ts +66 -0
- package/dist/src/core/skill-refine/haiku-diff.d.ts.map +1 -0
- package/dist/src/core/skill-refine/haiku-diff.js +111 -0
- package/dist/src/core/skill-refine/haiku-diff.js.map +1 -0
- package/dist/src/core/skill-refine/ledger.d.ts +34 -0
- package/dist/src/core/skill-refine/ledger.d.ts.map +1 -0
- package/dist/src/core/skill-refine/ledger.js +81 -0
- package/dist/src/core/skill-refine/ledger.js.map +1 -0
- package/dist/src/core/skill-signal-emit.d.ts +46 -0
- package/dist/src/core/skill-signal-emit.d.ts.map +1 -0
- package/dist/src/core/skill-signal-emit.js +59 -0
- package/dist/src/core/skill-signal-emit.js.map +1 -0
- package/dist/src/core/skill-signals/index.d.ts +9 -0
- package/dist/src/core/skill-signals/index.d.ts.map +1 -0
- package/dist/src/core/skill-signals/index.js +9 -0
- package/dist/src/core/skill-signals/index.js.map +1 -0
- package/dist/src/core/skill-signals/reader.d.ts +30 -0
- package/dist/src/core/skill-signals/reader.d.ts.map +1 -0
- package/dist/src/core/skill-signals/reader.js +102 -0
- package/dist/src/core/skill-signals/reader.js.map +1 -0
- package/dist/src/core/skill-signals/writer.d.ts +34 -0
- package/dist/src/core/skill-signals/writer.d.ts.map +1 -0
- package/dist/src/core/skill-signals/writer.js +62 -0
- package/dist/src/core/skill-signals/writer.js.map +1 -0
- package/dist/src/core/skills/skill-judge.d.ts +8 -0
- package/dist/src/core/skills/skill-judge.d.ts.map +1 -1
- package/dist/src/core/skills/skill-judge.js +55 -0
- package/dist/src/core/skills/skill-judge.js.map +1 -1
- package/dist/src/skills/reflect-status.d.ts +23 -0
- package/dist/src/skills/reflect-status.d.ts.map +1 -0
- package/dist/src/skills/reflect-status.js +55 -0
- package/dist/src/skills/reflect-status.js.map +1 -0
- package/dist/src/skills/skill-refine.d.ts +81 -0
- package/dist/src/skills/skill-refine.d.ts.map +1 -0
- package/dist/src/skills/skill-refine.js +226 -0
- package/dist/src/skills/skill-refine.js.map +1 -0
- package/dist/src/sync/sync-coordinator.d.ts +14 -4
- package/dist/src/sync/sync-coordinator.d.ts.map +1 -1
- package/dist/src/sync/sync-coordinator.js +100 -38
- package/dist/src/sync/sync-coordinator.js.map +1 -1
- package/dist/src/types/skill-refinements.d.ts +75 -0
- package/dist/src/types/skill-refinements.d.ts.map +1 -0
- package/dist/src/types/skill-refinements.js +43 -0
- package/dist/src/types/skill-refinements.js.map +1 -0
- package/dist/src/types/skill-signals.d.ts +200 -0
- package/dist/src/types/skill-signals.d.ts.map +1 -0
- package/dist/src/types/skill-signals.js +115 -0
- package/dist/src/types/skill-signals.js.map +1 -0
- package/package.json +2 -2
- package/plugins/specweave/commands/reflect.md +48 -0
- package/plugins/specweave/skills/code-reviewer/SKILL.md +4 -0
- package/plugins/specweave/skills/judge-llm/SKILL.md +4 -0
- package/plugins/specweave/skills/skill-gen/SKILL.md +8 -0
- 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":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,MAAM,CAAC,MAAM,cAAc,GAA4B;IACrD,WAAW;IACX,QAAQ;IACR,eAAe;CAChB,CAAC;AACF,MAAM,CAAC,MAAM,iBAAiB,GAA8B,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAyBtF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;IAC7B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACjC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC7B,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;IACtB,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;IACrB,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;IACtB,iBAAiB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CAClD,CAAC,CAAC;AAoBH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;IAC7B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;IACxD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC3C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClC,CAAC,CAAC;AAMH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IAC5D,sBAAsB;IACtB,sBAAsB;CACvB,CAAC,CAAC;AAUH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3B,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC;CACpC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAe;IAC3C,aAAa,EAAE,CAAC;IAChB,OAAO,EAAE,EAAE;CACZ,CAAC;AAyBF,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACjC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC7B,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;IACtB,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;IACrB,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;IACtB,iBAAiB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CAClD,CAAC,CAAC;AAEH,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC;CACtC,CAAC,CAAC;AAEH,wEAAwE;AAExE;;;;GAIG;AACH,MAAM,UAAU,IAAI,CAAC,GAAY;IAC/B,OAAO,mBAAmB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;AACpD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,EAAiB;IAC7C,OAAO;QACL,aAAa,EAAE,CAAC;QAChB,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAClC,IAAI,EAAE,YAAqB;YAC3B,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,YAAY,EAAE,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC;YACrC,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,QAAQ,EAAE,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC;YAC7B,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,GAAG,CAAC,KAAK,CAAC,iBAAiB,KAAK,SAAS;gBACvC,CAAC,CAAC,EAAE,iBAAiB,EAAE,CAAC,GAAG,KAAK,CAAC,iBAAiB,CAAC,EAAE;gBACrD,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specweave",
|
|
3
|
-
"version": "1.0.
|
|
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.
|
|
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.
|