devflow-kit 2.4.0 → 3.0.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 +229 -0
- package/README.md +111 -18
- package/dist/agents/git.md +822 -0
- package/dist/cli/commands/agents.js +6 -1
- package/dist/cli/commands/ambient.js +160 -145
- package/dist/cli/commands/attribution-prompts.js +1 -1
- package/dist/cli/commands/capture.js +29 -55
- package/dist/cli/commands/compliance-prompts.js +1 -1
- package/dist/cli/commands/compliance.js +48 -55
- 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 +61 -27
- package/dist/cli/commands/init.js +649 -240
- package/dist/cli/commands/install-report.js +200 -0
- package/dist/cli/commands/knowledge/index.js +2 -2
- package/dist/cli/commands/knowledge/toggle.js +35 -37
- package/dist/cli/commands/learning.js +79 -57
- package/dist/cli/commands/legacy-hooks.js +11 -14
- package/dist/cli/commands/memory.js +134 -135
- package/dist/cli/commands/prompt-io.js +4 -4
- package/dist/cli/commands/proxy.js +23 -41
- package/dist/cli/commands/security.js +81 -29
- package/dist/cli/commands/skills.js +71 -7
- package/dist/cli/commands/tracker-prompts.js +145 -0
- package/dist/cli/commands/tracker.js +277 -0
- package/dist/cli/commands/uninstall.js +520 -169
- package/dist/cli.js +2 -0
- package/dist/commands/bug-analysis.md +58 -14
- package/dist/commands/code-review.md +110 -32
- package/dist/commands/debug.md +55 -11
- package/dist/commands/dynamic-build.md +344 -73
- package/dist/commands/dynamic-plan.md +77 -27
- package/dist/commands/dynamic-profile.md +25 -11
- package/dist/commands/dynamic-tickets.md +76 -15
- package/dist/commands/explore.md +37 -7
- package/dist/commands/implement.md +314 -62
- package/dist/commands/plan.md +146 -32
- package/dist/commands/release.md +64 -17
- package/dist/commands/research.md +34 -8
- package/dist/commands/resolve.md +196 -68
- package/dist/commands/self-review.md +45 -9
- package/dist/core/agent-models.js +55 -12
- package/dist/core/assets.js +58 -2
- package/dist/core/compliance-compose.js +27 -27
- package/dist/core/evidence-policy.js +363 -0
- package/dist/core/feature-config.js +200 -65
- package/dist/core/feature-switch.js +112 -0
- package/dist/core/flags.js +34 -6
- 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 +38 -10
- package/dist/core/mds-variants.js +798 -0
- package/dist/core/migrations.js +49 -23
- package/dist/core/model-discovery.js +12 -1
- package/dist/core/plugins.js +361 -12
- package/dist/core/project-paths.js +1 -18
- package/dist/core/proxy-log.js +8 -6
- package/dist/core/proxy-state.js +11 -8
- package/dist/core/reference-sweep.js +136 -0
- package/dist/core/same-location.js +25 -0
- package/dist/core/tracker.js +494 -0
- 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/decision-markers.md +19 -0
- package/dist/skills/git/references/learn-conventions.md +56 -0
- package/dist/skills/git/references/pr/check-ci-status.md +14 -0
- package/dist/skills/git/references/pr/check-merge-readiness.md +28 -0
- package/dist/skills/git/references/pr/ensure-pr-ready.md +24 -0
- package/dist/skills/git/references/pr/fetch-review-threads.md +22 -0
- package/dist/skills/git/references/pr/post-resolution-summary.md +40 -0
- package/dist/skills/git/references/pr/post-review-summary.md +42 -0
- package/dist/skills/git/references/pr/resolve-review-threads.md +35 -0
- package/dist/skills/git/references/pr/update-pr-evidence.md +14 -0
- package/dist/skills/git/references/pr/validate-branch.md +18 -0
- package/dist/skills/git/references/publication-gate.md +13 -0
- package/dist/skills/git/references/tracker/_mcp.md +153 -0
- package/dist/skills/git/references/tracker/github/associate-release.md +18 -0
- package/dist/skills/git/references/tracker/github/backlink-shipped-issues.md +40 -0
- package/dist/skills/git/references/tracker/github/create-release.md +11 -0
- package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +16 -0
- package/dist/skills/git/references/tracker/github/ensure-traceable-issue.md +69 -0
- package/dist/skills/git/references/tracker/github/fetch-issue.md +32 -0
- package/dist/skills/git/references/tracker/github/fetch-issues-batch.md +17 -0
- package/dist/skills/git/references/tracker/github/gather-release-evidence.md +19 -0
- package/dist/skills/git/references/tracker/github/manage-debt.md +101 -0
- package/dist/skills/git/references/tracker/github/post-wave-report.md +28 -0
- package/dist/skills/git/references/tracker/github/setup-task.md +26 -0
- package/dist/skills/git/references/tracker/jira/associate-release.md +18 -0
- package/dist/skills/git/references/tracker/jira/backlink-shipped-issues.md +49 -0
- package/dist/skills/git/references/tracker/jira/create-release.md +17 -0
- package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +22 -0
- package/dist/skills/git/references/tracker/jira/ensure-traceable-issue.md +53 -0
- package/dist/skills/git/references/tracker/jira/fetch-issue.md +14 -0
- package/dist/skills/git/references/tracker/jira/fetch-issues-batch.md +15 -0
- package/dist/skills/git/references/tracker/jira/gather-release-evidence.md +18 -0
- package/dist/skills/git/references/tracker/jira/manage-debt.md +37 -0
- package/dist/skills/git/references/tracker/jira/post-wave-report.md +33 -0
- package/dist/skills/git/references/tracker/jira/setup-task.md +31 -0
- package/dist/skills/git/references/tracker/linear/associate-release.md +18 -0
- package/dist/skills/git/references/tracker/linear/backlink-shipped-issues.md +53 -0
- package/dist/skills/git/references/tracker/linear/create-release.md +17 -0
- package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +22 -0
- package/dist/skills/git/references/tracker/linear/ensure-traceable-issue.md +53 -0
- package/dist/skills/git/references/tracker/linear/fetch-issue.md +14 -0
- package/dist/skills/git/references/tracker/linear/fetch-issues-batch.md +15 -0
- package/dist/skills/git/references/tracker/linear/gather-release-evidence.md +18 -0
- package/dist/skills/git/references/tracker/linear/manage-debt.md +37 -0
- package/dist/skills/git/references/tracker/linear/post-wave-report.md +33 -0
- package/dist/skills/git/references/tracker/linear/setup-task.md +32 -0
- package/dist/skills/git/references/trust-rule.md +7 -0
- 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 +1187 -32
- package/dist/targets/claude-code/legacy.js +5 -0
- package/dist/targets/claude-code/post-install.js +366 -151
- package/dist/targets/claude-code/tracker-install.js +134 -0
- package/package.json +8 -6
- package/src/assets/agents/code.md +45 -6
- package/src/assets/agents/design.md +2 -1
- package/src/assets/agents/git.mds +825 -0
- package/src/assets/agents/knowledge.md +3 -3
- package/src/assets/agents/learning.md +11 -0
- package/src/assets/agents/review.md +3 -1
- package/src/assets/agents/synthesize.md +1 -1
- package/src/assets/agents/test.md +16 -5
- package/src/assets/agents/tracker.md +474 -0
- package/src/assets/agents/validate.md +7 -5
- 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 +13 -11
- package/src/assets/commands/_partials/_evidence_policy.mds +30 -0
- 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 +22 -7
- package/src/assets/commands/_partials/_preamble.mds +2 -2
- package/src/assets/commands/_partials/_publication.mds +8 -2
- package/src/assets/commands/_partials/_settings.mds +28 -0
- package/src/assets/commands/_partials/_ticket_template.mds +3 -2
- package/src/assets/commands/_partials/_tracker.mds +18 -0
- package/src/assets/commands/_partials/_wave.mds +16 -10
- package/src/assets/commands/bug-analysis.mds +31 -19
- package/src/assets/commands/code-review.mds +67 -41
- package/src/assets/commands/debug.mds +13 -7
- package/src/assets/commands/dynamic-build.mds +274 -66
- package/src/assets/commands/dynamic-plan.mds +50 -23
- package/src/assets/commands/dynamic-profile.mds +24 -11
- package/src/assets/commands/dynamic-tickets.mds +63 -16
- package/src/assets/commands/explore.mds +4 -5
- package/src/assets/commands/implement.mds +234 -67
- package/src/assets/commands/plan.mds +91 -33
- package/src/assets/commands/release.md +64 -17
- package/src/assets/commands/research.mds +11 -9
- package/src/assets/commands/resolve.mds +150 -78
- package/src/assets/commands/self-review.mds +24 -25
- package/src/assets/mds/git/_pr.mds +331 -0
- package/src/assets/mds/git/_references.mds +135 -0
- package/src/assets/mds/tracker/_common.mds +156 -0
- package/src/assets/mds/tracker/_github.mds +472 -0
- package/src/assets/mds/tracker/_jira.mds +407 -0
- package/src/assets/mds/tracker/_linear.mds +449 -0
- package/src/assets/mds/tracker/_mcp.mds +305 -0
- package/src/assets/scripts/hooks/assets/orchestrator-charter.md +5 -8
- package/src/assets/scripts/hooks/background-memory-update +40 -19
- package/src/assets/scripts/hooks/capture-prompt +18 -8
- package/src/assets/scripts/hooks/capture-question +18 -8
- package/src/assets/scripts/hooks/capture-turn +27 -13
- 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 +236 -60
- package/src/assets/scripts/hooks/git-marker +48 -0
- package/src/assets/scripts/hooks/hook-log-init +3 -1
- package/src/assets/scripts/hooks/json-helper.cjs +228 -5
- package/src/assets/scripts/hooks/lib/project-paths.cjs +1 -20
- package/src/assets/scripts/hooks/log-paths +80 -0
- package/src/assets/scripts/hooks/memory-worker +22 -13
- package/src/assets/scripts/hooks/pre-compact-memory +44 -15
- package/src/assets/scripts/hooks/preamble +1 -4
- package/src/assets/scripts/hooks/queue-append +146 -28
- package/src/assets/scripts/hooks/resolve-project-root +101 -7
- package/src/assets/scripts/hooks/session-start-context +534 -20
- package/src/assets/scripts/hooks/session-start-memory +38 -15
- package/src/assets/scripts/lib/project-config.cjs +633 -0
- package/src/assets/scripts/pr-evidence.cjs +1961 -0
- package/src/assets/scripts/redact-secrets.cjs +490 -62
- package/src/assets/scripts/release-trace.cjs +1143 -0
- package/src/assets/scripts/resolve-evidence-policy.cjs +1145 -0
- package/src/assets/scripts/resolve-settings.cjs +1054 -0
- package/src/assets/scripts/verify-evidence.cjs +1822 -0
- package/src/assets/skills/compliance/SKILL.md +4 -2
- package/src/assets/skills/docs-framework/SKILL.md +11 -10
- 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/SKILL.md +8 -78
- package/src/assets/skills/git/references/github-api.md +179 -141
- package/src/assets/skills/git/references/patterns.md +11 -6
- package/src/assets/skills/review-methodology/SKILL.md +1 -1
- package/src/assets/skills/review-methodology/references/patterns.md +6 -61
- package/src/assets/skills/review-methodology/references/violations.md +14 -22
- 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
- package/src/assets/agents/git.md +0 -938
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file ledger-root.ts
|
|
3
|
+
*
|
|
4
|
+
* Where the learning ledger lives for a working directory — the TypeScript twin of
|
|
5
|
+
* `df_resolve_roots`' DF_LEDGER_ROOT in src/assets/scripts/hooks/resolve-project-root.
|
|
6
|
+
*
|
|
7
|
+
* D-LEDGER-MAIN-WORKTREE: the ledger is one per REPOSITORY, not per checkout. In a
|
|
8
|
+
* linked worktree the hooks queue and render into the main worktree's
|
|
9
|
+
* `.devflow/learning/`, so `devflow learning` and the HUD must read and clear that
|
|
10
|
+
* same directory — resolving the worktree's own toplevel (getGitRoot) would show an
|
|
11
|
+
* empty ledger and drain a queue nothing writes to. The rule, from ONE git call:
|
|
12
|
+
*
|
|
13
|
+
* git rev-parse --path-format=absolute --show-toplevel --git-common-dir
|
|
14
|
+
*
|
|
15
|
+
* - exactly two absolute lines, the common dir ends in `/.git`, `<main>/.devflow`
|
|
16
|
+
* is a directory and `<main>` is not HOME (physical paths, like the hooks'
|
|
17
|
+
* df_is_project_root) → `<main>`;
|
|
18
|
+
* - two absolute lines otherwise → the toplevel;
|
|
19
|
+
* - git before 2.31 echoes `--path-format=absolute` back as its own line → the
|
|
20
|
+
* toplevel it printed after it (the hooks fall back to the toplevel too);
|
|
21
|
+
* - git failed (not a work tree) → null: the caller keeps its non-git fallback;
|
|
22
|
+
* - any other output → getGitRoot(), the hooks' df_resolve_root fallback.
|
|
23
|
+
*
|
|
24
|
+
* Memory is NOT resolved here: working memory stays per checkout (getGitRoot).
|
|
25
|
+
* Parity with the shell helper is pinned by tests/core/ledger-root.test.ts, which
|
|
26
|
+
* runs df_resolve_roots on the same fixtures.
|
|
27
|
+
*/
|
|
28
|
+
import { execFile } from 'child_process';
|
|
29
|
+
import { promises as fs } from 'fs';
|
|
30
|
+
import * as os from 'os';
|
|
31
|
+
import * as path from 'path';
|
|
32
|
+
import { getGitRoot } from './git.js';
|
|
33
|
+
/** The one git call, as argv (no shell). */
|
|
34
|
+
const LEDGER_ROOT_GIT_ARGS = ['rev-parse', '--path-format=absolute', '--show-toplevel', '--git-common-dir'];
|
|
35
|
+
/** What git before 2.31 prints first: the flag it does not know, echoed back. */
|
|
36
|
+
const PATH_FORMAT_ECHO = '--path-format=absolute';
|
|
37
|
+
/** Classify the git call's stdout. Pure. */
|
|
38
|
+
export function parseLedgerRootOutput(stdout) {
|
|
39
|
+
const lines = stdout.replace(/\n$/, '').split('\n');
|
|
40
|
+
if (lines.length === 2 && lines.every(l => path.isAbsolute(l))) {
|
|
41
|
+
return { kind: 'roots', toplevel: lines[0], commonDir: lines[1] };
|
|
42
|
+
}
|
|
43
|
+
if (lines.length === 3 && lines[0] === PATH_FORMAT_ECHO && path.isAbsolute(lines[1])) {
|
|
44
|
+
return { kind: 'toplevel', toplevel: lines[1] };
|
|
45
|
+
}
|
|
46
|
+
return { kind: 'unrecognised' };
|
|
47
|
+
}
|
|
48
|
+
/** stdout of the one git call from `cwd`, or null when git failed. */
|
|
49
|
+
function runRevParse(cwd, timeoutMs) {
|
|
50
|
+
return new Promise((resolve) => {
|
|
51
|
+
execFile('git', LEDGER_ROOT_GIT_ARGS, { cwd, timeout: timeoutMs, encoding: 'utf-8' }, (err, stdout) => {
|
|
52
|
+
resolve(err ? null : stdout);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/** A path's physical location, or null when it cannot be resolved. */
|
|
57
|
+
async function physical(target) {
|
|
58
|
+
try {
|
|
59
|
+
return await fs.realpath(target);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Whether the main worktree `main` holds the ledger: it has a `.devflow/` directory
|
|
67
|
+
* and is not HOME. An unresolvable `main` is refused (the ledger stays in this
|
|
68
|
+
* checkout); an unresolvable HOME cannot equal it, so it refuses nothing — both as
|
|
69
|
+
* df_is_project_root decides.
|
|
70
|
+
*/
|
|
71
|
+
async function mainHoldsLedger(main, home) {
|
|
72
|
+
const stat = await fs.stat(path.join(main, '.devflow')).catch(() => null);
|
|
73
|
+
if (!stat?.isDirectory())
|
|
74
|
+
return false;
|
|
75
|
+
const [mainReal, homeReal] = await Promise.all([physical(main), physical(home)]);
|
|
76
|
+
return mainReal !== null && mainReal !== homeReal;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The learning ledger root for `cwd` — the main worktree or this checkout's
|
|
80
|
+
* toplevel — or null outside a git work tree.
|
|
81
|
+
*/
|
|
82
|
+
export async function getLedgerRoot(cwd = process.cwd(), options = {}) {
|
|
83
|
+
const stdout = await runRevParse(cwd, options.timeoutMs ?? 0);
|
|
84
|
+
if (stdout === null)
|
|
85
|
+
return null;
|
|
86
|
+
const parsed = parseLedgerRootOutput(stdout);
|
|
87
|
+
switch (parsed.kind) {
|
|
88
|
+
case 'toplevel':
|
|
89
|
+
return parsed.toplevel;
|
|
90
|
+
case 'unrecognised':
|
|
91
|
+
return getGitRoot(cwd);
|
|
92
|
+
case 'roots': {
|
|
93
|
+
if (!parsed.commonDir.endsWith('/.git'))
|
|
94
|
+
return parsed.toplevel;
|
|
95
|
+
const main = parsed.commonDir.slice(0, -'/.git'.length);
|
|
96
|
+
if (main && await mainHoldsLedger(main, options.home ?? os.homedir()))
|
|
97
|
+
return main;
|
|
98
|
+
return parsed.toplevel;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=ledger-root.js.map
|
package/dist/core/manifest.js
CHANGED
|
@@ -3,6 +3,7 @@ import * as path from 'path';
|
|
|
3
3
|
import { LEGACY_PLUGIN_NAMES, DELETED_PLUGIN_NAMES } from './plugins.js';
|
|
4
4
|
import { VIEW_MODES, migrateLegacyFlagsToRecord, sanitizeFlagsRecord, } from './flags.js';
|
|
5
5
|
import { normalizeComplianceFeature } from './compliance.js';
|
|
6
|
+
import { normalizeTrackerFeature } from './tracker.js';
|
|
6
7
|
import { writeFileAtomicExclusive } from './fs-atomic.js';
|
|
7
8
|
/**
|
|
8
9
|
* Parse features.flags across the three on-disk shapes; reports whether a heal is owed.
|
|
@@ -54,13 +55,14 @@ function parseManifestFlags(features, knownFlags) {
|
|
|
54
55
|
* Read and parse the manifest file. Returns null if missing or corrupt.
|
|
55
56
|
*
|
|
56
57
|
* Self-heals the following on-disk inconsistencies (applies ADR-014):
|
|
57
|
-
* - features.kb → features.knowledge rename
|
|
58
|
-
* - features.decisions → features.learning rename
|
|
58
|
+
* - features.kb → features.knowledge rename (both absent → true, D-FEATURES-ABSENT-ON)
|
|
59
|
+
* - features.decisions → features.learning rename (both absent → true, D-FEATURES-ABSENT-ON)
|
|
59
60
|
* - features.flags as string[] → FlagsRecord (via migrateLegacyFlagsToRecord)
|
|
60
61
|
* - features.viewMode folded into flags['view-mode'] and stripped from result
|
|
61
62
|
* - features.knownFlags stripped from result (folded into FlagsRecord key-presence)
|
|
62
63
|
* - features.proxy absent → false
|
|
63
64
|
* - features.compliance absent/malformed → {enabled:false, frameworks:[]}
|
|
65
|
+
* - features.tracker absent/malformed → {provider:'github'}
|
|
64
66
|
*
|
|
65
67
|
* D39: heal-write failure returns the migrated in-memory manifest (not null).
|
|
66
68
|
* The on-disk format remains unhealed; next read triggers another attempt.
|
|
@@ -73,7 +75,6 @@ export async function readManifest(devflowDir) {
|
|
|
73
75
|
const features = data.features;
|
|
74
76
|
if (!data.version ||
|
|
75
77
|
!Array.isArray(data.plugins) ||
|
|
76
|
-
!data.scope ||
|
|
77
78
|
typeof features !== 'object' ||
|
|
78
79
|
features === null ||
|
|
79
80
|
typeof features.ambient !== 'boolean' ||
|
|
@@ -82,15 +83,33 @@ export async function readManifest(devflowDir) {
|
|
|
82
83
|
typeof data.updatedAt !== 'string') {
|
|
83
84
|
return null;
|
|
84
85
|
}
|
|
85
|
-
//
|
|
86
|
+
// D-FEATURES-ABSENT-ON (a sub-decision of D-FEATURES-NARROW-ONLY,
|
|
87
|
+
// src/core/feature-switch.ts): knowledge and learning are machine-wide
|
|
88
|
+
// switches, and every runtime gate — queue_read_gates in the hooks,
|
|
89
|
+
// isMachineFeatureOn in the CLI, the knowledge write-back prose gate — reads
|
|
90
|
+
// an ABSENT key as ON. This reader must agree: init seeds from it and every
|
|
91
|
+
// syncManifestFeature toggle writes its result back, so a `false` default
|
|
92
|
+
// here would persist "off" for a feature the runtime is running — a plain
|
|
93
|
+
// re-init or `devflow hud --enable` on an older manifest silently switching
|
|
94
|
+
// it off machine-wide. Explicit booleans (and their legacy names) are kept
|
|
95
|
+
// as they are. memory needs no default: it is in the hard-null set above,
|
|
96
|
+
// so a manifest without it reads as no prior install and init seeds
|
|
97
|
+
// FEATURE_DEFAULTS.memory (true).
|
|
98
|
+
//
|
|
99
|
+
// Self-heal: rename features.kb → features.knowledge on disk.
|
|
100
|
+
// Coalesce: features.knowledge wins; fall back to features.kb; default ON.
|
|
101
|
+
// D-KNOWLEDGE-LEGACY-KB: isMachineFeatureOn applies this exact precedence,
|
|
102
|
+
// so the legacy key is honoured before the heal lands.
|
|
86
103
|
const knowledge = typeof features.knowledge === 'boolean' ? features.knowledge
|
|
87
104
|
: typeof features.kb === 'boolean' ? features.kb
|
|
88
|
-
:
|
|
89
|
-
// Self-heal: rename features.decisions → features.learning on disk
|
|
90
|
-
// Coalesce: features.learning wins; fall back to features.decisions; default
|
|
105
|
+
: true;
|
|
106
|
+
// Self-heal: rename features.decisions → features.learning on disk (ADR-011).
|
|
107
|
+
// Coalesce: features.learning wins; fall back to features.decisions; default ON.
|
|
108
|
+
// D-LEARNING-LEGACY-DECISIONS: isMachineFeatureOn and queue_read_gates apply
|
|
109
|
+
// this exact precedence, so the legacy key is honoured before the heal lands.
|
|
91
110
|
const learning = typeof features.learning === 'boolean' ? features.learning
|
|
92
111
|
: typeof features.decisions === 'boolean' ? features.decisions
|
|
93
|
-
:
|
|
112
|
+
: true;
|
|
94
113
|
// Self-heal: non-string-array or absent knownFlags/knownPlugins → undefined (never partial/garbage)
|
|
95
114
|
const asStringArray = (val) => Array.isArray(val) && val.every(e => typeof e === 'string')
|
|
96
115
|
? val
|
|
@@ -115,7 +134,8 @@ export async function readManifest(devflowDir) {
|
|
|
115
134
|
const manifest = {
|
|
116
135
|
version: data.version,
|
|
117
136
|
plugins: data.plugins,
|
|
118
|
-
|
|
137
|
+
// D-MANIFEST-SCOPE-PINNED: the on-disk value is not consulted.
|
|
138
|
+
scope: 'user',
|
|
119
139
|
knownPlugins,
|
|
120
140
|
features: {
|
|
121
141
|
ambient: features.ambient,
|
|
@@ -138,6 +158,12 @@ export async function readManifest(devflowDir) {
|
|
|
138
158
|
proxy: typeof features.proxy === 'boolean' ? features.proxy : false,
|
|
139
159
|
// Self-heal: absent/malformed compliance → {enabled:false, frameworks:[]}
|
|
140
160
|
compliance: normalizeComplianceFeature(features.compliance),
|
|
161
|
+
// Self-heal: absent/malformed/unknown tracker → {provider:'github'} (AC-3.21).
|
|
162
|
+
// Deliberately NOT in the hard-null set above — see the field's doc comment.
|
|
163
|
+
// Healing here is silent and emits no DEGRADED: that is the correct
|
|
164
|
+
// ADR-014 behaviour, and a different condition from a per-repo config
|
|
165
|
+
// value outside the domain (which does emit `unknown tracker provider`).
|
|
166
|
+
tracker: normalizeTrackerFeature(features.tracker),
|
|
141
167
|
},
|
|
142
168
|
installedAt: data.installedAt,
|
|
143
169
|
updatedAt: data.updatedAt,
|
|
@@ -168,7 +194,9 @@ export async function readManifest(devflowDir) {
|
|
|
168
194
|
export async function writeManifest(devflowDir, data) {
|
|
169
195
|
await fs.mkdir(devflowDir, { recursive: true });
|
|
170
196
|
const manifestPath = path.join(devflowDir, 'manifest.json');
|
|
171
|
-
|
|
197
|
+
// D-MANIFEST-SCOPE-PINNED: every write records 'user', whatever the caller holds.
|
|
198
|
+
const pinned = { ...data, scope: 'user' };
|
|
199
|
+
await writeFileAtomicExclusive(manifestPath, JSON.stringify(pinned, null, 2) + '\n');
|
|
172
200
|
}
|
|
173
201
|
/**
|
|
174
202
|
* Update a single feature field in the manifest. No-op when no manifest exists.
|