devflow-kit 3.4.0 → 3.5.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 +29 -0
- package/README.md +8 -4
- package/dist/agents/code-edit.md +133 -0
- package/dist/agents/code-fix.md +165 -0
- package/dist/agents/code.md +39 -182
- package/dist/agents/design.md +0 -1
- package/dist/agents/git.md +31 -693
- package/dist/agents/knowledge.md +8 -2
- package/dist/agents/research.md +6 -0
- package/dist/agents/review.md +0 -4
- package/dist/agents/scrutinize.md +3 -0
- package/dist/agents/skim.md +4 -0
- package/dist/agents/triage.md +8 -1
- package/dist/cli/commands/behavior-prompts.js +77 -0
- package/dist/cli/commands/behavior.js +123 -0
- package/dist/cli/commands/flags.js +8 -2
- package/dist/cli/commands/init-seed.js +7 -3
- package/dist/cli/commands/init.js +72 -5
- package/dist/cli/commands/rules.js +16 -0
- package/dist/cli/commands/tracker.js +112 -15
- package/dist/cli.js +2 -0
- package/dist/commands/bug-analysis.md +5 -5
- package/dist/commands/code-review.md +14 -9
- package/dist/commands/debug.md +25 -4
- package/dist/commands/dynamic-build.md +28 -38
- package/dist/commands/dynamic-plan.md +11 -9
- package/dist/commands/dynamic-profile.md +3 -3
- package/dist/commands/dynamic-tickets.md +12 -10
- package/dist/commands/explore.md +3 -3
- package/dist/commands/implement.md +91 -125
- package/dist/commands/plan.md +15 -8
- package/dist/commands/release.md +3 -2
- package/dist/commands/research.md +16 -9
- package/dist/commands/resolve.md +20 -15
- package/dist/commands/self-review.md +2 -2
- package/dist/core/agent-frontmatter.js +101 -0
- package/dist/core/compliance-compose.js +6 -4
- package/dist/core/feature-switch.js +23 -2
- package/dist/core/flags.js +111 -0
- package/dist/core/manifest.js +11 -3
- package/dist/core/mds-variants.js +68 -26
- package/dist/core/plugins.js +42 -65
- package/dist/core/project-paths.js +0 -4
- package/dist/core/proxy-log.js +1 -1
- package/dist/core/proxy-state.js +1 -1
- package/dist/core/tracker.js +120 -2
- package/dist/learning-off/agents/code-edit.md +129 -0
- package/dist/learning-off/agents/code-fix.md +161 -0
- package/dist/learning-off/agents/code.md +37 -180
- package/dist/learning-off/agents/design.md +0 -1
- package/dist/learning-off/agents/knowledge.md +8 -2
- package/dist/learning-off/agents/research.md +6 -0
- package/dist/learning-off/agents/review.md +0 -4
- package/dist/learning-off/agents/scrutinize.md +3 -0
- package/dist/learning-off/agents/skim.md +4 -0
- package/dist/learning-off/agents/triage.md +8 -1
- package/dist/learning-off/commands/bug-analysis.md +3 -3
- package/dist/learning-off/commands/code-review.md +12 -7
- package/dist/learning-off/commands/debug.md +22 -2
- package/dist/learning-off/commands/dynamic-build.md +27 -37
- package/dist/learning-off/commands/dynamic-plan.md +10 -8
- package/dist/learning-off/commands/dynamic-profile.md +2 -2
- package/dist/learning-off/commands/dynamic-tickets.md +11 -9
- package/dist/learning-off/commands/explore.md +1 -1
- package/dist/learning-off/commands/implement.md +89 -123
- package/dist/learning-off/commands/plan.md +13 -6
- package/dist/learning-off/commands/release.md +3 -2
- package/dist/learning-off/commands/research.md +14 -7
- package/dist/learning-off/commands/resolve.md +18 -13
- package/dist/skills/git/references/learn-conventions.md +27 -3
- package/dist/skills/git/references/pr/check-ci-status.md +19 -0
- package/dist/skills/git/references/pr/check-merge-readiness.md +19 -0
- package/dist/skills/git/references/pr/fetch-review-threads.md +30 -0
- package/dist/skills/git/references/pr/post-resolution-summary.md +18 -0
- package/dist/skills/git/references/pr/post-review-summary.md +20 -0
- package/dist/skills/git/references/pr/resolve-review-threads.md +28 -4
- package/dist/skills/git/references/pr/update-pr-evidence.md +13 -0
- package/dist/skills/git/references/pr/validate-branch.md +26 -0
- package/dist/skills/git/references/tracker/github/associate-release.md +24 -0
- package/dist/skills/git/references/tracker/github/backlink-shipped-issues.md +31 -1
- package/dist/skills/git/references/tracker/github/create-release.md +30 -1
- package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +89 -2
- package/dist/skills/git/references/tracker/github/ensure-traceable-issue.md +16 -1
- package/dist/skills/git/references/tracker/github/fetch-issue.md +36 -1
- package/dist/skills/git/references/tracker/github/fetch-issues-batch.md +47 -1
- package/dist/skills/git/references/tracker/github/gather-release-evidence.md +25 -0
- package/dist/skills/git/references/tracker/github/manage-debt.md +21 -1
- package/dist/skills/git/references/tracker/github/post-wave-report.md +15 -1
- package/dist/skills/git/references/tracker/github/setup-task.md +41 -1
- package/dist/skills/git/references/tracker/jira/associate-release.md +24 -0
- package/dist/skills/git/references/tracker/jira/backlink-shipped-issues.md +31 -1
- package/dist/skills/git/references/tracker/jira/create-release.md +30 -1
- package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +89 -2
- package/dist/skills/git/references/tracker/jira/ensure-traceable-issue.md +16 -1
- package/dist/skills/git/references/tracker/jira/fetch-issue.md +36 -1
- package/dist/skills/git/references/tracker/jira/fetch-issues-batch.md +47 -1
- package/dist/skills/git/references/tracker/jira/gather-release-evidence.md +25 -0
- package/dist/skills/git/references/tracker/jira/manage-debt.md +21 -1
- package/dist/skills/git/references/tracker/jira/post-wave-report.md +15 -1
- package/dist/skills/git/references/tracker/jira/setup-task.md +41 -1
- package/dist/skills/git/references/tracker/linear/associate-release.md +24 -0
- package/dist/skills/git/references/tracker/linear/backlink-shipped-issues.md +31 -1
- package/dist/skills/git/references/tracker/linear/create-release.md +30 -1
- package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +89 -2
- package/dist/skills/git/references/tracker/linear/ensure-traceable-issue.md +16 -1
- package/dist/skills/git/references/tracker/linear/fetch-issue.md +36 -1
- package/dist/skills/git/references/tracker/linear/fetch-issues-batch.md +47 -1
- package/dist/skills/git/references/tracker/linear/gather-release-evidence.md +25 -0
- package/dist/skills/git/references/tracker/linear/manage-debt.md +21 -1
- package/dist/skills/git/references/tracker/linear/post-wave-report.md +15 -1
- package/dist/skills/git/references/tracker/linear/setup-task.md +41 -1
- package/dist/targets/claude-code/agent-type-owner.js +164 -0
- package/dist/targets/claude-code/behavior-install.js +111 -0
- package/dist/targets/claude-code/installer.js +69 -2
- package/dist/targets/claude-code/learning-install.js +9 -1
- package/dist/targets/claude-code/tracker-install.js +33 -16
- package/dist/targets/claude-code/tracker-servers.js +107 -0
- package/package.json +4 -3
- package/src/assets/agents/_partials/_code.mds +109 -0
- package/src/assets/agents/code-edit.mds +81 -0
- package/src/assets/agents/code-fix.mds +113 -0
- package/src/assets/agents/code.mds +18 -222
- package/src/assets/agents/design.mds +0 -1
- package/src/assets/agents/evaluate.md +7 -1
- package/src/assets/agents/explore.md +58 -0
- package/src/assets/agents/git.mds +31 -693
- package/src/assets/agents/knowledge.mds +8 -2
- package/src/assets/agents/learning.md +19 -69
- package/src/assets/agents/research.mds +6 -0
- package/src/assets/agents/review.mds +0 -4
- package/src/assets/agents/scrutinize.mds +3 -0
- package/src/assets/agents/simplify.md +3 -0
- package/src/assets/agents/skim.mds +4 -0
- package/src/assets/agents/synthesize.md +26 -352
- package/src/assets/agents/test.md +8 -0
- package/src/assets/agents/tracker.md +20 -7
- package/src/assets/agents/triage.mds +8 -1
- package/src/assets/agents/validate.md +5 -0
- package/src/assets/commands/_partials/_compliance.mds +36 -0
- package/src/assets/commands/_partials/_decisions.mds +2 -2
- package/src/assets/commands/_partials/_engine.mds +8 -8
- package/src/assets/commands/_partials/_preamble.mds +3 -3
- package/src/assets/commands/_partials/_roster.mds +4 -3
- package/src/assets/commands/_partials/_wave.mds +2 -2
- package/src/assets/commands/bug-analysis.mds +3 -3
- package/src/assets/commands/code-review.mds +11 -8
- package/src/assets/commands/debug.mds +24 -2
- package/src/assets/commands/dynamic-build.mds +14 -25
- package/src/assets/commands/dynamic-plan.mds +4 -3
- package/src/assets/commands/dynamic-tickets.mds +5 -4
- package/src/assets/commands/explore.mds +1 -1
- package/src/assets/commands/implement.mds +89 -125
- package/src/assets/commands/plan.mds +12 -7
- package/src/assets/commands/release.mds +3 -2
- package/src/assets/commands/research.mds +14 -7
- package/src/assets/commands/resolve.mds +17 -14
- package/src/assets/mds/.mdsroot +4 -0
- package/src/assets/mds/git/_ops.mds +383 -0
- package/src/assets/mds/git/_ops_pr.mds +201 -0
- package/src/assets/mds/git/_ops_steps.mds +147 -0
- package/src/assets/mds/git/_pr.mds +39 -44
- package/src/assets/mds/git/_references.mds +6 -3
- package/src/assets/mds/tracker/_common.mds +5 -5
- package/src/assets/mds/tracker/_contract.mds +4 -3
- package/src/assets/mds/tracker/_github.mds +60 -14
- package/src/assets/mds/tracker/_jira.mds +60 -14
- package/src/assets/mds/tracker/_linear.mds +60 -14
- package/src/assets/mds/tracker/_steps.mds +10 -9
- package/src/assets/rules/behavior.md +6 -0
- package/src/assets/scripts/hooks/assets/orchestrator-charter.md +2 -1
- package/src/assets/scripts/hooks/lib/project-paths.cjs +0 -6
- package/src/assets/skills/agent-references/SKILL.md +33 -0
- package/src/assets/skills/agent-references/references/learning/maintain.md +71 -0
- package/src/assets/skills/agent-references/references/synthesize/bug-analysis.md +71 -0
- package/src/assets/skills/agent-references/references/synthesize/design.md +36 -0
- package/src/assets/skills/agent-references/references/synthesize/exploration.md +38 -0
- package/src/assets/skills/agent-references/references/synthesize/planning.md +60 -0
- package/src/assets/skills/agent-references/references/synthesize/research.md +61 -0
- package/src/assets/skills/agent-references/references/synthesize/review.md +76 -0
- package/src/assets/skills/compliance/SKILL.md +1 -1
- package/src/assets/skills/docs-framework/SKILL.md +80 -83
- package/src/assets/skills/docs-framework/references/patterns.md +14 -25
- package/src/assets/skills/docs-framework/references/violations.md +7 -7
- package/src/assets/skills/gap-analysis/SKILL.md +0 -16
- package/src/assets/skills/gap-analysis/references/compliance.md +19 -0
- package/dist/skills/git/references/pr/ensure-pr-ready.md +0 -24
|
@@ -271,32 +271,38 @@ export const TRACKER_OPS = [
|
|
|
271
271
|
*/
|
|
272
272
|
export const TRACKER_GITHUB_OPS = TRACKER_OPS;
|
|
273
273
|
/**
|
|
274
|
-
* The
|
|
274
|
+
* The 8 PR/review operations whose references are generated once, for every
|
|
275
275
|
* provider, under `pr/`.
|
|
276
276
|
*
|
|
277
277
|
* A PR-HOST roster, not a tracker roster, and the distinction is the whole
|
|
278
278
|
* reason this list exists separately from {@link TRACKER_OPS}: pull requests, PR
|
|
279
279
|
* reviews and PR checks stay on GitHub under every issue-tracker provider, so
|
|
280
|
-
* these
|
|
281
|
-
* them under `tracker/github/` would make a jira user's PR mechanics read
|
|
282
|
-
* their tracker's, and fanning them across the three provider directories
|
|
283
|
-
* ship three identical trees.
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
*
|
|
292
|
-
*
|
|
280
|
+
* these operations are the SAME file whatever `TRACKER_PROVIDER` resolves to.
|
|
281
|
+
* Filing them under `tracker/github/` would make a jira user's PR mechanics read
|
|
282
|
+
* as their tracker's, and fanning them across the three provider directories
|
|
283
|
+
* would ship three identical trees.
|
|
284
|
+
*
|
|
285
|
+
* D-OP-ONE-REF. Each file is the WHOLE operation: its contract (description,
|
|
286
|
+
* `**Input:**`, degradation notes, `**Output:**` template, written once in
|
|
287
|
+
* `src/assets/mds/git/_ops.mds`) and then its steps. The operation loads this one
|
|
288
|
+
* file and no other operation reference.
|
|
289
|
+
*
|
|
290
|
+
* `ensure-pr-ready` is deliberately NOT a member. It is a tracker operation: step
|
|
291
|
+
* 4b, the issue-number lookup and the link line it renders, is a tracker fact and
|
|
292
|
+
* differs per provider, so the operation is one file per provider under
|
|
293
|
+
* `tracker/{provider}/ensure-pr-ready.md`. That file carries the PR skeleton
|
|
294
|
+
* (branch/commit/push, create, retitle, and step 4b's open-PR lookup and body edit)
|
|
295
|
+
* as well, written once in `_ops.mds` and expanded into all three, so the PR-host
|
|
296
|
+
* half is the same bytes under every provider and the operation still loads one
|
|
297
|
+
* file.
|
|
298
|
+
*
|
|
299
|
+
* 8 entries, exactly {@link MIN_VARIANT_PAIRS}, which is a floor and not a
|
|
293
300
|
* target: a shorter roster makes every parity assertion over it vacuous (GAP-42)
|
|
294
|
-
* and `expandVariants` refuses the build, so the roster can grow
|
|
295
|
-
*
|
|
296
|
-
*
|
|
301
|
+
* and `expandVariants` refuses the build, so the roster can grow but never drop
|
|
302
|
+
* below 8. `update-pr-evidence` (#363) is the newest member: it edits the PR body
|
|
303
|
+
* and comments on the PR, both GitHub whatever the tracker is.
|
|
297
304
|
*/
|
|
298
305
|
export const PR_HOST_OPS = [
|
|
299
|
-
'ensure-pr-ready',
|
|
300
306
|
'validate-branch',
|
|
301
307
|
'post-review-summary',
|
|
302
308
|
'check-ci-status',
|
|
@@ -354,6 +360,44 @@ export const GIT_CROSS_CUTTING_DOCS = [
|
|
|
354
360
|
'publication-gate',
|
|
355
361
|
'trust-rule',
|
|
356
362
|
];
|
|
363
|
+
/**
|
|
364
|
+
* The Git operations whose one operation reference is a cross-cutting document
|
|
365
|
+
* rather than a per-op file in `pr/` or `tracker/{provider}/` (D-OP-ONE-REF).
|
|
366
|
+
*
|
|
367
|
+
* `learn-conventions` is the only one: it has no PR-host half and no provider half,
|
|
368
|
+
* so its reference is the named document {@link GIT_CROSS_CUTTING_DOCS} already emits
|
|
369
|
+
* at the references root. Its contract is compiled into that document like every
|
|
370
|
+
* other operation's (D-OP-CONTRACT-ONCE).
|
|
371
|
+
*/
|
|
372
|
+
export const DOC_BACKED_OPS = ['learn-conventions'];
|
|
373
|
+
/**
|
|
374
|
+
* Every operation the Git agent routes, derived from the three rosters that emit its
|
|
375
|
+
* reference — never retyped. Each one loads exactly one operation reference
|
|
376
|
+
* ({@link operationReferenceRel}).
|
|
377
|
+
*/
|
|
378
|
+
export const GIT_OPERATIONS = [...PR_HOST_OPS, ...TRACKER_OPS, ...DOC_BACKED_OPS];
|
|
379
|
+
/**
|
|
380
|
+
* The skill-relative path (under `references/`) of the one reference an operation
|
|
381
|
+
* loads, or `null` for a name that is not a Git operation.
|
|
382
|
+
*
|
|
383
|
+
* D-OP-ONE-REF. A PR-host operation is `pr/{op}.md`, the same file under every
|
|
384
|
+
* provider; a tracker operation is `tracker/{provider}/{op}.md` for the resolved
|
|
385
|
+
* provider; a doc-backed operation is its named document. The Git agent's
|
|
386
|
+
* `## Loading the mechanics` table states these paths in prose, and
|
|
387
|
+
* `tests/tracker/reference-reachability.test.ts` holds the table to this function.
|
|
388
|
+
*
|
|
389
|
+
* Total and pure: an unknown operation is `null`, never a throw. `ensure-pr-ready` is
|
|
390
|
+
* a tracker operation, so it resolves per provider even though its PR half is shared.
|
|
391
|
+
*/
|
|
392
|
+
export function operationReferenceRel(op, provider) {
|
|
393
|
+
if (TRACKER_OPS.includes(op))
|
|
394
|
+
return `${TRACKER_DESTINATION_ROOT}/${provider}/${op}.md`;
|
|
395
|
+
if (PR_HOST_OPS.includes(op))
|
|
396
|
+
return `${PR_HOST_DESTINATION_ROOT}/${op}.md`;
|
|
397
|
+
if (DOC_BACKED_OPS.includes(op))
|
|
398
|
+
return `${op}.md`;
|
|
399
|
+
return null;
|
|
400
|
+
}
|
|
357
401
|
/**
|
|
358
402
|
* Every reference module the build knows about — a closed registry, read the
|
|
359
403
|
* same way ALLOWED_OUTPUT_DIRS is read.
|
|
@@ -378,9 +422,9 @@ export const GIT_CROSS_CUTTING_DOCS = [
|
|
|
378
422
|
* that used to sit in the always-loaded Git agent, where every spawn paid for
|
|
379
423
|
* them although most spawns run a PR-host operation that never touches the
|
|
380
424
|
* issue tracker. A spawn now reads the file once, only when it runs a tracker
|
|
381
|
-
* operation, before its first tracker step. The agent's
|
|
382
|
-
*
|
|
383
|
-
*
|
|
425
|
+
* operation, before its first tracker step. The agent's `## Loading the mechanics`
|
|
426
|
+
* section is the one line that names it; it keeps the one-reference rule and the
|
|
427
|
+
* table naming every non-tracker operation's reference, which a PR-only spawn
|
|
384
428
|
* needs and which this file cannot instruct a spawn to load. It is ungated for
|
|
385
429
|
* the reason the registry's other provider-independent files are: every install
|
|
386
430
|
* carries every provider, GitHub included, so no registered provider is the
|
|
@@ -389,11 +433,9 @@ export const GIT_CROSS_CUTTING_DOCS = [
|
|
|
389
433
|
* The budget clause: the file is a per-SPAWN term of each tracker row (GitHub,
|
|
390
434
|
* Jira, Linear), charged the way the tool-call contract is (`contractTerm` in
|
|
391
435
|
* tests/tracker/budget-model.ts) and added in `providerLoadedSet`. It is not part
|
|
392
|
-
* of `ownLoadForProvider`, of the PR-host row or of the per-operation
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
* contract included, is priced through the tracker rows, where it is already a
|
|
396
|
-
* candidate.
|
|
436
|
+
* of `ownLoadForProvider`, of the PR-host row or of the per-operation load cap
|
|
437
|
+
* (D-OP-LOAD-CAP): the cap prices one operation's own reference, which is the same
|
|
438
|
+
* whichever tracker row it is read through.
|
|
397
439
|
*/
|
|
398
440
|
export const VARIANT_MODULES = [
|
|
399
441
|
{
|
package/dist/core/plugins.js
CHANGED
|
@@ -49,7 +49,14 @@ export const DEVFLOW_PLUGINS = [
|
|
|
49
49
|
* dist/commands/, and a hook-spawned agent appears in none of them.
|
|
50
50
|
*/
|
|
51
51
|
agents: ['learning', 'tracker'],
|
|
52
|
-
|
|
52
|
+
/**
|
|
53
|
+
* D-AGENT-REFS: `agent-references` is a reference-only skill. It holds the Synthesize mode
|
|
54
|
+
* templates and the Learning maintain step, which those two agents read by explicit path, so
|
|
55
|
+
* it sits here (core-skills is always installed) and no other plugin lists or requires it.
|
|
56
|
+
* It is never preloaded: tests/guards/agent-references.test.ts holds that, and the one
|
|
57
|
+
* exception to the repo-wide ban on `disable-model-invocation` names this skill alone.
|
|
58
|
+
*/
|
|
59
|
+
skills: ['apply-decisions', 'apply-feature-knowledge', 'software-design', 'docs-framework', 'git', 'boundary-validation', 'test-driven-development', 'testing', 'dependency-research', 'agent-references'],
|
|
53
60
|
requires: [
|
|
54
61
|
'architecture',
|
|
55
62
|
'complexity',
|
|
@@ -76,28 +83,18 @@ export const DEVFLOW_PLUGINS = [
|
|
|
76
83
|
name: 'devflow-plan',
|
|
77
84
|
description: 'Unified design planning with gap analysis and design review',
|
|
78
85
|
commands: ['/plan'],
|
|
79
|
-
agents: ['git', 'skim', 'synthesize', 'design'],
|
|
86
|
+
agents: ['git', 'skim', 'synthesize', 'design', 'explore'],
|
|
80
87
|
skills: ['gap-analysis', 'design-review', 'patterns', 'worktree-support', 'feature-knowledge', 'apply-feature-knowledge'],
|
|
81
88
|
// D-CHARTER-BOUNDED-INLINE: /plan's main thread orchestrates and loads no
|
|
82
89
|
// companion skills, so `requires:` lists only skills this plugin's command,
|
|
83
90
|
// agents and skills reference. `software-design` and `test-driven-development`
|
|
84
91
|
// have no reader here; the closure guard's reverse arm rejects an unread entry.
|
|
92
|
+
// `docs-framework` is read: Phase 14 loads it at the step that names the
|
|
93
|
+
// design document (D-DOCS-NAMES-AUTHORITY).
|
|
85
94
|
requires: [
|
|
86
95
|
'apply-decisions',
|
|
87
|
-
'architecture',
|
|
88
|
-
'complexity',
|
|
89
|
-
'consistency',
|
|
90
|
-
'database',
|
|
91
|
-
'dependencies',
|
|
92
96
|
'docs-framework',
|
|
93
|
-
'documentation',
|
|
94
97
|
'git',
|
|
95
|
-
'performance',
|
|
96
|
-
'regression',
|
|
97
|
-
'reliability',
|
|
98
|
-
'review-methodology',
|
|
99
|
-
'security',
|
|
100
|
-
'testing',
|
|
101
98
|
],
|
|
102
99
|
rules: [],
|
|
103
100
|
},
|
|
@@ -105,17 +102,15 @@ export const DEVFLOW_PLUGINS = [
|
|
|
105
102
|
name: 'devflow-implement',
|
|
106
103
|
description: 'Complete task implementation workflow - accepts plan documents, issues, or task descriptions',
|
|
107
104
|
commands: ['/implement'],
|
|
108
|
-
agents: ['git', 'code', 'simplify', 'scrutinize', 'evaluate', 'test', 'validate', 'knowledge'],
|
|
105
|
+
agents: ['git', 'code', 'code-fix', 'simplify', 'scrutinize', 'evaluate', 'test', 'validate', 'knowledge'],
|
|
109
106
|
skills: ['patterns', 'qa', 'quality-gates', 'worktree-support', 'feature-knowledge', 'apply-feature-knowledge'],
|
|
110
107
|
requires: [
|
|
111
108
|
'apply-decisions',
|
|
112
109
|
'architecture',
|
|
113
|
-
'boundary-validation',
|
|
114
110
|
'complexity',
|
|
115
111
|
'consistency',
|
|
116
112
|
'database',
|
|
117
113
|
'dependencies',
|
|
118
|
-
'dependency-research',
|
|
119
114
|
'documentation',
|
|
120
115
|
'git',
|
|
121
116
|
'performance',
|
|
@@ -139,23 +134,21 @@ export const DEVFLOW_PLUGINS = [
|
|
|
139
134
|
// no companion skills, so `requires:` lists only skills this plugin's command,
|
|
140
135
|
// agents and skills reference. `quality-gates` and `software-design` have no
|
|
141
136
|
// reader here; the closure guard's reverse arm rejects an unread entry.
|
|
142
|
-
requires: ['apply-decisions', '
|
|
137
|
+
requires: ['apply-decisions', 'git'],
|
|
143
138
|
rules: [],
|
|
144
139
|
},
|
|
145
140
|
{
|
|
146
141
|
name: 'devflow-resolve',
|
|
147
142
|
description: 'Process and fix code review issues with blast-radius triage, Code agent fixes, and Validate agent verification',
|
|
148
143
|
commands: ['/resolve'],
|
|
149
|
-
agents: ['git', 'triage', 'code', 'simplify', 'validate', 'test', 'knowledge'],
|
|
150
|
-
skills: ['patterns', '
|
|
144
|
+
agents: ['git', 'triage', 'code', 'code-fix', 'simplify', 'validate', 'test', 'knowledge'],
|
|
145
|
+
skills: ['patterns', 'worktree-support', 'feature-knowledge', 'apply-feature-knowledge', 'apply-decisions'],
|
|
151
146
|
requires: [
|
|
152
147
|
'architecture',
|
|
153
|
-
'boundary-validation',
|
|
154
148
|
'complexity',
|
|
155
149
|
'consistency',
|
|
156
150
|
'database',
|
|
157
151
|
'dependencies',
|
|
158
|
-
'dependency-research',
|
|
159
152
|
'documentation',
|
|
160
153
|
'git',
|
|
161
154
|
'performance',
|
|
@@ -163,6 +156,7 @@ export const DEVFLOW_PLUGINS = [
|
|
|
163
156
|
'regression',
|
|
164
157
|
'reliability',
|
|
165
158
|
'review-methodology',
|
|
159
|
+
'security',
|
|
166
160
|
'software-design',
|
|
167
161
|
'test-driven-development',
|
|
168
162
|
'testing',
|
|
@@ -173,8 +167,11 @@ export const DEVFLOW_PLUGINS = [
|
|
|
173
167
|
name: 'devflow-debug',
|
|
174
168
|
description: 'Debugging workflows with competing hypothesis investigation via parallel subagents',
|
|
175
169
|
commands: ['/debug'],
|
|
176
|
-
agents: ['git', 'synthesize', 'simplify', 'knowledge'],
|
|
170
|
+
agents: ['git', 'synthesize', 'simplify', 'knowledge', 'explore', 'code'],
|
|
177
171
|
skills: ['git', 'worktree-support', 'feature-knowledge', 'apply-feature-knowledge'],
|
|
172
|
+
// D-DEBUG-FIX-VIA-CODE: the fix is a Code spawn. Code loads no skill by language or mode
|
|
173
|
+
// (D-NO-RUNTIME-SKILLS), so `requires:` lists only the skills this command, its agents and the
|
|
174
|
+
// skills they preload reference; the closure guard rejects an entry nothing reads.
|
|
178
175
|
requires: [
|
|
179
176
|
'apply-decisions',
|
|
180
177
|
'architecture',
|
|
@@ -182,9 +179,7 @@ export const DEVFLOW_PLUGINS = [
|
|
|
182
179
|
'consistency',
|
|
183
180
|
'database',
|
|
184
181
|
'dependencies',
|
|
185
|
-
'docs-framework',
|
|
186
182
|
'documentation',
|
|
187
|
-
'patterns',
|
|
188
183
|
'performance',
|
|
189
184
|
'regression',
|
|
190
185
|
'reliability',
|
|
@@ -200,23 +195,12 @@ export const DEVFLOW_PLUGINS = [
|
|
|
200
195
|
name: 'devflow-explore',
|
|
201
196
|
description: 'Codebase exploration with structured analysis and optional knowledge base creation',
|
|
202
197
|
commands: ['/explore'],
|
|
203
|
-
|
|
198
|
+
// 'explore' is devflow's override of Claude Code's built-in Explore agent, spawned by
|
|
199
|
+
// type name (D-EXPLORE-OVERRIDE and D-EXPLORE-NO-CLOBBER, targets/claude-code/agent-type-owner.ts).
|
|
200
|
+
agents: ['skim', 'synthesize', 'knowledge', 'explore'],
|
|
204
201
|
skills: ['worktree-support', 'apply-feature-knowledge', 'feature-knowledge'],
|
|
205
202
|
requires: [
|
|
206
203
|
'apply-decisions',
|
|
207
|
-
'architecture',
|
|
208
|
-
'complexity',
|
|
209
|
-
'consistency',
|
|
210
|
-
'database',
|
|
211
|
-
'dependencies',
|
|
212
|
-
'docs-framework',
|
|
213
|
-
'documentation',
|
|
214
|
-
'performance',
|
|
215
|
-
'regression',
|
|
216
|
-
'reliability',
|
|
217
|
-
'review-methodology',
|
|
218
|
-
'security',
|
|
219
|
-
'testing',
|
|
220
204
|
],
|
|
221
205
|
rules: [],
|
|
222
206
|
},
|
|
@@ -226,21 +210,11 @@ export const DEVFLOW_PLUGINS = [
|
|
|
226
210
|
commands: ['/research'],
|
|
227
211
|
agents: ['research', 'skim', 'synthesize', 'knowledge'],
|
|
228
212
|
skills: ['worktree-support', 'apply-feature-knowledge', 'feature-knowledge', 'research-codebase', 'research-external', 'research-market', 'research-competitor', 'research-technology'],
|
|
213
|
+
// `docs-framework` is read: Phase 2 loads it at the step that names the
|
|
214
|
+
// research directory (D-DOCS-NAMES-AUTHORITY).
|
|
229
215
|
requires: [
|
|
230
216
|
'apply-decisions',
|
|
231
|
-
'architecture',
|
|
232
|
-
'complexity',
|
|
233
|
-
'consistency',
|
|
234
|
-
'database',
|
|
235
|
-
'dependencies',
|
|
236
217
|
'docs-framework',
|
|
237
|
-
'documentation',
|
|
238
|
-
'performance',
|
|
239
|
-
'regression',
|
|
240
|
-
'reliability',
|
|
241
|
-
'review-methodology',
|
|
242
|
-
'security',
|
|
243
|
-
'testing',
|
|
244
218
|
],
|
|
245
219
|
rules: [],
|
|
246
220
|
},
|
|
@@ -286,7 +260,6 @@ export const DEVFLOW_PLUGINS = [
|
|
|
286
260
|
'architecture',
|
|
287
261
|
'database',
|
|
288
262
|
'dependencies',
|
|
289
|
-
'docs-framework',
|
|
290
263
|
'documentation',
|
|
291
264
|
'git',
|
|
292
265
|
'performance',
|
|
@@ -299,7 +272,7 @@ export const DEVFLOW_PLUGINS = [
|
|
|
299
272
|
name: 'devflow-ambient',
|
|
300
273
|
description: 'Orchestrator ambient mode — session charter, per-prompt reminder, plan handoff',
|
|
301
274
|
commands: [],
|
|
302
|
-
agents: ['code', 'validate', 'simplify', 'scrutinize', 'evaluate', 'test', 'skim', 'review', 'git', 'synthesize', 'triage', 'design', 'knowledge', 'research', 'learning'],
|
|
275
|
+
agents: ['code', 'code-edit', 'validate', 'simplify', 'scrutinize', 'evaluate', 'test', 'skim', 'review', 'git', 'synthesize', 'triage', 'design', 'knowledge', 'research', 'learning', 'explore'],
|
|
303
276
|
skills: [
|
|
304
277
|
'review-methodology',
|
|
305
278
|
'security',
|
|
@@ -323,9 +296,6 @@ export const DEVFLOW_PLUGINS = [
|
|
|
323
296
|
],
|
|
324
297
|
requires: [
|
|
325
298
|
'apply-decisions',
|
|
326
|
-
'boundary-validation',
|
|
327
|
-
'dependency-research',
|
|
328
|
-
'docs-framework',
|
|
329
299
|
'git',
|
|
330
300
|
'quality-gates',
|
|
331
301
|
'research-codebase',
|
|
@@ -343,22 +313,19 @@ export const DEVFLOW_PLUGINS = [
|
|
|
343
313
|
description: 'Dynamic workflow recipes - dependency-aware tickets→plan→build delivery pipeline',
|
|
344
314
|
// Commands compiled from commands/*.mds at build time (build:mds).
|
|
345
315
|
commands: ['/dynamic-tickets', '/dynamic-plan', '/dynamic-build', '/dynamic-profile'],
|
|
346
|
-
agents: ['code', 'validate', 'simplify', 'scrutinize', 'evaluate', 'test', 'review', 'git', 'synthesize', 'knowledge', 'design'],
|
|
316
|
+
agents: ['code', 'code-fix', 'validate', 'simplify', 'scrutinize', 'evaluate', 'test', 'review', 'git', 'synthesize', 'knowledge', 'design'],
|
|
347
317
|
skills: ['apply-decisions', 'apply-feature-knowledge', 'worktree-support', 'docs-framework'],
|
|
348
318
|
requires: [
|
|
349
319
|
'architecture',
|
|
350
|
-
'boundary-validation',
|
|
351
320
|
'complexity',
|
|
352
321
|
'consistency',
|
|
353
322
|
'database',
|
|
354
323
|
'dependencies',
|
|
355
|
-
'dependency-research',
|
|
356
324
|
'design-review',
|
|
357
325
|
'documentation',
|
|
358
326
|
'feature-knowledge',
|
|
359
327
|
'gap-analysis',
|
|
360
328
|
'git',
|
|
361
|
-
'patterns',
|
|
362
329
|
'performance',
|
|
363
330
|
'qa',
|
|
364
331
|
'quality-gates',
|
|
@@ -491,16 +458,26 @@ export const FEATURE_OWNED_SKILLS = ['compliance'];
|
|
|
491
458
|
/**
|
|
492
459
|
* Rules owned by the feature system — not any plugin in DEVFLOW_PLUGINS.
|
|
493
460
|
* The compliance rule (src/assets/rules/compliance.md) is stamped and installed
|
|
494
|
-
* by convergeComplianceArtifacts, not by the plugin installer.
|
|
461
|
+
* by convergeComplianceArtifacts, not by the plugin installer. The behavior rule
|
|
462
|
+
* (src/assets/rules/behavior.md) is installed and removed by convergeBehaviorRule.
|
|
463
|
+
*
|
|
464
|
+
* D-BEHAVIOR-OPT-IN: the behavior rule is OPT-IN and default off. How agents reply and
|
|
465
|
+
* act is a taste, so no install carries it until the user asks: `features.behavior` in
|
|
466
|
+
* the machine manifest (`devflow init --behavior`, `devflow behavior --enable`). That is
|
|
467
|
+
* why it sits here and in no plugin's `rules` array: a plugin's rules install for every
|
|
468
|
+
* install that selects the plugin, with no switch, and the core plugin is always
|
|
469
|
+
* selected. The rule is one bullet per behavior and stays small, because every session
|
|
470
|
+
* and every subagent that loads the rules pays for it; tests/rules.test.ts pins the
|
|
471
|
+
* shape, the length and this registration.
|
|
495
472
|
*
|
|
496
473
|
* Used by:
|
|
497
474
|
* - rules.ts: union into allRules for shadow/unshadow/list
|
|
498
|
-
* - tests: independent literal ['compliance'] (avoids EXCLUDED-as-oracle trap)
|
|
475
|
+
* - tests: independent literal ['compliance', 'behavior'] (avoids EXCLUDED-as-oracle trap)
|
|
499
476
|
*
|
|
500
477
|
* D-FO-2: FEATURE_OWNED_RULES must be disjoint from getAllRuleNames()
|
|
501
478
|
* (guarded by plugins.test.ts FEATURE_OWNED constants describe block).
|
|
502
479
|
*/
|
|
503
|
-
export const FEATURE_OWNED_RULES = ['compliance'];
|
|
480
|
+
export const FEATURE_OWNED_RULES = ['compliance', 'behavior'];
|
|
504
481
|
/**
|
|
505
482
|
* Skills a learning-off machine does not install.
|
|
506
483
|
*
|
|
@@ -543,8 +520,8 @@ export function omitLearningGatedSkills(skillsMap, learning) {
|
|
|
543
520
|
* user may deliberately not have. The referencing prompts are written to
|
|
544
521
|
* proceed without it: `/code-review` spawns a language focus only when the
|
|
545
522
|
* installer stamped it into the command (D-LANGUAGE-FOCUS-STAMP,
|
|
546
|
-
* {@link installedLanguageFocuses}), and the Review
|
|
547
|
-
*
|
|
523
|
+
* {@link installedLanguageFocuses}), and the Review agent continues when the
|
|
524
|
+
* Skill invocation fails. Putting them in a `requires` would reinstate
|
|
548
525
|
* the universal install for exactly the eight skills the selection prompt
|
|
549
526
|
* exists to let a user decline (AC-25).
|
|
550
527
|
*
|
|
@@ -131,8 +131,4 @@ export function getDesignDir(projectRoot) {
|
|
|
131
131
|
export function getResearchDir(projectRoot) {
|
|
132
132
|
return path.join(projectRoot, '.devflow', 'docs', 'research');
|
|
133
133
|
}
|
|
134
|
-
/** .devflow/docs/handoff-{branchSlug}.md — Code agent phase handoff artifact */
|
|
135
|
-
export function getHandoffPath(projectRoot, branchSlug) {
|
|
136
|
-
return path.join(projectRoot, '.devflow', 'docs', `handoff-${branchSlug}.md`);
|
|
137
|
-
}
|
|
138
134
|
//# sourceMappingURL=project-paths.js.map
|
package/dist/core/proxy-log.js
CHANGED
|
@@ -34,7 +34,7 @@ export const PROXY_LOG_TAIL_BYTES = 1_048_576;
|
|
|
34
34
|
* XDG_CONFIG_HOME (user-config lookup, reached only on an implicit config load —
|
|
35
35
|
* see D-EFR-6 in model-discovery.ts). CI is read only by `init`; CODEX_HOME and
|
|
36
36
|
* CLAUDE_CONFIG_DIR only by the Codex ingress, `init` and the Codex doctor, none of
|
|
37
|
-
* which devflow enables or invokes. Verified by whole-dist grep of the 0.
|
|
37
|
+
* which devflow enables or invokes. Verified by whole-dist grep of the 0.6.0
|
|
38
38
|
* package. An allowlist is the correct shape: 61 inherited vars → 6.
|
|
39
39
|
*
|
|
40
40
|
* HOME is retained: the runtime's loadConfig resolves ~ paths via homedir().
|
package/dist/core/proxy-state.js
CHANGED
|
@@ -91,7 +91,7 @@ export async function writeProxyState(devflowDir, state) {
|
|
|
91
91
|
* Top-level keys devflow carries into the routing config. Unknown top-level keys
|
|
92
92
|
* cause a hard relay startup error — never emit them.
|
|
93
93
|
*
|
|
94
|
-
* @D-EFR-4 Subswitch 0.
|
|
94
|
+
* @D-EFR-4 Subswitch 0.6.0 routing config contract:
|
|
95
95
|
* FileConfigSchema is a z.strictObject with exactly 6 accepted top-level keys:
|
|
96
96
|
* port, logLevel, anthropic, providers, limits, codexIngress. Unknown keys cause a
|
|
97
97
|
* hard startup error — the relay refuses to start. anthropic and limits are
|
package/dist/core/tracker.js
CHANGED
|
@@ -60,6 +60,44 @@ export const TRACKER_PROVIDER_IDS = TRACKER_PROVIDERS.map(p => p.id);
|
|
|
60
60
|
*/
|
|
61
61
|
export const DEFAULT_TRACKER_PROVIDER = 'github';
|
|
62
62
|
// ---------------------------------------------------------------------------
|
|
63
|
+
// Tracker tool servers — the allowlist half of the Git and Tracker agents
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
/**
|
|
66
|
+
* D-TRACKER-SERVER-ALLOWLIST: the Git and Tracker agents hold a tool ALLOWLIST, and the
|
|
67
|
+
* tracker tool servers a user has connected differ per machine, so the shipped allowlist
|
|
68
|
+
* names no server (the agent sources stay vendor-neutral). The installer stamps one
|
|
69
|
+
* whole-server entry per name below onto the INSTALLED `tools:` line of those two agents
|
|
70
|
+
* (`stampAgentTools`, src/core/agent-frontmatter.ts), after the file is copied. Claude Code
|
|
71
|
+
* has no pattern form for an allowlist entry, so a server is granted by its name; a name
|
|
72
|
+
* that matches no connected server is inert (it grants nothing and blocks nothing).
|
|
73
|
+
*
|
|
74
|
+
* The default is one FLAT list, stamped whatever the provider: every install carries every
|
|
75
|
+
* provider, and a repository may select a provider other than the machine's, so a list
|
|
76
|
+
* keyed on the machine's provider would strand that repository. A server the user runs
|
|
77
|
+
* under another name is added with `devflow tracker --servers`. A wrong or missing name
|
|
78
|
+
* does not fail silently: the agent finds no tool for the capability it needs and reports
|
|
79
|
+
* `TRACEABILITY: DEGRADED (no tracker tool for {capability})`.
|
|
80
|
+
*
|
|
81
|
+
* The default leaves `github` out. Under the github provider the Git agent uses `gh` and
|
|
82
|
+
* never reads `_mcp.md`, so a stamped `github` server is never used by a tracker operation;
|
|
83
|
+
* under jira or linear, a connected GitHub server that also advertises issue creation would
|
|
84
|
+
* make the `_mcp.md` capability selection ambiguous, which is a degraded run. A user who
|
|
85
|
+
* wants it adds it with `devflow tracker --servers`.
|
|
86
|
+
*/
|
|
87
|
+
export const TRACKER_MCP_SERVERS_DEFAULT = Object.freeze([
|
|
88
|
+
'atlassian',
|
|
89
|
+
'jira',
|
|
90
|
+
'claude_ai_Atlassian',
|
|
91
|
+
'linear',
|
|
92
|
+
'claude_ai_Linear',
|
|
93
|
+
]);
|
|
94
|
+
/** A server name as a user may configure it. Byte-exact, like a provider token. */
|
|
95
|
+
export const TRACKER_SERVER_NAME_RE = /^[A-Za-z0-9_-]{1,64}$/;
|
|
96
|
+
/** The most servers one list may hold; every entry lands in a prompt-adjacent frontmatter line. */
|
|
97
|
+
export const TRACKER_SERVERS_MAX = 32;
|
|
98
|
+
/** The reserved word that returns the setting to {@link TRACKER_MCP_SERVERS_DEFAULT}. */
|
|
99
|
+
export const TRACKER_SERVERS_DEFAULT_WORD = 'default';
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
63
101
|
// Artifact basenames — one spelling for every TypeScript reader
|
|
64
102
|
//
|
|
65
103
|
// NOT the only spelling in the repository, and a rename that assumes it is will
|
|
@@ -238,6 +276,72 @@ export function parseTrackerId(input) {
|
|
|
238
276
|
}
|
|
239
277
|
return { ok: true, value: input };
|
|
240
278
|
}
|
|
279
|
+
/**
|
|
280
|
+
* Validate a list of tracker server names. The one rule set behind both the CLI argument
|
|
281
|
+
* and the manifest field.
|
|
282
|
+
*
|
|
283
|
+
* REJECT, NEVER REPAIR (as {@link parseTrackerId}): a name is accepted byte-exact against
|
|
284
|
+
* {@link TRACKER_SERVER_NAME_RE} and must not hold `__`, which is what separates a server
|
|
285
|
+
* from its tool in an entry such as `mcp__server__tool`. No trim, no case folding, no
|
|
286
|
+
* alias. Exact duplicates collapse to the first occurrence and the order is kept. The list
|
|
287
|
+
* is non-empty and holds at most {@link TRACKER_SERVERS_MAX} distinct names.
|
|
288
|
+
*/
|
|
289
|
+
export function validateTrackerServers(raw) {
|
|
290
|
+
if (raw.length === 0) {
|
|
291
|
+
return { ok: false, error: 'No tracker servers given. Pass one or more server names, or "default".' };
|
|
292
|
+
}
|
|
293
|
+
const seen = new Set();
|
|
294
|
+
for (const entry of raw) {
|
|
295
|
+
if (typeof entry !== 'string' || !TRACKER_SERVER_NAME_RE.test(entry)) {
|
|
296
|
+
return {
|
|
297
|
+
ok: false,
|
|
298
|
+
error: `Invalid tracker server name: "${describeTrackerValue(entry)}". ` +
|
|
299
|
+
'Names are 1-64 characters from A-Z, a-z, 0-9, "_" and "-".',
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
if (entry.includes('__')) {
|
|
303
|
+
return {
|
|
304
|
+
ok: false,
|
|
305
|
+
error: `Invalid tracker server name: "${describeTrackerValue(entry)}". ` +
|
|
306
|
+
'A name must not contain "__" (it separates a server from its tool).',
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
seen.add(entry);
|
|
310
|
+
}
|
|
311
|
+
if (seen.size > TRACKER_SERVERS_MAX) {
|
|
312
|
+
return { ok: false, error: `Too many tracker servers: ${seen.size} (at most ${TRACKER_SERVERS_MAX}).` };
|
|
313
|
+
}
|
|
314
|
+
return { ok: true, value: [...seen] };
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Strict boundary parser for `devflow tracker --servers <list>`.
|
|
318
|
+
*
|
|
319
|
+
* `default` alone selects {@link TRACKER_MCP_SERVERS_DEFAULT}; anything else is a
|
|
320
|
+
* comma-separated list of names handed to {@link validateTrackerServers} unchanged. An
|
|
321
|
+
* empty argument, an empty item (`a,,b`, a trailing comma) and the reserved word inside a
|
|
322
|
+
* list are errors, never silently dropped.
|
|
323
|
+
*/
|
|
324
|
+
export function parseTrackerServers(input) {
|
|
325
|
+
if (input === '') {
|
|
326
|
+
return { ok: false, error: 'Missing tracker servers. Pass a comma-separated list of names, or "default".' };
|
|
327
|
+
}
|
|
328
|
+
if (input === TRACKER_SERVERS_DEFAULT_WORD)
|
|
329
|
+
return { ok: true, value: { kind: 'default' } };
|
|
330
|
+
const items = input.split(',');
|
|
331
|
+
if (items.includes(TRACKER_SERVERS_DEFAULT_WORD)) {
|
|
332
|
+
return { ok: false, error: `"${TRACKER_SERVERS_DEFAULT_WORD}" is reserved: pass it alone, not inside a list.` };
|
|
333
|
+
}
|
|
334
|
+
const validated = validateTrackerServers(items);
|
|
335
|
+
return validated.ok ? { ok: true, value: { kind: 'list', servers: validated.value } } : validated;
|
|
336
|
+
}
|
|
337
|
+
/** The servers in force for `state`: its own list, else the default. */
|
|
338
|
+
export function effectiveTrackerServers(state) {
|
|
339
|
+
return state.servers ?? TRACKER_MCP_SERVERS_DEFAULT;
|
|
340
|
+
}
|
|
341
|
+
/** The whole-server allowlist entries for `servers`, in order: `github` becomes `mcp__github`. */
|
|
342
|
+
export function trackerServerTools(servers) {
|
|
343
|
+
return servers.map(name => `mcp__${name}`);
|
|
344
|
+
}
|
|
241
345
|
/**
|
|
242
346
|
* Tolerant sink normaliser for a raw `manifest.features.tracker` value.
|
|
243
347
|
*
|
|
@@ -249,9 +353,11 @@ export function parseTrackerId(input) {
|
|
|
249
353
|
* D-TRACKER-SELF-HEAL [DR-26]: self-healing here is SILENT and emits no
|
|
250
354
|
* DEGRADED — that is the correct self-heal behaviour, and it is a different
|
|
251
355
|
* condition from a per-repo config value outside the domain (which does emit
|
|
252
|
-
* `unknown tracker provider`). The two must not be conflated.
|
|
356
|
+
* `unknown tracker provider`). The two must not be conflated. The one exception is
|
|
357
|
+
* `servers` (see the body): a present but invalid list heals to the default AND reaches
|
|
358
|
+
* `onWarning` when a caller supplies one, because the user wrote that list on purpose.
|
|
253
359
|
*/
|
|
254
|
-
export function normalizeTrackerFeature(raw) {
|
|
360
|
+
export function normalizeTrackerFeature(raw, onWarning) {
|
|
255
361
|
const DEFAULT = { provider: DEFAULT_TRACKER_PROVIDER };
|
|
256
362
|
if (raw === null || raw === undefined || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
257
363
|
return DEFAULT;
|
|
@@ -259,6 +365,18 @@ export function normalizeTrackerFeature(raw) {
|
|
|
259
365
|
const obj = raw;
|
|
260
366
|
if (!isTrackerProvider(obj.provider))
|
|
261
367
|
return DEFAULT;
|
|
368
|
+
// `servers`: absent is the default, silently. A present value that is not a valid list is
|
|
369
|
+
// dropped WHOLE (never trimmed to its valid names) and reported through `onWarning`, which a
|
|
370
|
+
// caller with a terminal passes; the reader itself has no output channel. The state then
|
|
371
|
+
// reads as the default list, and the next `devflow tracker --servers` or `devflow init`
|
|
372
|
+
// writes the manifest without the bad value.
|
|
373
|
+
if (obj.servers === undefined)
|
|
374
|
+
return { provider: obj.provider };
|
|
375
|
+
const servers = Array.isArray(obj.servers) ? validateTrackerServers(obj.servers) : undefined;
|
|
376
|
+
if (servers?.ok === true)
|
|
377
|
+
return { provider: obj.provider, servers: servers.value };
|
|
378
|
+
onWarning?.(`The manifest's tracker servers setting is not a valid list (${servers?.ok === false ? servers.error : 'not a list'}); ` +
|
|
379
|
+
'using the default. Run `devflow tracker --servers <names>` to set it, or `devflow tracker --servers default`.');
|
|
262
380
|
return { provider: obj.provider };
|
|
263
381
|
}
|
|
264
382
|
// ---------------------------------------------------------------------------
|