devflow-kit 3.8.0 → 3.10.0
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 +231 -0
- package/README.md +6 -6
- package/dist/agents/code.md +10 -10
- package/dist/agents/fix.md +7 -7
- package/dist/agents/git.md +2 -2
- package/dist/agents/harden.md +7 -6
- package/dist/agents/refactor.md +6 -6
- package/dist/agents/skim.md +1 -1
- package/dist/agents/triage.md +7 -0
- package/dist/cli/commands/ambient.js +10 -2
- package/dist/cli/commands/compliance-prompts.js +9 -4
- package/dist/cli/commands/compliance.js +171 -24
- package/dist/cli/commands/curation.js +79 -23
- package/dist/cli/commands/gate-level-prompts.js +39 -23
- package/dist/cli/commands/gates.js +6 -7
- package/dist/cli/commands/init.js +150 -145
- package/dist/cli/commands/install-report.js +34 -0
- package/dist/cli/commands/legacy-sweep.js +64 -0
- package/dist/cli/commands/memory.js +59 -12
- package/dist/cli/commands/proxy.js +6 -1
- package/dist/cli/commands/rules.js +29 -12
- package/dist/cli/commands/skills.js +42 -9
- package/dist/cli/commands/tracker.js +9 -3
- package/dist/cli/commands/uninstall.js +354 -60
- package/dist/commands/bug-analysis.md +71 -122
- package/dist/commands/code-review.md +11 -11
- package/dist/commands/debug.md +2 -2
- package/dist/commands/dynamic-build.md +25 -25
- package/dist/commands/dynamic-plan.md +2 -2
- package/dist/commands/dynamic-profile.md +2 -2
- package/dist/commands/dynamic-tickets.md +2 -2
- package/dist/commands/explore.md +2 -2
- package/dist/commands/implement.md +48 -34
- package/dist/commands/plan.md +2 -2
- package/dist/commands/release.md +3 -3
- package/dist/commands/research.md +2 -2
- package/dist/commands/resolve.md +50 -46
- package/dist/commands/self-review.md +10 -9
- package/dist/compliance-off/agents/git.md +120 -0
- package/dist/compliance-off/agents/triage.md +180 -0
- package/dist/compliance-off/commands/bug-analysis.md +398 -0
- package/dist/compliance-off/commands/code-review.md +520 -0
- package/dist/compliance-off/commands/dynamic-build.md +1251 -0
- package/dist/compliance-off/commands/dynamic-tickets.md +676 -0
- package/dist/compliance-off/commands/implement.md +736 -0
- package/dist/compliance-off/commands/plan.md +671 -0
- package/dist/compliance-off/commands/release.md +309 -0
- package/dist/compliance-off/commands/resolve.md +742 -0
- package/dist/compliance-off/skills/git/references/decision-markers.md +17 -0
- package/dist/compliance-off/skills/git/references/learn-conventions.md +80 -0
- package/dist/compliance-off/skills/git/references/pr/check-ci-status.md +33 -0
- package/dist/compliance-off/skills/git/references/pr/check-merge-readiness.md +49 -0
- package/dist/compliance-off/skills/git/references/pr/fetch-review-threads.md +52 -0
- package/dist/compliance-off/skills/git/references/pr/validate-branch.md +47 -0
- package/dist/compliance-off/skills/git/references/tracker/_contract.md +33 -0
- package/dist/compliance-off/skills/git/references/tracker/_mcp.md +153 -0
- package/dist/compliance-off/skills/git/references/tracker/github/create-release.md +35 -0
- package/dist/compliance-off/skills/git/references/tracker/github/ensure-pr-ready.md +100 -0
- package/dist/compliance-off/skills/git/references/tracker/github/ensure-traceable-issue.md +74 -0
- package/dist/compliance-off/skills/git/references/tracker/github/fetch-issue.md +69 -0
- package/dist/compliance-off/skills/git/references/tracker/github/fetch-issues-batch.md +65 -0
- package/dist/compliance-off/skills/git/references/tracker/github/gather-release-evidence.md +48 -0
- package/dist/compliance-off/skills/git/references/tracker/github/setup-task.md +77 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/create-release.md +35 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/ensure-pr-ready.md +100 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/ensure-traceable-issue.md +61 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/fetch-issue.md +51 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/fetch-issues-batch.md +63 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/gather-release-evidence.md +47 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/setup-task.md +82 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/create-release.md +35 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/ensure-pr-ready.md +100 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/ensure-traceable-issue.md +61 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/fetch-issue.md +51 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/fetch-issues-batch.md +63 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/gather-release-evidence.md +47 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/setup-task.md +83 -0
- package/dist/compliance-off/skills/git/references/trust-rule.md +7 -0
- package/dist/core/agent-models.js +19 -4
- package/dist/core/area-pause-notice.js +44 -0
- package/dist/core/assets.js +126 -17
- package/dist/core/compliance-off-files.js +27 -0
- package/dist/core/curation-move-skip.js +4 -5
- package/dist/core/curation-queue-cleanup.js +6 -5
- package/dist/core/curation-store.js +1 -0
- package/dist/core/curation-variants.js +460 -112
- package/dist/core/evidence-policy.js +10 -8
- package/dist/core/flags.js +2 -2
- package/dist/core/installed-variants.js +63 -0
- package/dist/core/manifest.js +48 -5
- package/dist/core/mds-variants.js +700 -3
- package/dist/core/orphan-sweep.js +11 -2
- package/dist/core/plugins.js +69 -12
- package/dist/core/tracked-areas.js +138 -14
- package/dist/curation-compliance-off/agents/triage.md +176 -0
- package/dist/curation-compliance-off/commands/bug-analysis.md +349 -0
- package/dist/curation-compliance-off/commands/code-review.md +481 -0
- package/dist/curation-compliance-off/commands/dynamic-build.md +1211 -0
- package/dist/curation-compliance-off/commands/dynamic-tickets.md +634 -0
- package/dist/curation-compliance-off/commands/implement.md +689 -0
- package/dist/curation-compliance-off/commands/plan.md +631 -0
- package/dist/curation-compliance-off/commands/release.md +279 -0
- package/dist/curation-compliance-off/commands/resolve.md +692 -0
- package/dist/curation-off/agents/code.md +10 -10
- package/dist/curation-off/agents/fix.md +7 -7
- package/dist/curation-off/agents/harden.md +7 -6
- package/dist/curation-off/agents/refactor.md +6 -6
- package/dist/curation-off/agents/triage.md +7 -0
- package/dist/curation-off/commands/bug-analysis.md +69 -119
- package/dist/curation-off/commands/code-review.md +11 -11
- package/dist/curation-off/commands/debug.md +2 -2
- package/dist/curation-off/commands/dynamic-build.md +25 -25
- package/dist/curation-off/commands/explore.md +2 -2
- package/dist/curation-off/commands/implement.md +48 -34
- package/dist/curation-off/commands/plan.md +2 -2
- package/dist/curation-off/commands/release.md +1 -1
- package/dist/curation-off/commands/resolve.md +50 -46
- package/dist/curation-off/commands/self-review.md +10 -9
- package/dist/hud/components/curation-counts.js +27 -0
- package/dist/skills/git/references/pr/post-resolution-summary.md +12 -11
- package/dist/skills/git/references/pr/post-review-summary.md +12 -11
- package/dist/skills/git/references/pr/resolve-review-threads.md +1 -1
- package/dist/skills/git/references/pr/update-pr-evidence.md +2 -2
- package/dist/skills/git/references/publication-gate.md +6 -7
- package/dist/skills/git/references/tracker/github/manage-debt.md +6 -2
- package/dist/skills/git/references/tracker/jira/manage-debt.md +6 -2
- package/dist/skills/git/references/tracker/linear/manage-debt.md +6 -2
- package/dist/targets/claude-code/behavior-install.js +23 -9
- package/dist/targets/claude-code/charter-render.js +374 -0
- package/dist/targets/claude-code/compliance-install.js +32 -12
- package/dist/targets/claude-code/compliance-off-files.js +245 -0
- package/dist/targets/claude-code/curation-install.js +570 -100
- package/dist/targets/claude-code/installer.js +467 -62
- package/dist/targets/claude-code/language-stamp.js +6 -0
- package/dist/targets/claude-code/linked-folder.js +182 -0
- package/dist/targets/claude-code/reference-converge.js +118 -0
- package/dist/targets/claude-code/tracker-install.js +21 -8
- package/dist/targets/claude-code/tracker-servers.js +20 -6
- package/dist/targets/claude-code/workflow-folder-install.js +231 -0
- package/dist/variant-axes.json +109 -0
- package/package.json +1 -1
- package/src/assets/agents/_partials/_code.mds +6 -6
- package/src/assets/agents/code.mds +4 -4
- package/src/assets/agents/evaluate.md +7 -13
- package/src/assets/agents/fix.mds +1 -1
- package/src/assets/agents/git.mds +34 -2
- package/src/assets/agents/harden.mds +7 -6
- package/src/assets/agents/skim.mds +1 -1
- package/src/assets/agents/test.md +21 -12
- package/src/assets/agents/triage.mds +9 -0
- package/src/assets/agents/validate.md +27 -34
- package/src/assets/commands/_partials/_compliance.mds +5 -3
- package/src/assets/commands/_partials/_decisions.mds +10 -8
- package/src/assets/commands/_partials/_engine.mds +9 -8
- package/src/assets/commands/_partials/_publication.mds +10 -1
- package/src/assets/commands/_partials/_settings.mds +2 -2
- package/src/assets/commands/bug-analysis.mds +80 -126
- package/src/assets/commands/code-review.mds +52 -9
- package/src/assets/commands/dynamic-build.mds +109 -15
- package/src/assets/commands/dynamic-tickets.mds +13 -0
- package/src/assets/commands/implement.mds +145 -33
- package/src/assets/commands/plan.mds +19 -0
- package/src/assets/commands/release.mds +50 -1
- package/src/assets/commands/resolve.mds +229 -44
- package/src/assets/commands/self-review.mds +8 -7
- package/src/assets/mds/git/_ops.mds +29 -1
- package/src/assets/mds/git/_ops_pr.mds +20 -10
- package/src/assets/mds/git/_ops_steps.mds +27 -0
- package/src/assets/mds/git/_pr.mds +15 -15
- package/src/assets/mds/git/_references.mds +12 -7
- package/src/assets/mds/tracker/_common.mds +4 -0
- package/src/assets/mds/tracker/_github.mds +43 -4
- package/src/assets/mds/tracker/_jira.mds +44 -4
- package/src/assets/mds/tracker/_linear.mds +44 -4
- package/src/assets/rules/quality.md +2 -0
- package/src/assets/scripts/ci-wait.cjs +493 -118
- package/src/assets/scripts/hooks/assets/implement-installed +1 -0
- package/src/assets/scripts/hooks/assets/orchestrator-charter.md +13 -11
- package/src/assets/scripts/hooks/background-memory-update +79 -1
- package/src/assets/scripts/hooks/json-helper.cjs +44 -2
- package/src/assets/scripts/hooks/lib/curation-store.cjs +82 -20
- package/src/assets/scripts/hooks/lib/render-decisions.cjs +9 -1
- package/src/assets/scripts/hooks/lib/tracked-areas.cjs +226 -33
- package/src/assets/scripts/hooks/memory-permission +10 -2
- package/src/assets/scripts/hooks/memory-worker +11 -0
- package/src/assets/scripts/hooks/pre-compact-memory +11 -0
- package/src/assets/scripts/hooks/preamble +18 -8
- package/src/assets/scripts/hooks/queue-append +218 -1
- package/src/assets/scripts/hooks/session-start-context +89 -37
- package/src/assets/scripts/hooks/session-start-memory +39 -0
- package/src/assets/scripts/hooks/session-start-orchestrator +4 -2
- package/src/assets/scripts/pr-evidence.cjs +46 -4
- package/src/assets/scripts/resolve-settings.cjs +244 -30
- package/src/assets/scripts/verify-evidence.cjs +708 -124
- package/src/assets/skills/agent-references/SKILL.md +7 -1
- package/src/assets/skills/agent-references/references/commands/implement-levels.md +6 -4
- package/src/assets/skills/agent-references/references/commands/implement-revalidate.md +3 -3
- package/src/assets/skills/agent-references/references/commands/plan-levels.md +1 -1
- package/src/assets/skills/agent-references/references/commands/resolve-levels.md +3 -2
- package/src/assets/skills/agent-references/references/synthesize/bug-analysis.md +6 -2
- package/src/assets/skills/agent-references/references/synthesize/review.md +4 -4
- package/src/assets/skills/agent-references/references/triage/severity-tiers.md +43 -0
- package/src/assets/skills/agent-references/references/validate/passed-alone.md +14 -0
- package/src/assets/skills/docs-framework/SKILL.md +5 -2
- package/src/assets/skills/git/SKILL.md +3 -3
- package/src/assets/skills/git/references/github-api.md +2 -139
- package/src/assets/skills/git/references/github-posting.md +158 -0
- package/src/assets/skills/review-methodology/SKILL.md +1 -1
- package/src/assets/skills/review-methodology/references/patterns.md +1 -1
- package/src/assets/skills/review-methodology/references/report-template.md +1 -2
- package/src/assets/skills/testing/SKILL.md +2 -4
|
@@ -131,8 +131,8 @@ export function loadEvidencePolicyModule(dir = scriptsDir()) {
|
|
|
131
131
|
}
|
|
132
132
|
/**
|
|
133
133
|
* Load the settings resolver from `dir` (default: the package's own scripts
|
|
134
|
-
* directory) and shape-check its surface. A `resolveSettings()` call makes
|
|
135
|
-
* local `git`
|
|
134
|
+
* directory) and shape-check its surface. A `resolveSettings()` call makes a few
|
|
135
|
+
* local `git` calls and no network call (D-SETTINGS-LOCAL-ONLY).
|
|
136
136
|
*/
|
|
137
137
|
export function loadSettingsModule(dir = scriptsDir()) {
|
|
138
138
|
return loadScript(join(dir, SETTINGS_SCRIPT_NAME), SETTINGS_MODULE_SURFACE);
|
|
@@ -238,18 +238,20 @@ export function settingsSourceFile(source) {
|
|
|
238
238
|
* layer narrows it — `disabled (.devflow/project.json)` — and null otherwise, so a
|
|
239
239
|
* `--status` whose machine switch alone decides prints exactly what it always has
|
|
240
240
|
* (D-FEATURES-NARROW-ONLY). A repository file that exists but is unreadable fails
|
|
241
|
-
* every field closed but the compliance lens
|
|
242
|
-
* labelled with that file —
|
|
243
|
-
* `disabled (.devflow/project.json is unreadable)` — since commands act on it.
|
|
244
|
-
*
|
|
245
|
-
*
|
|
241
|
+
* every field closed but the compliance lens and the memory and curation switches, and
|
|
242
|
+
* the one switch that closed off (knowledge) is labelled with that file —
|
|
243
|
+
* `disabled (.devflow/project.json is unreadable)` — since commands act on it. The
|
|
244
|
+
* memory and curation switches of such a resolution are the machine's, narrowed by what
|
|
245
|
+
* git tracks (a narrowing that carries source `machine`): no file turned them off, so
|
|
246
|
+
* they get no label. Any other failure (the resolver failed to load, or git could not
|
|
247
|
+
* answer) yields null: it knows nothing about this repository.
|
|
246
248
|
*/
|
|
247
249
|
export function narrowedSwitchLabel(loaded, opts, feature) {
|
|
248
250
|
if (!loaded.ok)
|
|
249
251
|
return null;
|
|
250
252
|
const settings = loaded.value.resolveSettings(opts);
|
|
251
253
|
if (!settings.ok) {
|
|
252
|
-
if (settings.unreadable === null || settings.switches[feature].on)
|
|
254
|
+
if (settings.unreadable === null || feature !== 'knowledge' || settings.switches[feature].on)
|
|
253
255
|
return null;
|
|
254
256
|
return `disabled (${settingsSourceFile(settings.unreadable)} is unreadable)`;
|
|
255
257
|
}
|
package/dist/core/flags.js
CHANGED
|
@@ -441,8 +441,8 @@ export const FLAG_REGISTRY = [
|
|
|
441
441
|
{
|
|
442
442
|
// D-FOREGROUND-RUN: every agent runs builds and tests in the foreground under an explicit
|
|
443
443
|
// Bash `timeout` whose ceiling is Claude Code's 600000 ms, or this variable when set. A
|
|
444
|
-
//
|
|
445
|
-
//
|
|
444
|
+
// run that passes its timeout is waited for and read, so raising the ceiling is optional:
|
|
445
|
+
// it only lets a long run end inside one call.
|
|
446
446
|
// The env name was confirmed against Claude Code 2.1.294 (docs/reference/claude-code-flags-probe.md):
|
|
447
447
|
// the binary reads BASH_MAX_TIMEOUT_MS, ignores a non-positive or NaN value, and takes the
|
|
448
448
|
// larger of it and the default timeout. Neutral by default (undefined → manifest null →
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The install record of the prompt variants (#648, AC-29 and AC-31).
|
|
3
|
+
*
|
|
4
|
+
* After a converge that finished clean, the manifest records which variant of each axis the
|
|
5
|
+
* installed prompts hold: `installedVariants: { curation, compliance }`. The record is the only
|
|
6
|
+
* way to tell what is installed without reading every prompt, and it answers one question the
|
|
7
|
+
* switches alone cannot: does this machine still carry posting steps from before the switch moved?
|
|
8
|
+
*
|
|
9
|
+
* The manifest reader carries the field raw, so a hand-edited or newer-version value reaches this
|
|
10
|
+
* module unchecked. {@link readInstalledVariants} is the one parse: anything but two booleans is
|
|
11
|
+
* unknown, and an absent field is unknown. Nothing heals an unknown record. Pure, with no I/O.
|
|
12
|
+
*/
|
|
13
|
+
/** The record as the manifest carries it, or null when it is absent or is not two booleans (unknown). */
|
|
14
|
+
export function readInstalledVariants(raw) {
|
|
15
|
+
if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
|
|
16
|
+
return null;
|
|
17
|
+
const { curation, compliance } = raw;
|
|
18
|
+
if (typeof curation !== 'boolean' || typeof compliance !== 'boolean')
|
|
19
|
+
return null;
|
|
20
|
+
return { curation, compliance };
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The record to write for a converge, or null when none is owed (AC-29). Only a converge that
|
|
24
|
+
* finished clean records the switches the prompts were converged onto. Any other converge writes
|
|
25
|
+
* nothing, so the field is left out and reads as unknown: it names `devflow init`, and the posting
|
|
26
|
+
* notice stays due. Pure; the result is a fresh object.
|
|
27
|
+
*/
|
|
28
|
+
export function installRecordFor(converged, switches) {
|
|
29
|
+
return converged ? { curation: switches.curation, compliance: switches.compliance } : null;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Whether the posting steps are installed, from the record and the machine's compliance switch.
|
|
33
|
+
*
|
|
34
|
+
* `installed` and `not installed` are the two settled states: the record agrees with the switch, and
|
|
35
|
+
* the on variant carries the posting steps while the off variant carries none. A record that
|
|
36
|
+
* disagrees with the switch is `mismatch`, and a record that is absent or unreadable is `unknown`;
|
|
37
|
+
* both name the remedy.
|
|
38
|
+
*/
|
|
39
|
+
export function postingStatus(installed, complianceEnabled) {
|
|
40
|
+
if (installed === null)
|
|
41
|
+
return 'unknown (run devflow init)';
|
|
42
|
+
if (installed.compliance !== complianceEnabled)
|
|
43
|
+
return 'mismatch (run devflow init)';
|
|
44
|
+
return complianceEnabled ? 'installed' : 'not installed';
|
|
45
|
+
}
|
|
46
|
+
/** What `devflow init` prints, once, when the installed prompts move from posting steps to none. */
|
|
47
|
+
export const POSTING_OFF_NOTICE = 'Compliance is off on this machine, so devflow installed no step that posts test-plan evidence, ' +
|
|
48
|
+
'review or resolution summaries, backlog entries, review-thread replies, wave reports, plan artifacts ' +
|
|
49
|
+
'or release back-links to GitHub or a tracker. Results stay in local files under .devflow/docs/. ' +
|
|
50
|
+
'To install these steps, run `devflow compliance --enable`.';
|
|
51
|
+
/**
|
|
52
|
+
* Whether init owes the posting notice: compliance is off and the record does not already say the
|
|
53
|
+
* installed prompts carry no posting step. A record that is absent or unreadable is unknown, and
|
|
54
|
+
* unknown counts as posting, so a machine from before the record existed hears the notice once.
|
|
55
|
+
* The caller also requires a clean converge and a written record, so the notice and the record
|
|
56
|
+
* move together and the next init finds the record and stays quiet.
|
|
57
|
+
*/
|
|
58
|
+
export function postingNoticeDue(installed, complianceEnabled) {
|
|
59
|
+
if (complianceEnabled)
|
|
60
|
+
return false;
|
|
61
|
+
return installed === null || installed.compliance;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=installed-variants.js.map
|
package/dist/core/manifest.js
CHANGED
|
@@ -210,6 +210,9 @@ export async function readManifest(devflowDir, opts) {
|
|
|
210
210
|
},
|
|
211
211
|
installedAt: data.installedAt,
|
|
212
212
|
updatedAt: data.updatedAt,
|
|
213
|
+
// The install record of the prompt variants, raw (see the field's doc comment). Last, where
|
|
214
|
+
// the writer that records it puts it, so a read and a write never move the key.
|
|
215
|
+
...(Object.hasOwn(data, 'installedVariants') ? { installedVariants: data.installedVariants } : {}),
|
|
213
216
|
};
|
|
214
217
|
if (needsHeal) {
|
|
215
218
|
// D39: wrap the heal-write in its own try/catch so a write failure does NOT
|
|
@@ -293,7 +296,8 @@ export async function syncManifestFeature(devflowDir, key, value) {
|
|
|
293
296
|
* re-init install it again. Going through readManifest()/writeManifest() instead
|
|
294
297
|
* would drop every key ManifestData does not model (one a newer devflow wrote,
|
|
295
298
|
* say) and persist that reader's unrelated heals as a side effect of a removal.
|
|
296
|
-
* Entries that are not strings are neither matched nor dropped.
|
|
299
|
+
* Entries that are not strings are neither matched nor dropped. A legacy name matches its current plugin
|
|
300
|
+
* ({@link doomedEntryTest}).
|
|
297
301
|
*/
|
|
298
302
|
export function withoutManifestPlugins(rawManifest, names, now) {
|
|
299
303
|
if (typeof rawManifest !== 'object' || rawManifest === null || Array.isArray(rawManifest))
|
|
@@ -301,12 +305,25 @@ export function withoutManifestPlugins(rawManifest, names, now) {
|
|
|
301
305
|
const record = rawManifest;
|
|
302
306
|
if (!Array.isArray(record.plugins))
|
|
303
307
|
return null;
|
|
304
|
-
const
|
|
305
|
-
const kept = record.plugins.filter(entry => !(typeof entry === 'string' &&
|
|
308
|
+
const isDoomed = doomedEntryTest(names);
|
|
309
|
+
const kept = record.plugins.filter(entry => !(typeof entry === 'string' && isDoomed(entry)));
|
|
306
310
|
if (kept.length === record.plugins.length)
|
|
307
311
|
return null;
|
|
308
312
|
return { ...record, plugins: kept, updatedAt: now };
|
|
309
313
|
}
|
|
314
|
+
/**
|
|
315
|
+
* Whether a recorded plugin name is one of `names`, a legacy name counting as its current plugin on both sides.
|
|
316
|
+
* Removing `devflow-plan` therefore also drops a record that still holds `devflow-specify`. Any other name,
|
|
317
|
+
* a name the registry does not know included, matches only itself.
|
|
318
|
+
*
|
|
319
|
+
* The record is file content, so only a key LEGACY_PLUGIN_NAMES owns maps; one it inherits from Object,
|
|
320
|
+
* such as `constructor`, is an ordinary name.
|
|
321
|
+
*/
|
|
322
|
+
function doomedEntryTest(names) {
|
|
323
|
+
const current = (name) => (Object.hasOwn(LEGACY_PLUGIN_NAMES, name) ? LEGACY_PLUGIN_NAMES[name] : name);
|
|
324
|
+
const doomed = new Set(names.map(current));
|
|
325
|
+
return entry => doomed.has(current(entry));
|
|
326
|
+
}
|
|
310
327
|
/**
|
|
311
328
|
* D-UNINSTALL-DROPS-PLUGIN: record a selective uninstall in `<devflowDir>/manifest.json`.
|
|
312
329
|
*
|
|
@@ -339,9 +356,35 @@ export async function removeManifestPlugins(devflowDir, names) {
|
|
|
339
356
|
catch (error) {
|
|
340
357
|
return { ok: false, error: error instanceof Error ? error.message : String(error) };
|
|
341
358
|
}
|
|
342
|
-
const
|
|
359
|
+
const isDoomed = doomedEntryTest(names);
|
|
343
360
|
const before = raw.plugins;
|
|
344
|
-
return { ok: true, removed: before.filter((entry) => typeof entry === 'string' &&
|
|
361
|
+
return { ok: true, removed: before.filter((entry) => typeof entry === 'string' && isDoomed(entry)) };
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* The plugin names `<devflowDir>/manifest.json` records as installed, or null when there is no usable record.
|
|
365
|
+
* Read only: unlike {@link readManifest} it never heals, never takes the manifest lock and writes nothing, so
|
|
366
|
+
* the file stays byte-identical. That is the property a selective uninstall needs. Its caller works from the
|
|
367
|
+
* record as `removeManifestPlugins` does, and a heal would rewrite a manifest the uninstall did not mean to
|
|
368
|
+
* touch (and write through a link in a legacy local install).
|
|
369
|
+
*
|
|
370
|
+
* A record is a manifest {@link readManifest} would accept: valid JSON that holds every required field.
|
|
371
|
+
* Anything else is null, never an empty list, so a caller can tell "nothing recorded" from "nothing
|
|
372
|
+
* installed". Entries that are not strings are skipped.
|
|
373
|
+
*/
|
|
374
|
+
export async function readManifestPlugins(devflowDir) {
|
|
375
|
+
let raw;
|
|
376
|
+
try {
|
|
377
|
+
raw = JSON.parse(await fs.readFile(path.join(devflowDir, 'manifest.json'), 'utf-8'));
|
|
378
|
+
}
|
|
379
|
+
catch {
|
|
380
|
+
return null;
|
|
381
|
+
}
|
|
382
|
+
if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
|
|
383
|
+
return null;
|
|
384
|
+
const record = raw;
|
|
385
|
+
if (!hasRequiredManifestFields(record))
|
|
386
|
+
return null;
|
|
387
|
+
return record.plugins.filter((entry) => typeof entry === 'string');
|
|
345
388
|
}
|
|
346
389
|
/**
|
|
347
390
|
* Merge new plugins into existing plugin list (union, no duplicates).
|