@shrkcrft/inspector 0.1.0-alpha.8 → 0.1.0-alpha.9
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/README.md +1 -1
- package/dist/adoption-state.js +1 -1
- package/dist/agent-brief.d.ts.map +1 -1
- package/dist/agent-brief.js +10 -59
- package/dist/agent-task-prep.d.ts.map +1 -1
- package/dist/agent-task-prep.js +3 -1
- package/dist/ai-readiness.d.ts +9 -84
- package/dist/ai-readiness.d.ts.map +1 -1
- package/dist/ai-readiness.js +30 -161
- package/dist/apply-dispatch-trace.d.ts +2 -1
- package/dist/apply-dispatch-trace.d.ts.map +1 -1
- package/dist/apply-dispatch-trace.js +9 -0
- package/dist/area-explore.d.ts.map +1 -1
- package/dist/area-explore.js +5 -1
- package/dist/area-map.d.ts +19 -0
- package/dist/area-map.d.ts.map +1 -1
- package/dist/area-map.js +27 -0
- package/dist/ci-permissions-fix.d.ts +1 -1
- package/dist/ci-permissions-fix.d.ts.map +1 -1
- package/dist/ci-permissions-fix.js +182 -1
- package/dist/compliance-profiles.js +1 -1
- package/dist/construct-adoption-diff.d.ts.map +1 -1
- package/dist/construct-adoption-diff.js +1 -2
- package/dist/construct-adoption.d.ts.map +1 -1
- package/dist/construct-adoption.js +11 -10
- package/dist/construct-inference.d.ts.map +1 -1
- package/dist/construct-inference.js +1 -2
- package/dist/construct-registry.d.ts.map +1 -1
- package/dist/construct-registry.js +10 -2
- package/dist/contract-template-registry.d.ts.map +1 -1
- package/dist/contract-template-registry.js +10 -2
- package/dist/convention-registry.d.ts.map +1 -1
- package/dist/convention-registry.js +10 -2
- package/dist/decision-records.d.ts.map +1 -1
- package/dist/decision-records.js +9 -2
- package/dist/demo-script.d.ts +1 -0
- package/dist/demo-script.d.ts.map +1 -1
- package/dist/demo-script.js +43 -0
- package/dist/docs-check.js +1 -1
- package/dist/drift-baseline.d.ts.map +1 -1
- package/dist/drift-baseline.js +2 -5
- package/dist/feedback-ingestion.d.ts.map +1 -1
- package/dist/feedback-ingestion.js +16 -2
- package/dist/git-helpers.d.ts +12 -0
- package/dist/git-helpers.d.ts.map +1 -1
- package/dist/git-helpers.js +63 -0
- package/dist/helper-registry.d.ts +54 -27
- package/dist/helper-registry.d.ts.map +1 -1
- package/dist/helper-registry.js +517 -16
- package/dist/impact-analysis.d.ts.map +1 -1
- package/dist/impact-analysis.js +5 -4
- package/dist/impact-render.d.ts.map +1 -1
- package/dist/impact-render.js +9 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/ingest-drafts.js +4 -8
- package/dist/migration-profile-registry.d.ts.map +1 -1
- package/dist/migration-profile-registry.js +10 -2
- package/dist/monorepo-onboarding.js +2 -2
- package/dist/onboarding-drafts-merge.d.ts +71 -0
- package/dist/onboarding-drafts-merge.d.ts.map +1 -0
- package/dist/onboarding-drafts-merge.js +174 -0
- package/dist/onboarding-drafts.d.ts +14 -0
- package/dist/onboarding-drafts.d.ts.map +1 -1
- package/dist/onboarding-drafts.js +39 -5
- package/dist/onboarding-report.d.ts.map +1 -1
- package/dist/onboarding-report.js +1 -5
- package/dist/onboarding.d.ts +1 -1
- package/dist/onboarding.d.ts.map +1 -1
- package/dist/onboarding.js +64 -5
- package/dist/ownership.js +10 -2
- package/dist/pack-contributions-inventory.d.ts +1 -0
- package/dist/pack-contributions-inventory.d.ts.map +1 -1
- package/dist/pack-contributions-inventory.js +24 -0
- package/dist/pack-helper-registry.d.ts.map +1 -1
- package/dist/pack-helper-registry.js +10 -2
- package/dist/pack-release-check.d.ts.map +1 -1
- package/dist/pack-release-check.js +11 -4
- package/dist/pack-signature-status.d.ts.map +1 -1
- package/dist/pack-signature-status.js +1 -0
- package/dist/pack-symbol-compat.d.ts +17 -4
- package/dist/pack-symbol-compat.d.ts.map +1 -1
- package/dist/pack-symbol-compat.js +155 -7
- package/dist/pack-test-runner.js +10 -2
- package/dist/plan-simulation.d.ts.map +1 -1
- package/dist/plan-simulation.js +20 -3
- package/dist/playbook-registry.d.ts.map +1 -1
- package/dist/playbook-registry.js +10 -2
- package/dist/plugin-lifecycle-profile-registry.d.ts +52 -0
- package/dist/plugin-lifecycle-profile-registry.d.ts.map +1 -0
- package/dist/plugin-lifecycle-profile-registry.js +202 -0
- package/dist/plugin-lifecycle.d.ts +132 -0
- package/dist/plugin-lifecycle.d.ts.map +1 -0
- package/dist/plugin-lifecycle.js +477 -0
- package/dist/policy-engine.d.ts.map +1 -1
- package/dist/policy-engine.js +11 -3
- package/dist/policy-test.js +11 -3
- package/dist/product-coherence.js +5 -5
- package/dist/profile-registry.d.ts +1 -0
- package/dist/profile-registry.d.ts.map +1 -1
- package/dist/profile-registry.js +32 -4
- package/dist/quality-baseline.d.ts.map +1 -1
- package/dist/quality-baseline.js +1 -3
- package/dist/ranker-explainability.d.ts.map +1 -1
- package/dist/ranker-explainability.js +9 -3
- package/dist/registration-hint-registry.d.ts.map +1 -1
- package/dist/registration-hint-registry.js +10 -2
- package/dist/release-readiness.js +5 -5
- package/dist/reposet.js +1 -1
- package/dist/repository-knowledge-model.d.ts +1 -1
- package/dist/repository-knowledge-model.d.ts.map +1 -1
- package/dist/review-packet-v2.d.ts.map +1 -1
- package/dist/review-packet-v2.js +13 -3
- package/dist/rule-scaffold.d.ts.map +1 -1
- package/dist/rule-scaffold.js +4 -12
- package/dist/scaffold-patterns.js +10 -2
- package/dist/search-tuning-registry.d.ts.map +1 -1
- package/dist/search-tuning-registry.js +10 -2
- package/dist/self-config-doctor-v2.d.ts +1 -1
- package/dist/self-config-doctor-v2.d.ts.map +1 -1
- package/dist/self-config-doctor-v2.js +10 -6
- package/dist/self-config-doctor.d.ts.map +1 -1
- package/dist/self-config-doctor.js +13 -7
- package/dist/sharkcraft-inspector.d.ts.map +1 -1
- package/dist/sharkcraft-inspector.js +0 -1
- package/dist/start-here.d.ts +1 -1
- package/dist/start-here.js +1 -1
- package/dist/task-ranker.d.ts.map +1 -1
- package/dist/task-ranker.js +31 -1
- package/dist/task-routing-hint-registry.d.ts.map +1 -1
- package/dist/task-routing-hint-registry.js +10 -2
- package/dist/test-runner.d.ts.map +1 -1
- package/dist/test-runner.js +16 -8
- package/dist/universal-search.d.ts +1 -0
- package/dist/universal-search.d.ts.map +1 -1
- package/dist/universal-search.js +12 -0
- package/dist/upgrade-advisor.js +1 -1
- package/package.json +21 -22
- package/dist/synthesize-from-onboarding.d.ts +0 -68
- package/dist/synthesize-from-onboarding.d.ts.map +0 -1
- package/dist/synthesize-from-onboarding.js +0 -508
package/dist/helper-registry.js
CHANGED
|
@@ -1,28 +1,529 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Helper plan generators.
|
|
2
|
+
* Helper plan generators (profile-driven for project-specific paths).
|
|
3
3
|
*
|
|
4
4
|
* Helpers are one-shot plan-v2 producers for small, well-bounded edits.
|
|
5
|
-
*
|
|
5
|
+
* They are dry-run by default and idempotent where the plan engine supports it.
|
|
6
6
|
*
|
|
7
|
-
* No helper writes source directly. The output is a structured
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* No helper writes source directly. The output is a structured `IHelperPlan`
|
|
8
|
+
* containing planned ops (using the existing plan-v2 operation set) and a
|
|
9
|
+
* list of advisory conflicts when an expected anchor cannot be resolved.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* Helpers must accept an IPluginLifecycleProfile instead of hardcoded paths,
|
|
12
|
+
* so the engine knows where the key-table / plugin roots live.
|
|
13
|
+
* Project-specific helpers contributed by packs travel in pack-contributed
|
|
14
|
+
* playbooks/scaffolds; the engine just provides the generic shapes.
|
|
15
|
+
*/
|
|
16
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
17
|
+
import { join } from 'node:path';
|
|
18
|
+
import { CaseStyle, } from '@shrkcrft/plugin-api';
|
|
19
|
+
export var HelperId;
|
|
20
|
+
(function (HelperId) {
|
|
21
|
+
HelperId["AddPluginKey"] = "core.add-plugin-key";
|
|
22
|
+
HelperId["RemovePluginKey"] = "core.remove-plugin-key";
|
|
23
|
+
HelperId["RenamePluginKey"] = "core.rename-plugin-key";
|
|
24
|
+
HelperId["AddBarrelExport"] = "core.add-barrel-export";
|
|
25
|
+
HelperId["RemoveBarrelExport"] = "core.remove-barrel-export";
|
|
26
|
+
HelperId["AddEventEntry"] = "core.add-event-entry";
|
|
27
|
+
HelperId["RemoveEventEntry"] = "core.remove-event-entry";
|
|
28
|
+
HelperId["AddDefaultRegistration"] = "core.add-default-registration";
|
|
29
|
+
HelperId["RemoveDefaultRegistration"] = "core.remove-default-registration";
|
|
30
|
+
HelperId["AddComposerEntry"] = "core.add-composer-entry";
|
|
31
|
+
HelperId["RemoveComposerEntry"] = "core.remove-composer-entry";
|
|
32
|
+
HelperId["RenamePluginFolder"] = "core.rename-plugin-folder";
|
|
33
|
+
HelperId["RemoveUserPluginEntry"] = "core.remove-user-plugin-entry";
|
|
34
|
+
})(HelperId || (HelperId = {}));
|
|
35
|
+
export const HELPERS = Object.freeze([
|
|
36
|
+
{
|
|
37
|
+
id: HelperId.AddPluginKey,
|
|
38
|
+
description: 'Insert a plugin key-table entry just before the closing `} as const;` brace (profile-driven).',
|
|
39
|
+
destructive: false,
|
|
40
|
+
requiresHumanReview: false,
|
|
41
|
+
requiresProfile: true,
|
|
42
|
+
variables: [
|
|
43
|
+
{ name: 'key', required: true, description: 'kebab-case plugin key (e.g. user-card).' },
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: HelperId.RemovePluginKey,
|
|
48
|
+
description: 'Remove a plugin key-table entry (profile-driven). Destructive.',
|
|
49
|
+
destructive: true,
|
|
50
|
+
requiresHumanReview: true,
|
|
51
|
+
requiresProfile: true,
|
|
52
|
+
variables: [{ name: 'key', required: true, description: 'kebab-case plugin key.' }],
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: HelperId.RenamePluginKey,
|
|
56
|
+
description: 'Rename a plugin key-table entry (profile-driven). Destructive.',
|
|
57
|
+
destructive: true,
|
|
58
|
+
requiresHumanReview: true,
|
|
59
|
+
requiresProfile: true,
|
|
60
|
+
variables: [
|
|
61
|
+
{ name: 'old', required: true, description: 'old kebab-case key.' },
|
|
62
|
+
{ name: 'new', required: true, description: 'new kebab-case key.' },
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: HelperId.AddBarrelExport,
|
|
67
|
+
description: 'Append an `export * from <module>` to a barrel.',
|
|
68
|
+
destructive: false,
|
|
69
|
+
requiresHumanReview: false,
|
|
70
|
+
variables: [
|
|
71
|
+
{ name: 'barrel', required: true, description: 'project-relative path to the barrel file.' },
|
|
72
|
+
{ name: 'from', required: true, description: 'relative module path to re-export.' },
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: HelperId.RemoveBarrelExport,
|
|
77
|
+
description: 'Remove a barrel `export * from` line. Destructive.',
|
|
78
|
+
destructive: true,
|
|
79
|
+
requiresHumanReview: true,
|
|
80
|
+
variables: [
|
|
81
|
+
{ name: 'barrel', required: true, description: 'project-relative path to the barrel file.' },
|
|
82
|
+
{ name: 'from', required: true, description: 'relative module path to remove.' },
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
id: HelperId.AddEventEntry,
|
|
87
|
+
description: 'Append a typed event entry to a plugin events file (requires `eventsPath` var when no profile root is suitable).',
|
|
88
|
+
destructive: false,
|
|
89
|
+
requiresHumanReview: false,
|
|
90
|
+
variables: [
|
|
91
|
+
{ name: 'plugin', required: true, description: 'host plugin kebab-case.' },
|
|
92
|
+
{ name: 'event', required: true, description: 'PascalCase event name.' },
|
|
93
|
+
{
|
|
94
|
+
name: 'eventsPath',
|
|
95
|
+
required: false,
|
|
96
|
+
description: 'Override target path. Otherwise derived from the first profile pluginRoot + plugin + /events.ts.',
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
id: HelperId.RemoveEventEntry,
|
|
102
|
+
description: 'Remove a typed event block from a plugin events file. Destructive.',
|
|
103
|
+
destructive: true,
|
|
104
|
+
requiresHumanReview: true,
|
|
105
|
+
variables: [
|
|
106
|
+
{ name: 'plugin', required: true, description: 'host plugin kebab-case.' },
|
|
107
|
+
{ name: 'event', required: true, description: 'PascalCase event name.' },
|
|
108
|
+
{
|
|
109
|
+
name: 'eventsPath',
|
|
110
|
+
required: false,
|
|
111
|
+
description: 'Override target path. Otherwise derived from the first profile pluginRoot + plugin + /events.ts.',
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
id: HelperId.AddDefaultRegistration,
|
|
117
|
+
description: 'Register default config/state providers (manual checklist; locations vary).',
|
|
118
|
+
destructive: false,
|
|
119
|
+
requiresHumanReview: true,
|
|
120
|
+
variables: [
|
|
121
|
+
{ name: 'name', required: true, description: 'plugin kebab-case.' },
|
|
122
|
+
{ name: 'pascal', required: true, description: 'plugin PascalCase.' },
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
id: HelperId.RemoveDefaultRegistration,
|
|
127
|
+
description: 'Remove default config/state provider registration (manual checklist). Destructive.',
|
|
128
|
+
destructive: true,
|
|
129
|
+
requiresHumanReview: true,
|
|
130
|
+
variables: [{ name: 'pascal', required: true, description: 'plugin PascalCase.' }],
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: HelperId.AddComposerEntry,
|
|
134
|
+
description: 'Append a composer entry (manual checklist — composer locations vary).',
|
|
135
|
+
destructive: false,
|
|
136
|
+
requiresHumanReview: true,
|
|
137
|
+
variables: [{ name: 'plugin', required: true, description: 'plugin kebab-case.' }],
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
id: HelperId.RemoveComposerEntry,
|
|
141
|
+
description: 'Remove a composer entry (manual checklist).',
|
|
142
|
+
destructive: true,
|
|
143
|
+
requiresHumanReview: true,
|
|
144
|
+
variables: [{ name: 'plugin', required: true, description: 'plugin kebab-case.' }],
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
id: HelperId.RenamePluginFolder,
|
|
148
|
+
description: 'Manual checklist: rename a plugin folder across the profile roots.',
|
|
149
|
+
destructive: true,
|
|
150
|
+
requiresHumanReview: true,
|
|
151
|
+
requiresProfile: true,
|
|
152
|
+
variables: [
|
|
153
|
+
{ name: 'old', required: true, description: 'old plugin kebab-case.' },
|
|
154
|
+
{ name: 'new', required: true, description: 'new plugin kebab-case.' },
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
id: HelperId.RemoveUserPluginEntry,
|
|
159
|
+
description: 'Remove a plugin entry from user-facing key-by-scope tables (heuristic).',
|
|
160
|
+
destructive: true,
|
|
161
|
+
requiresHumanReview: true,
|
|
162
|
+
variables: [{ name: 'key', required: true, description: 'plugin kebab-case.' }],
|
|
163
|
+
},
|
|
164
|
+
]);
|
|
165
|
+
/**
|
|
166
|
+
* Convert a helper plan into a saved plan (synthetic templateId) so
|
|
167
|
+
* it flows through `shrk apply`. Helper ops are persisted as v2 operation
|
|
168
|
+
* intents; the apply path evaluates them against the live file system.
|
|
169
|
+
* Unsigned by default; call `signPlan` separately when desired.
|
|
13
170
|
*/
|
|
14
|
-
export const HELPERS = Object.freeze([]);
|
|
15
171
|
export const HELPER_SYNTHETIC_TEMPLATE = '__helper__';
|
|
16
|
-
export function
|
|
17
|
-
|
|
172
|
+
export function helperPlanToSavedPlan(plan, projectRoot) {
|
|
173
|
+
// Map each helper op to a saved expectedChange. The sizeBytes is the
|
|
174
|
+
// best-effort post-apply size (zero for inserts whose snippet is empty)
|
|
175
|
+
// — the live evaluator recomputes the actual size at apply time.
|
|
176
|
+
const expectedChanges = plan.ops.map((op) => {
|
|
177
|
+
const kind = typeof op.operation['kind'] === 'string' ? op.operation['kind'] : 'append';
|
|
178
|
+
let sizeBytes = 0;
|
|
179
|
+
if (typeof op.operation['snippet'] === 'string') {
|
|
180
|
+
sizeBytes = Buffer.byteLength(op.operation['snippet'], 'utf8');
|
|
181
|
+
}
|
|
182
|
+
else if (typeof op.operation['replaceWith'] === 'string') {
|
|
183
|
+
sizeBytes = Buffer.byteLength(op.operation['replaceWith'], 'utf8');
|
|
184
|
+
}
|
|
185
|
+
else if (typeof op.operation['content'] === 'string') {
|
|
186
|
+
sizeBytes = Buffer.byteLength(op.operation['content'], 'utf8');
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
type: kind,
|
|
190
|
+
relativePath: op.targetPath,
|
|
191
|
+
sizeBytes,
|
|
192
|
+
operation: op.operation,
|
|
193
|
+
};
|
|
194
|
+
});
|
|
195
|
+
const out = {
|
|
196
|
+
schema: 'sharkcraft.plan/v2',
|
|
197
|
+
templateId: HELPER_SYNTHETIC_TEMPLATE,
|
|
198
|
+
variables: {
|
|
199
|
+
helperId: plan.helperId,
|
|
200
|
+
...plan.variables,
|
|
201
|
+
},
|
|
202
|
+
projectRoot,
|
|
203
|
+
createdAt: new Date().toISOString(),
|
|
204
|
+
expectedChanges,
|
|
205
|
+
};
|
|
206
|
+
if (plan.manualSteps.length > 0) {
|
|
207
|
+
out.note = `Manual steps required: ${plan.manualSteps.join('; ')}`;
|
|
208
|
+
}
|
|
209
|
+
return out;
|
|
210
|
+
}
|
|
211
|
+
function readFileSafe(p) {
|
|
212
|
+
if (!existsSync(p))
|
|
213
|
+
return null;
|
|
214
|
+
try {
|
|
215
|
+
return readFileSync(p, 'utf8');
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function splitWords(input) {
|
|
222
|
+
if (!input)
|
|
223
|
+
return [];
|
|
224
|
+
if (input.includes('-') || input.includes('_'))
|
|
225
|
+
return input.split(/[-_]/).filter(Boolean);
|
|
226
|
+
return input.split(/(?=[A-Z])/).map((w) => w.toLowerCase()).filter(Boolean);
|
|
227
|
+
}
|
|
228
|
+
function toCase(input, style) {
|
|
229
|
+
const words = splitWords(input);
|
|
230
|
+
if (words.length === 0)
|
|
231
|
+
return input;
|
|
232
|
+
switch (style) {
|
|
233
|
+
case CaseStyle.Kebab:
|
|
234
|
+
return words.map((w) => w.toLowerCase()).join('-');
|
|
235
|
+
case CaseStyle.UpperSnake:
|
|
236
|
+
return words.map((w) => w.toUpperCase()).join('_');
|
|
237
|
+
case CaseStyle.Pascal:
|
|
238
|
+
return words.map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join('');
|
|
239
|
+
case CaseStyle.Camel:
|
|
240
|
+
return words
|
|
241
|
+
.map((w, i) => (i === 0 ? w.toLowerCase() : w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()))
|
|
242
|
+
.join('');
|
|
243
|
+
default:
|
|
244
|
+
return input;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
function escapeRegex(s) {
|
|
248
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
249
|
+
}
|
|
250
|
+
function requireProfile(helperId, profile) {
|
|
251
|
+
if (!profile) {
|
|
252
|
+
throw new Error(`Helper ${helperId} requires a lifecycle profile. Pass the profile loaded from sharkcraft/plugin-lifecycle-profiles or a pack.`);
|
|
253
|
+
}
|
|
254
|
+
return profile;
|
|
18
255
|
}
|
|
19
|
-
export function
|
|
20
|
-
|
|
256
|
+
export function buildHelperPlan(input) {
|
|
257
|
+
const def = HELPERS.find((h) => h.id === input.helperId);
|
|
258
|
+
if (!def) {
|
|
259
|
+
throw new Error(`Unknown helper id: ${input.helperId}`);
|
|
260
|
+
}
|
|
261
|
+
for (const v of def.variables) {
|
|
262
|
+
if (v.required && !input.vars[v.name]) {
|
|
263
|
+
throw new Error(`Helper ${def.id} requires variable "${v.name}".`);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
const ops = [];
|
|
267
|
+
const manual = [];
|
|
268
|
+
const conflicts = [];
|
|
269
|
+
switch (input.helperId) {
|
|
270
|
+
case HelperId.AddPluginKey: {
|
|
271
|
+
const profile = requireProfile(input.helperId, input.profile);
|
|
272
|
+
if (!profile.keyTable) {
|
|
273
|
+
conflicts.push(`Profile "${profile.id}" has no keyTable; cannot add a plugin key entry.`);
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
const keyTablePath = profile.keyTable.path;
|
|
277
|
+
const keyName = input.vars.key;
|
|
278
|
+
const key = toCase(keyName, profile.keyTable.keyCase);
|
|
279
|
+
const value = toCase(keyName, profile.keyTable.valueCase);
|
|
280
|
+
ops.push({
|
|
281
|
+
targetPath: keyTablePath,
|
|
282
|
+
operation: {
|
|
283
|
+
kind: 'insert-before',
|
|
284
|
+
anchor: '} as const;',
|
|
285
|
+
snippet: ` ${key}: '${value}',\n`,
|
|
286
|
+
ifMissing: `${key}:`,
|
|
287
|
+
description: `Register key-table entry ${key} = '${value}'.`,
|
|
288
|
+
},
|
|
289
|
+
});
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
292
|
+
case HelperId.RemovePluginKey: {
|
|
293
|
+
const profile = requireProfile(input.helperId, input.profile);
|
|
294
|
+
if (!profile.keyTable) {
|
|
295
|
+
conflicts.push(`Profile "${profile.id}" has no keyTable; nothing to remove.`);
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
const keyTablePath = profile.keyTable.path;
|
|
299
|
+
const keyName = input.vars.key;
|
|
300
|
+
const key = toCase(keyName, profile.keyTable.keyCase);
|
|
301
|
+
const value = toCase(keyName, profile.keyTable.valueCase);
|
|
302
|
+
const file = join(input.projectRoot, keyTablePath);
|
|
303
|
+
const content = readFileSafe(file);
|
|
304
|
+
const re = new RegExp(`\\s*${escapeRegex(key)}:\\s*['"]${escapeRegex(value)}['"],?\\n`);
|
|
305
|
+
const m = content?.match(re);
|
|
306
|
+
if (m) {
|
|
307
|
+
ops.push({
|
|
308
|
+
targetPath: keyTablePath,
|
|
309
|
+
operation: {
|
|
310
|
+
kind: 'replace',
|
|
311
|
+
find: m[0],
|
|
312
|
+
replaceWith: '',
|
|
313
|
+
description: `Remove key-table entry ${key}.`,
|
|
314
|
+
},
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
conflicts.push(`Key-table entry ${key} not found in ${keyTablePath}.`);
|
|
319
|
+
}
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
322
|
+
case HelperId.RenamePluginKey: {
|
|
323
|
+
const profile = requireProfile(input.helperId, input.profile);
|
|
324
|
+
if (!profile.keyTable) {
|
|
325
|
+
conflicts.push(`Profile "${profile.id}" has no keyTable; nothing to rename.`);
|
|
326
|
+
break;
|
|
327
|
+
}
|
|
328
|
+
const keyTablePath = profile.keyTable.path;
|
|
329
|
+
const oldName = input.vars.old;
|
|
330
|
+
const newName = input.vars.new;
|
|
331
|
+
const oldKey = toCase(oldName, profile.keyTable.keyCase);
|
|
332
|
+
const newKey = toCase(newName, profile.keyTable.keyCase);
|
|
333
|
+
const oldValue = toCase(oldName, profile.keyTable.valueCase);
|
|
334
|
+
const newValue = toCase(newName, profile.keyTable.valueCase);
|
|
335
|
+
const file = join(input.projectRoot, keyTablePath);
|
|
336
|
+
const content = readFileSafe(file);
|
|
337
|
+
const re = new RegExp(`(\\s*)${escapeRegex(oldKey)}:\\s*['"]${escapeRegex(oldValue)}['"](,?\\n)`);
|
|
338
|
+
const m = content?.match(re);
|
|
339
|
+
if (m) {
|
|
340
|
+
ops.push({
|
|
341
|
+
targetPath: keyTablePath,
|
|
342
|
+
operation: {
|
|
343
|
+
kind: 'replace',
|
|
344
|
+
find: m[0],
|
|
345
|
+
replaceWith: `${m[1]}${newKey}: '${newValue}'${m[2]}`,
|
|
346
|
+
description: `Rename key-table entry ${oldKey} → ${newKey}.`,
|
|
347
|
+
},
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
conflicts.push(`Key-table entry ${oldKey} not found.`);
|
|
352
|
+
}
|
|
353
|
+
break;
|
|
354
|
+
}
|
|
355
|
+
case HelperId.AddBarrelExport: {
|
|
356
|
+
const barrel = input.vars.barrel;
|
|
357
|
+
const from = input.vars.from;
|
|
358
|
+
ops.push({
|
|
359
|
+
targetPath: barrel,
|
|
360
|
+
operation: {
|
|
361
|
+
kind: 'export',
|
|
362
|
+
from,
|
|
363
|
+
description: `Append export * from '${from}' to ${barrel}.`,
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
368
|
+
case HelperId.RemoveBarrelExport: {
|
|
369
|
+
const barrel = input.vars.barrel;
|
|
370
|
+
const from = input.vars.from;
|
|
371
|
+
const content = readFileSafe(join(input.projectRoot, barrel));
|
|
372
|
+
const lines = (content ?? '').split('\n');
|
|
373
|
+
const match = lines.find((l) => l.includes(`'${from}'`) || l.includes(`"${from}"`));
|
|
374
|
+
if (match) {
|
|
375
|
+
ops.push({
|
|
376
|
+
targetPath: barrel,
|
|
377
|
+
operation: {
|
|
378
|
+
kind: 'replace',
|
|
379
|
+
find: match + '\n',
|
|
380
|
+
replaceWith: '',
|
|
381
|
+
description: `Remove export * from '${from}' from ${barrel}.`,
|
|
382
|
+
},
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
conflicts.push(`No export referencing '${from}' in ${barrel}.`);
|
|
387
|
+
}
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
390
|
+
case HelperId.AddEventEntry: {
|
|
391
|
+
const plugin = input.vars.plugin;
|
|
392
|
+
const eventPascal = input.vars.event;
|
|
393
|
+
const upper = toCase(eventPascal, CaseStyle.UpperSnake);
|
|
394
|
+
let eventsPath = input.vars.eventsPath;
|
|
395
|
+
if (!eventsPath) {
|
|
396
|
+
const profile = requireProfile(input.helperId, input.profile);
|
|
397
|
+
const root = profile.pluginRoots[0];
|
|
398
|
+
if (!root) {
|
|
399
|
+
conflicts.push(`Profile "${profile.id}" has no pluginRoots; cannot derive eventsPath.`);
|
|
400
|
+
break;
|
|
401
|
+
}
|
|
402
|
+
eventsPath = `${root.path}/${plugin}/events.ts`;
|
|
403
|
+
}
|
|
404
|
+
const beginMarker = `// ─── ${eventPascal} event (helper) ───`;
|
|
405
|
+
const snippet = `\n${beginMarker}\n` +
|
|
406
|
+
`export interface ${eventPascal}Payload {}\n` +
|
|
407
|
+
`// ${eventPascal} event entry; wire EventType.${upper} manually.\n` +
|
|
408
|
+
`// ─── end ${eventPascal} event ───\n`;
|
|
409
|
+
ops.push({
|
|
410
|
+
targetPath: eventsPath,
|
|
411
|
+
operation: {
|
|
412
|
+
kind: 'append',
|
|
413
|
+
snippet,
|
|
414
|
+
ifMissing: beginMarker,
|
|
415
|
+
description: `Append ${eventPascal} event block to ${eventsPath}.`,
|
|
416
|
+
},
|
|
417
|
+
});
|
|
418
|
+
manual.push(`Add the EventType.${upper} = '${plugin}.${toCase(eventPascal, CaseStyle.Camel)}' enum entry inside the host's EventType enum.`);
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
421
|
+
case HelperId.RemoveEventEntry: {
|
|
422
|
+
const plugin = input.vars.plugin;
|
|
423
|
+
const eventPascal = input.vars.event;
|
|
424
|
+
let eventsPath = input.vars.eventsPath;
|
|
425
|
+
if (!eventsPath) {
|
|
426
|
+
const profile = requireProfile(input.helperId, input.profile);
|
|
427
|
+
const root = profile.pluginRoots[0];
|
|
428
|
+
if (!root) {
|
|
429
|
+
conflicts.push(`Profile "${profile.id}" has no pluginRoots; cannot derive eventsPath.`);
|
|
430
|
+
break;
|
|
431
|
+
}
|
|
432
|
+
eventsPath = `${root.path}/${plugin}/events.ts`;
|
|
433
|
+
}
|
|
434
|
+
const file = join(input.projectRoot, eventsPath);
|
|
435
|
+
const content = readFileSafe(file);
|
|
436
|
+
const beginMarker = `// ─── ${eventPascal} event`;
|
|
437
|
+
const endMarker = `// ─── end ${eventPascal} event ───`;
|
|
438
|
+
if (content && content.includes(beginMarker) && content.includes(endMarker)) {
|
|
439
|
+
const start = content.indexOf(beginMarker);
|
|
440
|
+
const end = content.indexOf(endMarker) + endMarker.length + 1;
|
|
441
|
+
const block = content.slice(start, end);
|
|
442
|
+
ops.push({
|
|
443
|
+
targetPath: eventsPath,
|
|
444
|
+
operation: {
|
|
445
|
+
kind: 'replace',
|
|
446
|
+
find: block,
|
|
447
|
+
replaceWith: '',
|
|
448
|
+
description: `Remove ${eventPascal} event block from ${eventsPath}.`,
|
|
449
|
+
},
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
else {
|
|
453
|
+
conflicts.push(`Event block ${eventPascal} not found in ${eventsPath}.`);
|
|
454
|
+
}
|
|
455
|
+
break;
|
|
456
|
+
}
|
|
457
|
+
case HelperId.AddDefaultRegistration: {
|
|
458
|
+
const pascal = input.vars.pascal;
|
|
459
|
+
manual.push(`Register ${pascal} default providers in the runtime composition layer (composer location varies — review manually).`);
|
|
460
|
+
break;
|
|
461
|
+
}
|
|
462
|
+
case HelperId.RemoveDefaultRegistration: {
|
|
463
|
+
const pascal = input.vars.pascal;
|
|
464
|
+
manual.push(`Remove ${pascal} default providers from the runtime composition layer (composer location varies — review manually).`);
|
|
465
|
+
break;
|
|
466
|
+
}
|
|
467
|
+
case HelperId.AddComposerEntry: {
|
|
468
|
+
const plugin = input.vars.plugin;
|
|
469
|
+
manual.push(`Append ${plugin} entry to the appropriate composer. Composer locations vary — review manually.`);
|
|
470
|
+
break;
|
|
471
|
+
}
|
|
472
|
+
case HelperId.RemoveComposerEntry: {
|
|
473
|
+
const plugin = input.vars.plugin;
|
|
474
|
+
manual.push(`Remove ${plugin} entry from the appropriate composer. Composer locations vary — review manually.`);
|
|
475
|
+
break;
|
|
476
|
+
}
|
|
477
|
+
case HelperId.RenamePluginFolder: {
|
|
478
|
+
const oldName = input.vars.old;
|
|
479
|
+
const newName = input.vars.new;
|
|
480
|
+
const profile = requireProfile(input.helperId, input.profile);
|
|
481
|
+
for (const root of profile.pluginRoots) {
|
|
482
|
+
manual.push(`git mv ${root.path}/${oldName} ${root.path}/${newName}`);
|
|
483
|
+
}
|
|
484
|
+
break;
|
|
485
|
+
}
|
|
486
|
+
case HelperId.RemoveUserPluginEntry: {
|
|
487
|
+
const key = input.vars.key;
|
|
488
|
+
manual.push(`Search for "${key}" in user-facing key-by-scope tables and remove the corresponding entry. Heuristic — review manually.`);
|
|
489
|
+
break;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return {
|
|
493
|
+
schema: 'sharkcraft.helper-plan/v1',
|
|
494
|
+
helperId: input.helperId,
|
|
495
|
+
variables: { ...input.vars },
|
|
496
|
+
ops,
|
|
497
|
+
manualSteps: manual,
|
|
498
|
+
conflicts,
|
|
499
|
+
destructive: def.destructive,
|
|
500
|
+
humanReviewRequired: def.requiresHumanReview,
|
|
501
|
+
};
|
|
21
502
|
}
|
|
22
503
|
export function renderHelperPlanText(plan) {
|
|
23
504
|
const lines = [];
|
|
24
|
-
lines.push(
|
|
25
|
-
lines.push(`
|
|
26
|
-
lines.push(`
|
|
27
|
-
|
|
505
|
+
lines.push(`=== Helper plan: ${plan.helperId} ===`);
|
|
506
|
+
lines.push(` destructive ${plan.destructive ? 'YES' : 'no'}`);
|
|
507
|
+
lines.push(` review ${plan.humanReviewRequired ? 'human review required' : 'auto'}`);
|
|
508
|
+
lines.push('');
|
|
509
|
+
lines.push(`Operations (${plan.ops.length}):`);
|
|
510
|
+
for (const op of plan.ops) {
|
|
511
|
+
const o = op.operation;
|
|
512
|
+
lines.push(` • ${op.targetPath} [${o.kind ?? '?'}]`);
|
|
513
|
+
if (o.description)
|
|
514
|
+
lines.push(` ${o.description}`);
|
|
515
|
+
}
|
|
516
|
+
if (plan.manualSteps.length > 0) {
|
|
517
|
+
lines.push('');
|
|
518
|
+
lines.push(`Manual steps:`);
|
|
519
|
+
for (const m of plan.manualSteps)
|
|
520
|
+
lines.push(` • ${m}`);
|
|
521
|
+
}
|
|
522
|
+
if (plan.conflicts.length > 0) {
|
|
523
|
+
lines.push('');
|
|
524
|
+
lines.push(`Conflicts:`);
|
|
525
|
+
for (const c of plan.conflicts)
|
|
526
|
+
lines.push(` • ${c}`);
|
|
527
|
+
}
|
|
528
|
+
return lines.join('\n') + '\n';
|
|
28
529
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impact-analysis.d.ts","sourceRoot":"","sources":["../src/impact-analysis.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"impact-analysis.d.ts","sourceRoot":"","sources":["../src/impact-analysis.ts"],"names":[],"mappings":"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"}
|
package/dist/impact-analysis.js
CHANGED
|
@@ -366,10 +366,10 @@ function affectedPolicies(ctx, affected, boundary) {
|
|
|
366
366
|
severity: 'warning',
|
|
367
367
|
});
|
|
368
368
|
}
|
|
369
|
-
if (affected.some((a) => a.kind === AreaKind.Core)) {
|
|
369
|
+
if (affected.some((a) => a.kind === AreaKind.Core || a.kind === AreaKind.Kernel)) {
|
|
370
370
|
concerns.push({
|
|
371
371
|
policyId: 'core.protected-area',
|
|
372
|
-
reason: 'Core area touched; requires elevated review.',
|
|
372
|
+
reason: 'Core / kernel area touched; requires elevated review.',
|
|
373
373
|
severity: 'error',
|
|
374
374
|
});
|
|
375
375
|
}
|
|
@@ -442,7 +442,7 @@ function classifyRisk(input) {
|
|
|
442
442
|
score += 18;
|
|
443
443
|
reasons.push({
|
|
444
444
|
code: 'core-area',
|
|
445
|
-
message: 'Touches core area.',
|
|
445
|
+
message: 'Touches core / kernel area.',
|
|
446
446
|
});
|
|
447
447
|
}
|
|
448
448
|
if (input.boundaryCount > 0) {
|
|
@@ -610,8 +610,9 @@ export async function analyzeImpact(inspection, input) {
|
|
|
610
610
|
}));
|
|
611
611
|
const publicApi = files.some((f) => f.endsWith('/index.ts') ||
|
|
612
612
|
f.endsWith('main.ts') ||
|
|
613
|
+
f.includes('plugin-api/') ||
|
|
613
614
|
f.includes('public-api/'));
|
|
614
|
-
const hitsCore = affectedAreas.some((a) => a.kind === AreaKind.Core);
|
|
615
|
+
const hitsCore = affectedAreas.some((a) => a.kind === AreaKind.Core || a.kind === AreaKind.Kernel || a.kind === AreaKind.Common);
|
|
615
616
|
const hitsPolicy = files.some((f) => f.includes('policy') || f.includes('policy-engine'));
|
|
616
617
|
const hitsTemplates = templates.length > 0 || pipelines.length > 0;
|
|
617
618
|
const ownershipReview = (ownership?.requiredReviewFiles.length ?? 0) > 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impact-render.d.ts","sourceRoot":"","sources":["../src/impact-render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,WAAW,oBAAoB;IACnC,kEAAkE;IAClE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA6BD,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,EAAE,CAAC;CACvB;AAED,uEAAuE;AACvE,wBAAgB,eAAe,CAC7B,MAAM,EAAE,eAAe,EACvB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5C,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"impact-render.d.ts","sourceRoot":"","sources":["../src/impact-render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,WAAW,oBAAoB;IACnC,kEAAkE;IAClE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA6BD,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,EAAE,CAAC;CACvB;AAED,uEAAuE;AACvE,wBAAgB,eAAe,CAC7B,MAAM,EAAE,eAAe,EACvB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5C,SAAS,EAAE,CAiDb;AAiCD,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,eAAe,EACvB,IAAI,GAAE,oBAAyB,GAC9B,MAAM,CAgER;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,eAAe,EACvB,IAAI,GAAE,oBAAyB,GAC9B,MAAM,CAyGR;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,eAAe,EACvB,IAAI,GAAE,oBAAyB,GAC9B,MAAM,CAiIR"}
|
package/dist/impact-render.js
CHANGED
|
@@ -36,6 +36,11 @@ export function buildImpactTree(impact, opts = {}) {
|
|
|
36
36
|
for (let i = 0; i < chain.length - 1; i += 1) {
|
|
37
37
|
const importer = chain[i];
|
|
38
38
|
const target = chain[i + 1];
|
|
39
|
+
// Skip self-references — a file cannot import itself in the
|
|
40
|
+
// dependency tree we render. (Cycles do exist in import graphs,
|
|
41
|
+
// but the renderer's job is reviewer clarity, not topology.)
|
|
42
|
+
if (importer === target)
|
|
43
|
+
continue;
|
|
39
44
|
const set = importers.get(target) ?? new Set();
|
|
40
45
|
set.add(importer);
|
|
41
46
|
importers.set(target, set);
|
|
@@ -45,6 +50,10 @@ export function buildImpactTree(impact, opts = {}) {
|
|
|
45
50
|
for (const target of impact.normalizedTargets) {
|
|
46
51
|
const set = importers.get(target) ?? new Set();
|
|
47
52
|
for (const dep of impact.directDependents) {
|
|
53
|
+
// Skip self — a target appearing in its own directDependents list
|
|
54
|
+
// is a graph artifact, not a real edge to render.
|
|
55
|
+
if (dep === target)
|
|
56
|
+
continue;
|
|
48
57
|
// Heuristic: every direct dependent is a candidate importer of every
|
|
49
58
|
// target (the real graph is captured in dependencyPathExamples).
|
|
50
59
|
// We only add direct dependents if they don't already appear as
|
package/dist/index.d.ts
CHANGED
|
@@ -22,8 +22,8 @@ export * from './test-runner.js';
|
|
|
22
22
|
export * from './plan-review.js';
|
|
23
23
|
export * from './onboarding.js';
|
|
24
24
|
export * from './onboarding-report.js';
|
|
25
|
-
export * from './synthesize-from-onboarding.js';
|
|
26
25
|
export * from './onboarding-drafts.js';
|
|
26
|
+
export * from './onboarding-drafts-merge.js';
|
|
27
27
|
export * from './onboarding-diff.js';
|
|
28
28
|
export * from './onboarding-adoption.js';
|
|
29
29
|
export * from './adoption-state.js';
|
|
@@ -48,6 +48,7 @@ export * from './dev-session-html.js';
|
|
|
48
48
|
export * from './dashboard/dashboard-data.js';
|
|
49
49
|
export * from './git-helpers.js';
|
|
50
50
|
export * from './boundaries-changed-only.js';
|
|
51
|
+
export * from './plugin-lifecycle.js';
|
|
51
52
|
export * from './helper-registry.js';
|
|
52
53
|
export * from './pack-author-ux.js';
|
|
53
54
|
export * from './pack-test-runner.js';
|
|
@@ -174,6 +175,7 @@ export * from './changes-summary.js';
|
|
|
174
175
|
export * from './pr-summary.js';
|
|
175
176
|
export * from './ci-integrity-report.js';
|
|
176
177
|
export * from './uncertainty.js';
|
|
178
|
+
export * from './plugin-lifecycle-profile-registry.js';
|
|
177
179
|
export * from './contract-template-registry.js';
|
|
178
180
|
export * from './migration-profile-registry.js';
|
|
179
181
|
export * from './profile-registry.js';
|