devflow-kit 2.5.0 → 3.0.1
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/CHANGELOG.md +82 -0
- package/README.md +44 -19
- package/dist/agents/git.md +13 -15
- package/dist/cli/commands/ambient.js +160 -145
- package/dist/cli/commands/capture.js +29 -55
- package/dist/cli/commands/compliance.js +32 -61
- package/dist/cli/commands/context.js +17 -32
- package/dist/cli/commands/debug.js +65 -26
- package/dist/cli/commands/flags.js +3 -3
- package/dist/cli/commands/hud.js +34 -10
- package/dist/cli/commands/init-seed.js +40 -4
- package/dist/cli/commands/init.js +249 -271
- package/dist/cli/commands/install-report.js +10 -15
- package/dist/cli/commands/knowledge/index.js +1 -1
- package/dist/cli/commands/knowledge/toggle.js +11 -3
- package/dist/cli/commands/learning.js +52 -37
- package/dist/cli/commands/legacy-hooks.js +11 -14
- package/dist/cli/commands/memory.js +67 -78
- package/dist/cli/commands/proxy.js +23 -41
- package/dist/cli/commands/security.js +5 -13
- package/dist/cli/commands/skills.js +21 -3
- package/dist/cli/commands/tracker.js +100 -228
- package/dist/cli/commands/uninstall.js +343 -138
- package/dist/commands/bug-analysis.md +38 -12
- package/dist/commands/code-review.md +70 -21
- package/dist/commands/debug.md +37 -7
- package/dist/commands/dynamic-build.md +66 -17
- package/dist/commands/dynamic-plan.md +19 -8
- package/dist/commands/dynamic-profile.md +24 -10
- package/dist/commands/dynamic-tickets.md +22 -11
- package/dist/commands/explore.md +37 -7
- package/dist/commands/implement.md +96 -32
- package/dist/commands/plan.md +62 -19
- package/dist/commands/release.md +2 -2
- package/dist/commands/research.md +34 -8
- package/dist/commands/resolve.md +65 -17
- package/dist/commands/self-review.md +45 -9
- package/dist/core/compliance-compose.js +27 -27
- package/dist/core/evidence-policy.js +240 -24
- package/dist/core/feature-config.js +94 -25
- package/dist/core/feature-switch.js +1 -1
- package/dist/core/flags.js +30 -2
- package/dist/core/fs-atomic.js +27 -0
- package/dist/core/hook-log-dirs.js +104 -0
- package/dist/core/learning-tuning-config.js +5 -3
- package/dist/core/ledger-root.js +102 -0
- package/dist/core/manifest.js +6 -4
- package/dist/core/mds-variants.js +34 -97
- package/dist/core/migrations.js +49 -23
- package/dist/core/plugins.js +5 -4
- package/dist/core/project-paths.js +0 -17
- package/dist/core/same-location.js +25 -0
- package/dist/core/tracker.js +226 -139
- package/dist/hud/components/config-counts.js +15 -4
- package/dist/hud/components/learning-counts.js +14 -0
- package/dist/hud/config.js +2 -1
- package/dist/hud/cost-history.js +2 -4
- package/dist/hud/git.js +52 -7
- package/dist/hud/index.js +7 -9
- package/dist/skills/git/references/pr/check-merge-readiness.md +1 -1
- package/dist/skills/git/references/pr/ensure-pr-ready.md +1 -1
- package/dist/skills/git/references/pr/update-pr-evidence.md +1 -1
- package/dist/skills/git/references/tracker/_mcp.md +1 -1
- package/dist/skills/git/references/tracker/github/backlink-shipped-issues.md +1 -1
- package/dist/skills/git/references/tracker/github/ensure-traceable-issue.md +1 -1
- package/dist/skills/git/references/tracker/github/gather-release-evidence.md +2 -2
- package/dist/skills/git/references/tracker/github/manage-debt.md +3 -3
- package/dist/skills/git/references/tracker/jira/backlink-shipped-issues.md +1 -1
- package/dist/skills/git/references/tracker/jira/ensure-traceable-issue.md +1 -1
- package/dist/skills/git/references/tracker/jira/gather-release-evidence.md +2 -2
- package/dist/skills/git/references/tracker/jira/manage-debt.md +1 -1
- package/dist/skills/git/references/tracker/jira/post-wave-report.md +1 -1
- package/dist/skills/git/references/tracker/jira/setup-task.md +1 -1
- package/dist/skills/git/references/tracker/linear/backlink-shipped-issues.md +1 -1
- package/dist/skills/git/references/tracker/linear/ensure-traceable-issue.md +1 -1
- package/dist/skills/git/references/tracker/linear/gather-release-evidence.md +2 -2
- package/dist/skills/git/references/tracker/linear/manage-debt.md +1 -1
- package/dist/skills/git/references/tracker/linear/post-wave-report.md +1 -1
- package/dist/skills/git/references/tracker/linear/setup-task.md +1 -1
- package/dist/targets/claude-code/claude-paths.js +59 -57
- package/dist/targets/claude-code/compliance-install.js +49 -65
- package/dist/targets/claude-code/hooks.js +108 -3
- package/dist/targets/claude-code/installer.js +30 -57
- package/dist/targets/claude-code/post-install.js +246 -139
- package/dist/targets/claude-code/tracker-install.js +38 -65
- package/package.json +5 -4
- package/src/assets/agents/code.md +4 -3
- package/src/assets/agents/design.md +1 -0
- package/src/assets/agents/git.mds +55 -57
- package/src/assets/agents/knowledge.md +2 -2
- package/src/assets/agents/review.md +3 -1
- package/src/assets/agents/tracker.md +37 -30
- package/src/assets/commands/_partials/_compliance.mds +19 -1
- package/src/assets/commands/_partials/_decisions.mds +15 -3
- package/src/assets/commands/_partials/_docs_root.mds +35 -0
- package/src/assets/commands/_partials/_engine.mds +2 -2
- package/src/assets/commands/_partials/_evidence_policy.mds +3 -3
- package/src/assets/commands/_partials/_factory.mds +1 -1
- package/src/assets/commands/_partials/_knowledge.mds +27 -9
- package/src/assets/commands/_partials/_plan_contract.mds +2 -2
- package/src/assets/commands/_partials/_preamble.mds +1 -1
- package/src/assets/commands/_partials/_publication.mds +6 -2
- package/src/assets/commands/_partials/_settings.mds +28 -0
- package/src/assets/commands/_partials/_ticket_template.mds +3 -3
- package/src/assets/commands/_partials/_tracker.mds +4 -4
- package/src/assets/commands/_partials/_wave.mds +4 -4
- package/src/assets/commands/bug-analysis.mds +19 -17
- package/src/assets/commands/code-review.mds +39 -33
- package/src/assets/commands/debug.mds +4 -5
- package/src/assets/commands/dynamic-build.mds +75 -53
- package/src/assets/commands/dynamic-plan.mds +20 -15
- package/src/assets/commands/dynamic-profile.mds +24 -11
- package/src/assets/commands/dynamic-tickets.mds +25 -20
- package/src/assets/commands/explore.mds +4 -5
- package/src/assets/commands/implement.mds +58 -45
- package/src/assets/commands/plan.mds +34 -29
- package/src/assets/commands/release.md +2 -2
- package/src/assets/commands/research.mds +11 -9
- package/src/assets/commands/resolve.mds +41 -39
- package/src/assets/commands/self-review.mds +24 -25
- package/src/assets/mds/git/_pr.mds +61 -61
- package/src/assets/mds/git/_references.mds +19 -19
- package/src/assets/mds/tracker/_common.mds +8 -8
- package/src/assets/mds/tracker/_github.mds +71 -71
- package/src/assets/mds/tracker/_jira.mds +74 -74
- package/src/assets/mds/tracker/_linear.mds +75 -75
- package/src/assets/mds/tracker/_mcp.mds +23 -17
- package/src/assets/scripts/hooks/background-memory-update +35 -19
- package/src/assets/scripts/hooks/capture-prompt +18 -12
- package/src/assets/scripts/hooks/capture-question +18 -12
- package/src/assets/scripts/hooks/capture-turn +27 -17
- package/src/assets/scripts/hooks/debug-trace +11 -6
- package/src/assets/scripts/hooks/ensure-devflow-init +33 -6
- package/src/assets/scripts/hooks/ensure-proxy +9 -8
- package/src/assets/scripts/hooks/ensure-root-gitignore +111 -36
- package/src/assets/scripts/hooks/git-marker +48 -0
- package/src/assets/scripts/hooks/json-helper.cjs +6 -1
- package/src/assets/scripts/hooks/lib/project-paths.cjs +0 -19
- package/src/assets/scripts/hooks/log-paths +80 -0
- package/src/assets/scripts/hooks/memory-worker +17 -15
- package/src/assets/scripts/hooks/pre-compact-memory +41 -16
- package/src/assets/scripts/hooks/queue-append +104 -30
- package/src/assets/scripts/hooks/resolve-project-root +101 -7
- package/src/assets/scripts/hooks/session-start-context +289 -122
- package/src/assets/scripts/hooks/session-start-memory +35 -16
- package/src/assets/scripts/lib/project-config.cjs +633 -0
- package/src/assets/scripts/resolve-evidence-policy.cjs +300 -220
- package/src/assets/scripts/resolve-settings.cjs +1054 -0
- package/src/assets/scripts/verify-evidence.cjs +1 -1
- package/src/assets/skills/compliance/SKILL.md +2 -2
- package/src/assets/skills/docs-framework/SKILL.md +6 -7
- package/src/assets/skills/docs-framework/references/patterns.md +10 -17
- package/src/assets/skills/gap-analysis/SKILL.md +2 -2
- package/src/assets/skills/git/references/github-api.md +9 -9
- package/src/assets/skills/git/references/patterns.md +1 -1
- package/src/assets/skills/worktree-support/SKILL.md +1 -1
- package/src/assets/skills/worktree-support/references/roots.md +29 -0
- package/src/targets/claude-code/templates/managed-settings.json +25 -9
|
@@ -24,7 +24,7 @@ import * as p from '@clack/prompts';
|
|
|
24
24
|
import color from 'picocolors';
|
|
25
25
|
import { readProxyState, writeProxyState, buildProxyState, buildRoutingConfigJson, proxyBaseUrl, proxyJsonExists, resolveProxyBin, DEFAULT_PROXY_PORT, } from '../../core/proxy-state.js';
|
|
26
26
|
import { syncManifestFeature, readManifest } from '../../core/manifest.js';
|
|
27
|
-
import {
|
|
27
|
+
import { writeSettingsFileAtomic } from '../../core/fs-atomic.js';
|
|
28
28
|
import { scrubChildEnv, openProxyLog, rotateProxyLogIfLarge } from '../../core/proxy-log.js';
|
|
29
29
|
import { inspectCodexAuth, classifyCodexAuthReadError } from '../../core/codex-auth-inspect.js';
|
|
30
30
|
import { stripAnsi } from '../../hud/colors.js';
|
|
@@ -32,6 +32,7 @@ import { reapplyAgentMapping, revertExternalAgents, countExternalMappedAgents, r
|
|
|
32
32
|
import { getExternalModelsCached, discoverExternalModels, } from '../../core/model-discovery.js';
|
|
33
33
|
import { modelCacheDir } from '../../core/cache.js';
|
|
34
34
|
import { getClaudeDirectory, getDevFlowDirectory, getHomeDirectory, } from '../../targets/claude-code/claude-paths.js';
|
|
35
|
+
import { devflowHookOwner, ensureHook, hasHook, removeHooks, runHookCommand, } from '../../targets/claude-code/hooks.js';
|
|
35
36
|
function Ok(value) {
|
|
36
37
|
return { ok: true, value };
|
|
37
38
|
}
|
|
@@ -39,8 +40,17 @@ function Err(error) {
|
|
|
39
40
|
return { ok: false, error };
|
|
40
41
|
}
|
|
41
42
|
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
42
|
-
/**
|
|
43
|
+
/** The run-hook marker of the ensure-proxy hook. */
|
|
43
44
|
const PROXY_HOOK_MARKER = 'ensure-proxy';
|
|
45
|
+
/**
|
|
46
|
+
* D-EXACT-HOOK-OWNER: the ensure-proxy hook is devflow's only when its command ends
|
|
47
|
+
* in `/scripts/hooks/run-hook ensure-proxy` (hooks.ts), under any directory — the one
|
|
48
|
+
* form it has ever been registered in. A user's hook that merely mentions the word
|
|
49
|
+
* is theirs.
|
|
50
|
+
*/
|
|
51
|
+
const isProxyHook = devflowHookOwner([PROXY_HOOK_MARKER]);
|
|
52
|
+
/** The events the ensure-proxy hook is registered on. */
|
|
53
|
+
const PROXY_HOOK_EVENTS = ['SessionStart', 'UserPromptSubmit'];
|
|
44
54
|
/** Pattern matching our relay's ANTHROPIC_BASE_URL value. */
|
|
45
55
|
const OUR_BASE_URL_PATTERN = /^http:\/\/127\.0\.0\.1:\d+$/;
|
|
46
56
|
/** Timeout for individual TCP connect probes and HTTP health checks (ms). */
|
|
@@ -166,34 +176,6 @@ function _stripProxyEnvFromObject(settings, managedPort) {
|
|
|
166
176
|
delete s.env;
|
|
167
177
|
return removedUrl || hadWindowVar; // OR the locals — never compose with || inline (PF-015)
|
|
168
178
|
}
|
|
169
|
-
/** Internal: add ensure-proxy hook to one event. Returns true when added. */
|
|
170
|
-
function _ensureProxyHook(settings, eventName, hookCmd) {
|
|
171
|
-
const existing = settings.hooks?.[eventName];
|
|
172
|
-
if (existing?.some((m) => m.hooks.some((h) => h.command.includes(PROXY_HOOK_MARKER)))) {
|
|
173
|
-
return false;
|
|
174
|
-
}
|
|
175
|
-
settings.hooks ??= {};
|
|
176
|
-
settings.hooks[eventName] ??= [];
|
|
177
|
-
const entry = {
|
|
178
|
-
hooks: [{ type: 'command', command: hookCmd, timeout: 15 }],
|
|
179
|
-
};
|
|
180
|
-
settings.hooks[eventName].push(entry);
|
|
181
|
-
return true;
|
|
182
|
-
}
|
|
183
|
-
/** Internal: remove ensure-proxy hooks from one event. Returns true when removed. */
|
|
184
|
-
function _filterProxyHooks(settings, eventName) {
|
|
185
|
-
if (!settings.hooks?.[eventName])
|
|
186
|
-
return false;
|
|
187
|
-
const before = settings.hooks[eventName].length;
|
|
188
|
-
settings.hooks[eventName] = settings.hooks[eventName].filter((m) => !m.hooks.some((h) => h.command.includes(PROXY_HOOK_MARKER)));
|
|
189
|
-
if (settings.hooks[eventName].length === before)
|
|
190
|
-
return false;
|
|
191
|
-
if (settings.hooks[eventName].length === 0)
|
|
192
|
-
delete settings.hooks[eventName];
|
|
193
|
-
if (Object.keys(settings.hooks).length === 0)
|
|
194
|
-
delete settings.hooks;
|
|
195
|
-
return true;
|
|
196
|
-
}
|
|
197
179
|
// ─── Pure env functions (exported for testing and cross-module reuse) ─────────
|
|
198
180
|
/**
|
|
199
181
|
* Apply ANTHROPIC_BASE_URL=http://127.0.0.1:<port> to settings JSON.
|
|
@@ -251,20 +233,21 @@ export function readProxyEnvState(settingsJson, port) {
|
|
|
251
233
|
* Mutates settings in place. Returns true when any hook was added.
|
|
252
234
|
*/
|
|
253
235
|
export function addProxyHooks(settings, devflowDir) {
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
const addedPrompt =
|
|
236
|
+
const command = runHookCommand(devflowDir, PROXY_HOOK_MARKER);
|
|
237
|
+
// Evaluate each event into its own local — never short-circuit (PF-015).
|
|
238
|
+
const [addedSession, addedPrompt] = PROXY_HOOK_EVENTS.map((event) => ensureHook(settings, event, isProxyHook, { hooks: [{ type: 'command', command, timeout: 15 }] }));
|
|
257
239
|
return addedSession || addedPrompt;
|
|
258
240
|
}
|
|
259
241
|
/**
|
|
260
242
|
* Remove ensure-proxy hooks from all events.
|
|
261
243
|
* Idempotent — no-op when hooks are not present.
|
|
262
|
-
*
|
|
244
|
+
* Removes single hooks, so the other hooks of a shared matcher group stay in place
|
|
245
|
+
* (D-EXACT-HOOK-OWNER). Cleans empty arrays/objects.
|
|
263
246
|
* Mutates settings in place. Returns true when any hook was removed.
|
|
264
247
|
*/
|
|
265
248
|
export function removeProxyHooks(settings) {
|
|
266
|
-
|
|
267
|
-
const removedPrompt =
|
|
249
|
+
// Evaluate each event into its own local — never short-circuit (PF-015).
|
|
250
|
+
const [removedSession, removedPrompt] = PROXY_HOOK_EVENTS.map((event) => removeHooks(settings, event, isProxyHook));
|
|
268
251
|
return removedSession || removedPrompt;
|
|
269
252
|
}
|
|
270
253
|
/**
|
|
@@ -319,8 +302,7 @@ export function applyProxyTeardownToSettings(settings, managedPort) {
|
|
|
319
302
|
*/
|
|
320
303
|
export function hasProxyHooks(input) {
|
|
321
304
|
const settings = typeof input === 'string' ? JSON.parse(input) : input;
|
|
322
|
-
|
|
323
|
-
return check('SessionStart') || check('UserPromptSubmit');
|
|
305
|
+
return PROXY_HOOK_EVENTS.some((event) => hasHook(settings, event, isProxyHook));
|
|
324
306
|
}
|
|
325
307
|
// ─── Health-check identity helper ────────────────────────────────────────────
|
|
326
308
|
/**
|
|
@@ -747,7 +729,7 @@ export async function runPostSpawnVerification(binPath, configPath, logPath, spa
|
|
|
747
729
|
* Perform the single atomic settings.json pass for enable:
|
|
748
730
|
* strip old hooks + env, then apply new hooks + env in one write.
|
|
749
731
|
*
|
|
750
|
-
* The
|
|
732
|
+
* The writeSettingsFileAtomic call is guarded — ENOSPC/EACCES returns Err
|
|
751
733
|
* instead of crashing with an unhandled rejection.
|
|
752
734
|
*
|
|
753
735
|
* Returns Ok(undefined) on success, Err(reason) on hard failure.
|
|
@@ -777,7 +759,7 @@ async function applyEnableSettingsPass(settingsPath, devflowDir, port) {
|
|
|
777
759
|
addProxyHooks(parsedSettings, devflowDir);
|
|
778
760
|
_applyProxyEnvToObject(parsedSettings, port);
|
|
779
761
|
try {
|
|
780
|
-
await
|
|
762
|
+
await writeSettingsFileAtomic(settingsPath, JSON.stringify(parsedSettings, null, 2) + '\n');
|
|
781
763
|
}
|
|
782
764
|
catch (err) {
|
|
783
765
|
return Err(`Could not write settings.json: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -1465,7 +1447,7 @@ async function runDisable() {
|
|
|
1465
1447
|
if (changed) {
|
|
1466
1448
|
// Guard ENOSPC/EACCES — unhandled rejection leaves proxy in partial state
|
|
1467
1449
|
try {
|
|
1468
|
-
await
|
|
1450
|
+
await writeSettingsFileAtomic(settingsPath, JSON.stringify(parsedSettings, null, 2) + '\n');
|
|
1469
1451
|
}
|
|
1470
1452
|
catch (err) {
|
|
1471
1453
|
p.log.error(`Could not write settings.json: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -4,8 +4,8 @@ import * as p from '@clack/prompts';
|
|
|
4
4
|
import color from 'picocolors';
|
|
5
5
|
import { getClaudeDirectory, getDevFlowDirectory, getManagedSettingsPath } from '../../targets/claude-code/claude-paths.js';
|
|
6
6
|
import { readManifest, syncManifestFeature } from '../../core/manifest.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { applyUserSecurityDenyList, stripUserDenyList, detectDenyState, DEVFLOW_HISTORICAL_DENY, removeManagedSettings, installManagedSettings, loadTemplateDenyEntries, stripUserSecurityDenyList, } from '../../targets/claude-code/post-install.js';
|
|
8
|
+
import { writeSettingsFileAtomic } from '../../core/fs-atomic.js';
|
|
9
9
|
import { promises as fs } from 'fs';
|
|
10
10
|
import { getPackageRoot } from '../../core/paths.js';
|
|
11
11
|
// ─── Pure helpers ─────────────────────────────────────────────────────────────
|
|
@@ -183,16 +183,8 @@ export const securityCommand = new Command('security')
|
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
185
|
else {
|
|
186
|
-
// User mode: merge into ~/.claude/settings.json
|
|
187
|
-
|
|
188
|
-
try {
|
|
189
|
-
existing = await fs.readFile(userSettingsPath, 'utf-8');
|
|
190
|
-
}
|
|
191
|
-
catch {
|
|
192
|
-
existing = '{}';
|
|
193
|
-
}
|
|
194
|
-
const merged = mergeDenyList(existing, templateDeny);
|
|
195
|
-
await writeFileAtomicExclusive(userSettingsPath, merged);
|
|
186
|
+
// User mode: merge into ~/.claude/settings.json, converging retired entries
|
|
187
|
+
const merged = await applyUserSecurityDenyList(userSettingsPath, templateDeny);
|
|
196
188
|
const count = countDenyEntries(merged);
|
|
197
189
|
p.log.success(`Security deny list applied to user settings (${count} entries)`);
|
|
198
190
|
p.log.info(` Location: ${color.dim(userSettingsPath)}`);
|
|
@@ -214,7 +206,7 @@ export const securityCommand = new Command('security')
|
|
|
214
206
|
}
|
|
215
207
|
const { json: stripped, removed } = stripUserDenyList(userSettingsJson, DEVFLOW_HISTORICAL_DENY);
|
|
216
208
|
if (removed.length > 0) {
|
|
217
|
-
await
|
|
209
|
+
await writeSettingsFileAtomic(userSettingsPath, stripped);
|
|
218
210
|
p.log.success(`Removed ${removed.length} entries from user settings:`);
|
|
219
211
|
for (const entry of removed) {
|
|
220
212
|
p.log.info(` ${color.dim(entry)}`);
|
|
@@ -25,6 +25,23 @@ async function dirExists(dirPath) {
|
|
|
25
25
|
function getShadowDir(devflowDir, skillName) {
|
|
26
26
|
return path.join(devflowDir, 'skills', unprefixSkillName(skillName));
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* The directory a new shadow of `bareName` is copied from.
|
|
30
|
+
*
|
|
31
|
+
* D-COMPLIANCE-SHADOW-SOURCE (mirrors seedRuleShadow's Tier-1 skip in rules.ts):
|
|
32
|
+
* a FEATURE_OWNED skill always seeds from the shipped SOURCE. Its installed copy
|
|
33
|
+
* is composed — every `${DEVFLOW_COMPLIANCE_*}` token already replaced with the
|
|
34
|
+
* frameworks of that moment — and a token-free shadow passes through composition
|
|
35
|
+
* byte-identical (C1), so seeding from it would freeze that stamp: a later
|
|
36
|
+
* `devflow compliance --set` could never re-stamp the skill. Every other skill
|
|
37
|
+
* seeds from its installed copy when there is one, else from source.
|
|
38
|
+
*/
|
|
39
|
+
export function shadowSeedDir(bareName, installedDir) {
|
|
40
|
+
const sourceDir = path.join(skillsDir(), bareName);
|
|
41
|
+
if (FEATURE_OWNED_SKILLS.includes(bareName))
|
|
42
|
+
return sourceDir;
|
|
43
|
+
return installedDir ?? sourceDir;
|
|
44
|
+
}
|
|
28
45
|
/**
|
|
29
46
|
* Check if a skill has a shadow (personal override).
|
|
30
47
|
*/
|
|
@@ -40,13 +57,14 @@ export async function hasShadow(skillName, devflowDir) {
|
|
|
40
57
|
* names one plugin out of several that would each do (D-ALL-OWNERS).
|
|
41
58
|
* FEATURE_OWNED skills have no plugin owner at all and say so, because telling
|
|
42
59
|
* a user to select a plugin for `compliance` would send them looking for one
|
|
43
|
-
* that does not exist.
|
|
60
|
+
* that does not exist. Compliance is installed on every machine
|
|
61
|
+
* (D-COMPLIANCE-INSTALL-ALWAYS), so its feature is the whole answer.
|
|
44
62
|
*/
|
|
45
63
|
function describeOwners(bareName, owners) {
|
|
46
64
|
const declarers = owners ?? skillOwners(bareName);
|
|
47
65
|
if (declarers.length === 0) {
|
|
48
66
|
return FEATURE_OWNED_SKILLS.includes(bareName)
|
|
49
|
-
? '
|
|
67
|
+
? 'the compliance feature (every install)'
|
|
50
68
|
: 'no plugin';
|
|
51
69
|
}
|
|
52
70
|
return declarers.join(' or ');
|
|
@@ -99,7 +117,7 @@ export const skillsCommand = new Command('skills')
|
|
|
99
117
|
// The shadow is seeded from the shipped source instead and reported as
|
|
100
118
|
// DORMANT — it exists, it is preserved by every future install, and it
|
|
101
119
|
// applies to nothing until the plugin that uses it is selected.
|
|
102
|
-
const seedDir = installed ? installedSkillDir :
|
|
120
|
+
const seedDir = shadowSeedDir(bareName, installed ? installedSkillDir : null);
|
|
103
121
|
if (!await dirExists(seedDir)) {
|
|
104
122
|
p.log.error(`No source for ${bareName} — reinstall devflow, then try again.`);
|
|
105
123
|
process.exit(1);
|