@khoavu882/doflow 2.0.0-beta.3 → 2.0.0-beta.5
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/bin/doflow.js +2 -2
- package/core/.antigravity-plugin/plugin.json +0 -1
- package/core/.claude-plugin/plugin.json +1 -1
- package/core/.codex-plugin/plugin.json +1 -1
- package/core/.plugin/plugin.json +1 -1
- package/core/harnesses/claude/hooks/mcp-tool-guard.sh +7 -17
- package/core/harnesses/claude/hooks/pre-bash-guard.sh +7 -17
- package/core/harnesses/claude/hooks/pre-implement-gate.sh +7 -18
- package/core/harnesses/claude/hooks/session-start.sh +5 -3
- package/core/harnesses/claude/hooks/stop-check.sh +5 -3
- package/core/harnesses/claude/hooks/subagent-audit.sh +5 -5
- package/core/harnesses/claude/hooks/user-prompt-submit.sh +5 -3
- package/core/harnesses/codex/hooks/mcp-tool-guard.sh +7 -15
- package/core/harnesses/codex/hooks/pre-bash-guard.sh +7 -15
- package/core/harnesses/codex/hooks/pre-implement-gate.sh +7 -16
- package/core/harnesses/codex/hooks/session-start.sh +5 -3
- package/core/harnesses/codex/hooks/stop-check.sh +6 -5
- package/core/harnesses/codex/hooks/subagent-audit.sh +17 -6
- package/core/harnesses/codex/hooks/user-prompt-submit.sh +5 -4
- package/core/harnesses/gemini/hooks/mcp-tool-guard.sh +7 -18
- package/core/harnesses/gemini/hooks/pre-bash-guard.sh +7 -18
- package/core/harnesses/gemini/hooks/pre-implement-gate.sh +7 -19
- package/core/harnesses/gemini/hooks/session-start.sh +5 -3
- package/core/harnesses/kiro/hooks/mcp-tool-guard.sh +20 -5
- package/core/harnesses/kiro/hooks/pre-bash-guard.sh +20 -5
- package/core/harnesses/kiro/hooks/pre-implement-gate.sh +20 -5
- package/core/harnesses/kiro/hooks/session-start.sh +11 -5
- package/core/harnesses/kiro/hooks/stop-check.sh +21 -30
- package/core/harnesses/pi/extensions/doflow-guard.js +159 -0
- package/core/harnesses/shared/hooks/ENVELOPE_MIGRATION.md +27 -11
- package/core/harnesses/shared/hooks/adapters/antigravity.js +14 -57
- package/core/harnesses/shared/hooks/bridge/bridge.sh +184 -0
- package/core/harnesses/shared/hooks/bridge/envelope.jq +60 -0
- package/core/harnesses/shared/hooks/bridge/respond.sh +62 -0
- package/core/harnesses/shared/hooks/policies/capture-failure.sh +4 -2
- package/core/harnesses/shared/hooks/policies/contract.sh +75 -0
- package/core/harnesses/shared/hooks/policies/deny-json.sh +39 -4
- package/core/harnesses/shared/hooks/policies/lib.sh +4 -2
- package/core/harnesses/shared/hooks/policies/mcp-tool-guard.sh +46 -34
- package/core/harnesses/shared/hooks/policies/pre-bash-guard.sh +75 -25
- package/core/harnesses/shared/hooks/policies/pre-implementation-gate.sh +67 -73
- package/core/harnesses/shared/hooks/policies/session-context.sh +37 -7
- package/core/harnesses/shared/hooks/policies/stop-check.sh +42 -15
- package/core/harnesses/shared/hooks/policies/subagent-audit.sh +35 -5
- package/core/harnesses/shared/hooks/policies/user-prompt-submit.sh +40 -7
- package/core/harnesses/shared/hooks/stream-hook-runner.js +69 -181
- package/core/registry/assets.json +19 -0
- package/core/registry/contracts.json +2 -2
- package/core/registry/harnesses.json +196 -10
- package/core/registry/lifecycle.json +2626 -7
- package/core/registry/storage.json +110 -83
- package/core/registry/verification.json +1 -1
- package/core/shared/scripts/doflow/bash/render-puml.sh +2 -2
- package/core/shared/scripts/doflow/bin/doflow-run +10 -6
- package/core/shared/skills/do-design/SKILL.md +6 -6
- package/core/shared/skills/do-execute-plan/SKILL.md +11 -10
- package/core/shared/skills/do-execute-plan/references/readiness_gate.md +2 -0
- package/core/shared/skills/do-execute-plan/references/scaffold.md +2 -2
- package/core/shared/skills/do-implement/SKILL.md +3 -2
- package/core/shared/skills/do-plan/SKILL.md +7 -8
- package/package.json +4 -2
- package/src/adapters/antigravity/{index.ts → index.js} +141 -105
- package/src/adapters/claude/{index.ts → index.js} +63 -49
- package/src/adapters/claude/{mcp.ts → mcp.js} +16 -16
- package/src/adapters/codex/{agents.ts → agents.js} +24 -24
- package/src/adapters/codex/{config.ts → config.js} +49 -49
- package/src/adapters/codex/{hooks.ts → hooks.js} +62 -27
- package/src/adapters/codex/{index.ts → index.js} +148 -105
- package/src/adapters/codex/{mcp.ts → mcp.js} +38 -38
- package/src/adapters/codex/{native-projection.ts → native-projection.js} +5 -5
- package/src/adapters/copilot/{index.ts → index.js} +42 -42
- package/src/adapters/{copy-tree.ts → copy-tree.js} +74 -74
- package/src/adapters/gemini/{hooks.ts → hooks.js} +78 -37
- package/src/adapters/gemini/{index.ts → index.js} +96 -57
- package/src/adapters/{hook-commands.ts → hook-commands.js} +8 -8
- package/src/adapters/{index.ts → index.js} +13 -13
- package/src/adapters/kiro/{index.ts → index.js} +49 -35
- package/src/adapters/{mcp-entries.ts → mcp-entries.js} +55 -55
- package/src/adapters/opencode/{index.ts → index.js} +52 -52
- package/src/adapters/pi/hooks.js +119 -0
- package/src/adapters/pi/{index.ts → index.js} +64 -39
- package/src/adapters/pi/{json-members.ts → json-members.js} +23 -23
- package/src/adapters/pi/{mcp.ts → mcp.js} +70 -70
- package/src/adapters/{resolve-source.ts → resolve-source.js} +1 -1
- package/src/cli/commands/{install.ts → install.js} +25 -25
- package/src/cli/commands/{list-backups.ts → list-backups.js} +4 -4
- package/src/cli/commands/{reconcile.ts → reconcile.js} +19 -19
- package/src/cli/commands/{remove.ts → remove.js} +10 -10
- package/src/cli/commands/{rollback.ts → rollback.js} +17 -17
- package/src/cli/commands/{self-update.ts → self-update.js} +3 -3
- package/src/cli/commands/{status.ts → status.js} +24 -24
- package/src/cli/commands/{tools.ts → tools.js} +16 -16
- package/src/cli/commands/{update.ts → update.js} +20 -20
- package/src/cli/{index.ts → index.js} +43 -31
- package/src/cli/{runtime-commands.ts → runtime-commands.js} +97 -58
- package/src/cli/{shared.ts → shared.js} +40 -40
- package/src/helper/{bash-helper.ts → bash-helper.js} +7 -7
- package/src/helper/{git.ts → git.js} +2 -2
- package/src/helper/{guardrails.ts → guardrails.js} +10 -10
- package/src/helper/{harness-paths.ts → harness-paths.js} +24 -24
- package/src/helper/{marker-merge.ts → marker-merge.js} +4 -4
- package/src/helper/{prompt.ts → prompt.js} +5 -5
- package/src/helper/{repo-root.ts → repo-root.js} +2 -2
- package/src/helper/{settings-merge.ts → settings-merge.js} +27 -27
- package/src/helper/{settings-scope.ts → settings-scope.js} +3 -3
- package/src/helper/{toml.ts → toml.js} +48 -48
- package/src/install/{backup-set.ts → backup-set.js} +16 -16
- package/src/install/{backup.ts → backup.js} +65 -65
- package/src/install/{context.ts → context.js} +15 -15
- package/src/install/{manifest.ts → manifest.js} +27 -27
- package/src/install/{mcp.ts → mcp.js} +30 -30
- package/src/install/{paths.ts → paths.js} +15 -15
- package/src/install/{targets.ts → targets.js} +10 -10
- package/src/install/{tool-lifecycle.ts → tool-lifecycle.js} +20 -20
- package/src/lifecycle/{bash-availability.ts → bash-availability.js} +1 -1
- package/src/lifecycle/coverage.js +57 -0
- package/src/lifecycle/hook-step.js +61 -0
- package/src/lifecycle/{index.ts → index.js} +160 -146
- package/src/lifecycle/{mcp-index.ts → mcp-index.js} +1 -1
- package/src/lifecycle/{policies.ts → policies.js} +11 -11
- package/src/lifecycle/{view.ts → view.js} +28 -28
- package/src/registry/{index.ts → index.js} +195 -66
- package/src/release/build-package.js +91 -0
- package/src/release/changelog-section.js +70 -0
- package/src/release/{sync-plugin-versions.ts → sync-plugin-versions.js} +4 -4
- package/src/runtime/advice/{cli.ts → cli.js} +31 -31
- package/src/runtime/advice/{client.ts → client.js} +44 -44
- package/src/runtime/advice/{config.ts → config.js} +16 -16
- package/src/runtime/advice/{doctor.ts → doctor.js} +32 -32
- package/src/runtime/advice/{endpoint-guard.ts → endpoint-guard.js} +20 -20
- package/src/runtime/advice/{kinds.ts → kinds.js} +16 -16
- package/src/runtime/advice/providers/{ollama-systemone.ts → ollama-systemone.js} +21 -21
- package/src/runtime/advice/{record.ts → record.js} +19 -19
- package/src/runtime/advice/{registry.ts → registry.js} +16 -16
- package/src/runtime/advice/{strength.ts → strength.js} +7 -7
- package/src/runtime/{brief-tools.ts → brief-tools.js} +50 -50
- package/src/runtime/{c4-project.ts → c4-project.js} +27 -27
- package/src/runtime/candidate.js +505 -0
- package/src/runtime/{capability-router.ts → capability-router.js} +39 -39
- package/src/runtime/{checkouts.ts → checkouts.js} +21 -21
- package/src/runtime/{claims.ts → claims.js} +44 -35
- package/src/runtime/{cli-result.ts → cli-result.js} +15 -8
- package/src/runtime/{cli.ts → cli.js} +59 -292
- package/src/runtime/{command-detect.ts → command-detect.js} +47 -47
- package/src/runtime/context/budget.js +203 -0
- package/src/runtime/context/compose.js +1367 -0
- package/src/runtime/context/delivery-store.js +102 -0
- package/src/runtime/context/mandatory.js +594 -0
- package/src/runtime/context/pointer.js +142 -0
- package/src/runtime/context-pack.js +1277 -0
- package/src/runtime/{decision-register.ts → decision-register.js} +67 -67
- package/src/runtime/evidence-fields.js +39 -0
- package/src/runtime/{evidence-ledger.ts → evidence-ledger.js} +32 -25
- package/src/runtime/failure/{capture.ts → capture.js} +29 -29
- package/src/runtime/failure/{classifier.ts → classifier.js} +4 -4
- package/src/runtime/failure/{cli.ts → cli.js} +30 -30
- package/src/runtime/failure/{home.ts → home.js} +6 -6
- package/src/runtime/failure/{store.ts → store.js} +32 -32
- package/src/runtime/{feature-resolve.ts → feature-resolve.js} +6 -6
- package/src/runtime/{freshness.ts → freshness.js} +59 -22
- package/src/runtime/{health.ts → health.js} +72 -72
- package/src/runtime/{history-compactor.ts → history-compactor.js} +25 -25
- package/src/runtime/{implementation-gate.ts → implementation-gate.js} +30 -30
- package/src/runtime/inventory/{coverage.ts → coverage.js} +10 -10
- package/src/runtime/inventory/{identity.ts → identity.js} +2 -2
- package/src/runtime/inventory/{index.ts → index.js} +36 -36
- package/src/runtime/inventory/{precedence.ts → precedence.js} +2 -2
- package/src/runtime/inventory/{read-scopes.ts → read-scopes.js} +9 -9
- package/src/runtime/inventory/{siblings.ts → siblings.js} +15 -15
- package/src/runtime/knowledge/{chunker.ts → chunker.js} +12 -12
- package/src/runtime/knowledge/{hybrid.ts → hybrid.js} +17 -17
- package/src/runtime/knowledge/{index-store.ts → index-store.js} +23 -23
- package/src/runtime/knowledge/{retrieval.ts → retrieval.js} +27 -27
- package/src/runtime/{leak-scan.ts → leak-scan.js} +12 -12
- package/src/runtime/lifecycle/{cli.ts → cli.js} +32 -32
- package/src/runtime/lifecycle/{event-store.ts → event-store.js} +48 -48
- package/src/runtime/lifecycle/{fold.ts → fold.js} +41 -41
- package/src/runtime/lifecycle/{followup.ts → followup.js} +54 -54
- package/src/runtime/lifecycle/{goal.ts → goal.js} +50 -50
- package/src/runtime/lifecycle/{intent-writer.ts → intent-writer.js} +5 -5
- package/src/runtime/lifecycle/{overview.ts → overview.js} +47 -47
- package/src/runtime/lifecycle/{release.ts → release.js} +29 -29
- package/src/runtime/lifecycle/{report-store.ts → report-store.js} +25 -25
- package/src/runtime/lifecycle/{retention.ts → retention.js} +37 -37
- package/src/runtime/lifecycle/{root.ts → root.js} +9 -9
- package/src/runtime/lifecycle/{status.ts → status.js} +64 -64
- package/src/runtime/lifecycle/{store-upkeep.ts → store-upkeep.js} +46 -46
- package/src/runtime/{locator-resolve.ts → locator-resolve.js} +7 -7
- package/src/runtime/{mask.ts → mask.js} +22 -22
- package/src/runtime/{mcp-consultations.ts → mcp-consultations.js} +54 -54
- package/src/runtime/{mcp-reach.ts → mcp-reach.js} +24 -24
- package/src/runtime/{model-router.ts → model-router.js} +20 -20
- package/src/runtime/{outcome.ts → outcome.js} +27 -27
- package/src/runtime/{reach.ts → reach.js} +21 -21
- package/src/runtime/{readiness-record.ts → readiness-record.js} +12 -12
- package/src/runtime/{readiness.ts → readiness.js} +113 -43
- package/src/runtime/{recovery.ts → recovery.js} +15 -15
- package/src/runtime/{research-request.ts → research-request.js} +34 -34
- package/src/runtime/{retrieval-plan.ts → retrieval-plan.js} +453 -104
- package/src/runtime/retrieval-record.js +223 -0
- package/src/runtime/scaffold/{artifacts.ts → artifacts.js} +22 -19
- package/src/runtime/scaffold/{fingerprint.ts → fingerprint.js} +3 -3
- package/src/runtime/scaffold/{generate.ts → generate.js} +109 -109
- package/src/runtime/scaffold/{languages.ts → languages.js} +34 -34
- package/src/runtime/source-version.js +289 -0
- package/src/runtime/storage/{cli.ts → cli.js} +9 -9
- package/src/runtime/storage/{engine.ts → engine.js} +37 -37
- package/src/runtime/storage/{registry.ts → registry.js} +19 -19
- package/src/runtime/storage/{roots.ts → roots.js} +8 -8
- package/src/runtime/storage/{rules.ts → rules.js} +26 -26
- package/src/runtime/storage/{upkeep.ts → upkeep.js} +35 -35
- package/src/runtime/storage/{work-status.ts → work-status.js} +39 -39
- package/src/runtime/{task-attempts.ts → task-attempts.js} +62 -62
- package/src/runtime/{task-classifier.ts → task-classifier.js} +34 -34
- package/src/runtime/{task-scope.ts → task-scope.js} +40 -15
- package/src/runtime/{task-state.ts → task-state.js} +86 -21
- package/src/runtime/trace/{indicators.ts → indicators.js} +22 -22
- package/src/runtime/trace/{ledger.ts → ledger.js} +42 -42
- package/src/runtime/trace/{render.ts → render.js} +7 -7
- package/src/runtime/trace/{views.ts → views.js} +40 -40
- package/src/runtime/verification/{contract-runner.ts → contract-runner.js} +23 -23
- package/src/runtime/verification/{engine.ts → engine.js} +143 -143
- package/src/runtime/verification/{registry.ts → registry.js} +6 -6
- package/src/runtime/verification/{scope-bound.ts → scope-bound.js} +50 -50
- package/src/runtime/verification/{test-selection.ts → test-selection.js} +28 -28
- package/src/runtime/{workflow-engine.ts → workflow-engine.js} +50 -50
- package/src/runtime/{workflow-orchestrator.ts → workflow-orchestrator.js} +91 -91
- package/src/runtime/{worktree.ts → worktree.js} +31 -31
- package/src/state/{index.ts → index.js} +26 -26
- package/src/state/{lockfile.ts → lockfile.js} +20 -20
- package/src/state/{run-lock.ts → run-lock.js} +44 -44
- package/core/.antigravity-plugin/hooks.json +0 -39
- package/core/harnesses/shared/hooks/adapters/arg-fields.js +0 -19
- package/core/harnesses/shared/hooks/adapters/gemini.js +0 -114
- package/core/harnesses/shared/hooks/hooks.json +0 -47
- package/src/runtime/context-pack.ts +0 -492
|
@@ -6,31 +6,31 @@
|
|
|
6
6
|
// restores per tool, as it always did.
|
|
7
7
|
// TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
|
|
8
8
|
const path = require('node:path');
|
|
9
|
-
const { resolveTargets, toolDirs } = require('../../install/targets.
|
|
10
|
-
const { resolveContext, printContext } = require('../../install/context.
|
|
9
|
+
const { resolveTargets, toolDirs } = require('../../install/targets.js');
|
|
10
|
+
const { resolveContext, printContext } = require('../../install/context.js');
|
|
11
11
|
const {
|
|
12
12
|
BackupError, createFileBackup, planRestore, executeRestore, listBackups, formatBytes,
|
|
13
|
-
} = require('../../install/backup.
|
|
14
|
-
const { backupSetFromPaths } = require('../../install/backup-set.
|
|
15
|
-
const { writeManifest } = require('../../install/manifest.
|
|
16
|
-
const { stateRoot, ledgerPath } = require('../../state/index.
|
|
17
|
-
const { confirm, promptLine } = require('../../helper/prompt.
|
|
18
|
-
const { sourceCommit } = require('../../helper/git.
|
|
19
|
-
const { captureCaught } = require('../../runtime/cli-result.
|
|
13
|
+
} = require('../../install/backup.js');
|
|
14
|
+
const { backupSetFromPaths } = require('../../install/backup-set.js');
|
|
15
|
+
const { writeManifest } = require('../../install/manifest.js');
|
|
16
|
+
const { stateRoot, ledgerPath } = require('../../state/index.js');
|
|
17
|
+
const { confirm, promptLine } = require('../../helper/prompt.js');
|
|
18
|
+
const { sourceCommit } = require('../../helper/git.js');
|
|
19
|
+
const { captureCaught } = require('../../runtime/cli-result.js');
|
|
20
20
|
const {
|
|
21
21
|
REPO_ROOT, SCRIPT_DIR, pkg, installPaths, printBackupTable, holdRunLock, checkpointRunLock,
|
|
22
|
-
} = require('../shared.
|
|
22
|
+
} = require('../shared.js');
|
|
23
23
|
|
|
24
24
|
const LISTED_ABSENT = 10;
|
|
25
25
|
|
|
26
|
-
function fail(error
|
|
26
|
+
function fail(error ) {
|
|
27
27
|
captureCaught(error, 'rollback', 1);
|
|
28
28
|
console.error(`[ERROR] ${error.message}`);
|
|
29
29
|
console.error('[ERROR] Use --list-backups to see available backups');
|
|
30
30
|
process.exit(1);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
function cmdRollback(o
|
|
33
|
+
function cmdRollback(o ) {
|
|
34
34
|
const targets = resolveTargets(o.targets);
|
|
35
35
|
const dirs = toolDirs({ global: o.global, projectRoot: '.' });
|
|
36
36
|
const scope = { global: o.global, projectRoot: '.' };
|
|
@@ -50,7 +50,7 @@ function cmdRollback(o: any): void {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
// Worked out before anything is written. Reads only, so a bad id fails here, before the prompt.
|
|
53
|
-
let plan
|
|
53
|
+
let plan ;
|
|
54
54
|
try {
|
|
55
55
|
const neutralStateRoot = stateRoot({ scope: scopeName, projectRoot: lifecyclePaths.scopeRoot, homeDir: lifecyclePaths.scopeRoot });
|
|
56
56
|
plan = planRestore({ bid, backupRoot, scope: scopeName, scopeRoot: lifecyclePaths.scopeRoot, targets, explicitTargets, dirs,
|
|
@@ -61,7 +61,7 @@ function cmdRollback(o: any): void {
|
|
|
61
61
|
// A per-file backup restores the harnesses it holds (only those in --target when given), so the
|
|
62
62
|
// banner and the install manifest name those, not the default target.
|
|
63
63
|
const restoredTools = plan.format === 2
|
|
64
|
-
? [...new Set(plan.restore.flatMap((item
|
|
64
|
+
? [...new Set(plan.restore.flatMap((item ) => item.harnesses))].filter((h) => !explicitTargets || targets.includes(h)).sort()
|
|
65
65
|
: targets;
|
|
66
66
|
printContext(resolveContext({ repoRoot: REPO_ROOT, targets: restoredTools, dirs, sourceCommit: commit, global: o.global, projectRoot: '.' }));
|
|
67
67
|
|
|
@@ -87,7 +87,7 @@ function cmdRollback(o: any): void {
|
|
|
87
87
|
|
|
88
88
|
snapshotBeforeRestore({ o, plan, bid, backupRoot, lifecyclePaths, scopeName, commit });
|
|
89
89
|
|
|
90
|
-
let result
|
|
90
|
+
let result ;
|
|
91
91
|
try {
|
|
92
92
|
result = executeRestore(plan, { backupRoot, dryRun: o.dryRun });
|
|
93
93
|
} catch (error) {
|
|
@@ -134,7 +134,7 @@ function cmdRollback(o: any): void {
|
|
|
134
134
|
/** A backup of exactly the files the restore will overwrite, taken regardless of --no-backup:
|
|
135
135
|
* rollback is destructive enough that skipping it is not offered. Skipped when the restore
|
|
136
136
|
* overwrites nothing, so an empty snapshot never pushes a real restore point out of retention. */
|
|
137
|
-
function snapshotBeforeRestore({ o, plan, bid, backupRoot, lifecyclePaths, scopeName, commit }
|
|
137
|
+
function snapshotBeforeRestore({ o, plan, bid, backupRoot, lifecyclePaths, scopeName, commit } ) {
|
|
138
138
|
if (o.dryRun) {
|
|
139
139
|
console.log(`[DRY] Would snapshot ${plan.snapshot.length} file(s) before restoring`);
|
|
140
140
|
return;
|
|
@@ -157,7 +157,7 @@ function snapshotBeforeRestore({ o, plan, bid, backupRoot, lifecyclePaths, scope
|
|
|
157
157
|
});
|
|
158
158
|
snapshot = createFileBackup({ operation: 'pre-rollback', set, backupRoot, repoRoot: SCRIPT_DIR, sourceCommit: commit,
|
|
159
159
|
version: pkg.version, date: new Date(), restores: bid });
|
|
160
|
-
} catch (error
|
|
160
|
+
} catch (error ) {
|
|
161
161
|
if (!(error instanceof BackupError)) throw error;
|
|
162
162
|
console.error(`[ERROR] Pre-rollback snapshot failed, nothing was restored: ${error.message}`);
|
|
163
163
|
process.exit(1);
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
// installed trees match the freshly pulled source.
|
|
4
4
|
// TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
|
|
5
5
|
const { execFileSync } = require('node:child_process');
|
|
6
|
-
const { REPO_ROOT } = require('../shared.
|
|
7
|
-
const cmdInstall = require('./install.
|
|
6
|
+
const { REPO_ROOT } = require('../shared.js');
|
|
7
|
+
const cmdInstall = require('./install.js');
|
|
8
8
|
|
|
9
|
-
function cmdSelfUpdate(o
|
|
9
|
+
function cmdSelfUpdate(o ) {
|
|
10
10
|
console.log('[INFO] Self-update: checking for upstream changes...');
|
|
11
11
|
let pulled = false;
|
|
12
12
|
let fetchOk = false;
|
|
@@ -4,35 +4,35 @@
|
|
|
4
4
|
// scripting).
|
|
5
5
|
// TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
|
|
6
6
|
const path = require('node:path');
|
|
7
|
-
const { resolveTargets, toolDirs } = require('../../install/targets.
|
|
8
|
-
const { resolveContext, printContext } = require('../../install/context.
|
|
9
|
-
const { readInstallManifest } = require('../../install/manifest.
|
|
10
|
-
const { sourceCommit } = require('../../helper/git.
|
|
11
|
-
const { loadRegistry, mcpCapable } = require('../../registry/index.
|
|
12
|
-
const { recordedMcpSelections } = require('../../install/mcp.
|
|
13
|
-
const { pinnedSelections } = require('../../state/lockfile.
|
|
14
|
-
const { readLedger } = require('../../state/index.
|
|
15
|
-
const { verifyLifecycle } = require('../../lifecycle/index.
|
|
16
|
-
const { registryLifecycleView, LIFECYCLE_HARNESSES } = require('../../lifecycle/view.
|
|
17
|
-
const { REPO_ROOT, SCRIPT_DIR, installPaths, scopeOf, scopeSelectionState } = require('../shared.
|
|
7
|
+
const { resolveTargets, toolDirs } = require('../../install/targets.js');
|
|
8
|
+
const { resolveContext, printContext } = require('../../install/context.js');
|
|
9
|
+
const { readInstallManifest } = require('../../install/manifest.js');
|
|
10
|
+
const { sourceCommit } = require('../../helper/git.js');
|
|
11
|
+
const { loadRegistry, mcpCapable } = require('../../registry/index.js');
|
|
12
|
+
const { recordedMcpSelections } = require('../../install/mcp.js');
|
|
13
|
+
const { pinnedSelections } = require('../../state/lockfile.js');
|
|
14
|
+
const { readLedger } = require('../../state/index.js');
|
|
15
|
+
const { verifyLifecycle } = require('../../lifecycle/index.js');
|
|
16
|
+
const { registryLifecycleView, LIFECYCLE_HARNESSES } = require('../../lifecycle/view.js');
|
|
17
|
+
const { REPO_ROOT, SCRIPT_DIR, installPaths, scopeOf, scopeSelectionState } = require('../shared.js');
|
|
18
18
|
|
|
19
|
-
function cmdStatus(o
|
|
19
|
+
function cmdStatus(o ) {
|
|
20
20
|
const targets = resolveTargets(o.targets);
|
|
21
21
|
const scope = scopeOf(o);
|
|
22
22
|
const dirs = toolDirs(scope);
|
|
23
23
|
const lifecyclePaths = installPaths(scope);
|
|
24
|
-
const ctx
|
|
24
|
+
const ctx = resolveContext({ repoRoot: REPO_ROOT, targets, dirs, sourceCommit: sourceCommit(SCRIPT_DIR), ...scope });
|
|
25
25
|
const manifest = readInstallManifest({ scopeRoot: lifecyclePaths.scopeRoot });
|
|
26
|
-
let registryView
|
|
26
|
+
let registryView = null;
|
|
27
27
|
// Per MCP-capable target, the servers doflow.lock records for it, or null when it records none.
|
|
28
|
-
let mcpSelections
|
|
28
|
+
let mcpSelections = null;
|
|
29
29
|
try {
|
|
30
30
|
const registry = loadRegistry({ repoRoot: REPO_ROOT });
|
|
31
31
|
const { lock, ledger, manifestServers } = scopeSelectionState(scope);
|
|
32
32
|
const recorded = recordedMcpSelections({ registry, lock, ledger, targets, manifestServers });
|
|
33
33
|
const rows = pinnedSelections(lock);
|
|
34
|
-
mcpSelections = Object.fromEntries(targets.filter((harness
|
|
35
|
-
.map((harness
|
|
34
|
+
mcpSelections = Object.fromEntries(targets.filter((harness ) => mcpCapable(registry, harness))
|
|
35
|
+
.map((harness ) => [harness, rows[harness] ?? null]));
|
|
36
36
|
registryView = registryLifecycleView({ registry, repoRoot: REPO_ROOT, scope, dirs, targets,
|
|
37
37
|
mcpSelections: recorded.selections, mcpAdoptable: recorded.adoptable, retainedMcpIds: recorded.retainedMcpIds });
|
|
38
38
|
ctx.registry = {
|
|
@@ -46,17 +46,17 @@ function cmdStatus(o: any): void {
|
|
|
46
46
|
// registryView.plan.changes/conflicts across every target — otherwise, e.g., Codex having
|
|
47
47
|
// pending changes when it isn't installed yet would make Claude's line falsely report
|
|
48
48
|
// 'drift-or-pending-change' even though Claude itself has nothing pending.
|
|
49
|
-
const harnessPlan = (harness
|
|
49
|
+
const harnessPlan = (harness ) => registryView.plan.targets.find((target ) => target.harness === harness);
|
|
50
50
|
// Hook-wiring status needs the same general per-harness verification every install/update run
|
|
51
51
|
// already flows through (src/lifecycle's verifyLifecycle) rather than a Codex-only hardcode:
|
|
52
52
|
// it is the one place that can tell 'installed and active' apart from 'installed but pending a
|
|
53
53
|
// prerequisite' (Codex's unreviewed trust, Gemini's live hook-trust check) from 'absent'.
|
|
54
54
|
const verification = verifyLifecycle({ plan: registryView.plan, adapters: registryView.adapters, context: { registry } });
|
|
55
|
-
const hooksFor = (harness
|
|
56
|
-
const harnessStatus = (harness
|
|
55
|
+
const hooksFor = (harness ) => verification.verifications.find((item ) => item.harness === harness)?.hookWiring ?? null;
|
|
56
|
+
const harnessStatus = (harness ) => {
|
|
57
57
|
const target = harnessPlan(harness);
|
|
58
58
|
if (!target) return { status: 'verified', resources: [], errors: [], hooks: hooksFor(harness) };
|
|
59
|
-
const resources = registryView.ledger.resources.filter((resource
|
|
59
|
+
const resources = registryView.ledger.resources.filter((resource ) => resource.harness === harness);
|
|
60
60
|
// A conflict is reported first: a user-owned file in the way is not the same as nothing being
|
|
61
61
|
// installed. With no conflict, a harness the ledger owns nothing of was never installed: its
|
|
62
62
|
// whole plan is pending, which is not drift from an installation that does not exist.
|
|
@@ -75,7 +75,7 @@ function cmdStatus(o: any): void {
|
|
|
75
75
|
for (const harness of LIFECYCLE_HARNESSES) {
|
|
76
76
|
if (targets.includes(harness)) ctx[harness] = harnessStatus(harness);
|
|
77
77
|
}
|
|
78
|
-
} catch (error
|
|
78
|
+
} catch (error ) {
|
|
79
79
|
// Status must remain usable for an existing installation even if a local registry is invalid.
|
|
80
80
|
ctx.registry = { status: 'invalid', error: error.message };
|
|
81
81
|
}
|
|
@@ -85,7 +85,7 @@ function cmdStatus(o: any): void {
|
|
|
85
85
|
return;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
const hookLine = (label
|
|
88
|
+
const hookLine = (label , hooks ) => {
|
|
89
89
|
if (!hooks || hooks.status === 'absent') return null;
|
|
90
90
|
const prereqSuffix = hooks.prerequisites.length ? ` (unmet: ${hooks.prerequisites.join(', ')})` : '';
|
|
91
91
|
return ` ${label} hooks: ${hooks.status}${prereqSuffix}`;
|
|
@@ -104,7 +104,7 @@ function cmdStatus(o: any): void {
|
|
|
104
104
|
console.log(` Last backup ID: ${manifest.backupId}`);
|
|
105
105
|
console.log(` Script version: ${manifest.scriptVersion}`);
|
|
106
106
|
if (mcpSelections && Object.keys(mcpSelections).length) {
|
|
107
|
-
const recordedText = (ids
|
|
107
|
+
const recordedText = (ids ) => (ids === null ? 'not recorded' : ids.join(', ') || 'none');
|
|
108
108
|
console.log(` MCP selections: ${Object.entries(mcpSelections).map(([harness, ids]) => `${harness} ${recordedText(ids)}`).join('; ')}`);
|
|
109
109
|
}
|
|
110
110
|
// Printed in the same order LIFECYCLE_HARNESSES declares, so every wired harness gets a line —
|
|
@@ -2,34 +2,34 @@
|
|
|
2
2
|
// `doflow tools` — inspect or manage registered external tools (status/install/update/uninstall).
|
|
3
3
|
// --force is deliberately unavailable: every mutation gets its own confirmation.
|
|
4
4
|
// TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
|
|
5
|
-
const { confirm, promptLine } = require('../../helper/prompt.
|
|
6
|
-
const { loadRegistry } = require('../../registry/index.
|
|
7
|
-
const { commandText, planToolLifecycle, executeToolLifecycle } = require('../../install/tool-lifecycle.
|
|
8
|
-
const { REPO_ROOT } = require('../shared.
|
|
5
|
+
const { confirm, promptLine } = require('../../helper/prompt.js');
|
|
6
|
+
const { loadRegistry } = require('../../registry/index.js');
|
|
7
|
+
const { commandText, planToolLifecycle, executeToolLifecycle } = require('../../install/tool-lifecycle.js');
|
|
8
|
+
const { REPO_ROOT } = require('../shared.js');
|
|
9
9
|
|
|
10
|
-
function selectExternalTools(registry
|
|
10
|
+
function selectExternalTools(registry , o ) {
|
|
11
11
|
let requested = o.tools;
|
|
12
12
|
if (!requested) {
|
|
13
13
|
const interactive = Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY);
|
|
14
14
|
if (!interactive) throw new Error("doflow tools: --tool is required when stdin is not an interactive terminal");
|
|
15
15
|
const answer = promptLine('Select tools (rtk, graphify; comma-separated): ');
|
|
16
|
-
requested = answer.split(',').map((item
|
|
16
|
+
requested = answer.split(',').map((item ) => item.trim()).filter(Boolean);
|
|
17
17
|
}
|
|
18
18
|
if (!requested.length) throw new Error('doflow tools: select at least one tool');
|
|
19
|
-
const available = new Set(registry.externalTools.map((tool
|
|
19
|
+
const available = new Set(registry.externalTools.map((tool ) => tool.id));
|
|
20
20
|
const unknown = [...new Set(requested)].filter((id) => !available.has(id));
|
|
21
21
|
if (unknown.length) throw new Error(`doflow tools: unknown tool id(s): ${unknown.join(', ')}; expected: ${[...available].join(', ')}`);
|
|
22
22
|
const wanted = new Set(requested);
|
|
23
|
-
return registry.externalTools.filter((tool
|
|
23
|
+
return registry.externalTools.filter((tool ) => wanted.has(tool.id));
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
function toolJsonResults(plan
|
|
27
|
-
const executed = new Map((execution?.results || []).map((result
|
|
28
|
-
return plan.tools.map((item
|
|
26
|
+
function toolJsonResults(plan , execution = null) {
|
|
27
|
+
const executed = new Map((execution?.results || []).map((result ) => [result.tool, result]));
|
|
28
|
+
return plan.tools.map((item ) => ({
|
|
29
29
|
tool: item.tool.id,
|
|
30
30
|
state: item.state,
|
|
31
31
|
inspections: item.inspections,
|
|
32
|
-
prerequisites: item.prerequisites.map((prerequisite
|
|
32
|
+
prerequisites: item.prerequisites.map((prerequisite ) => ({ name: prerequisite.name, available: prerequisite.available })),
|
|
33
33
|
action: item.action,
|
|
34
34
|
result: executed.get(item.tool.id) ?? (item.action.applicable
|
|
35
35
|
? { tool: item.tool.id, status: 'not-attempted', command: [...item.action.command] }
|
|
@@ -37,7 +37,7 @@ function toolJsonResults(plan: any, execution: any = null): any[] {
|
|
|
37
37
|
}));
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
function cmdTools(o
|
|
40
|
+
function cmdTools(o ) {
|
|
41
41
|
if (o.force) throw new Error("doflow tools: --force is not supported; each lifecycle command requires its own confirmation");
|
|
42
42
|
if (!['status', 'install', 'update', 'uninstall'].includes(o.action)) {
|
|
43
43
|
throw new Error(`doflow tools: unsupported action '${o.action}'; expected: status, install, update, uninstall`);
|
|
@@ -72,12 +72,12 @@ function cmdTools(o: any): void {
|
|
|
72
72
|
|
|
73
73
|
const execution = executeToolLifecycle({
|
|
74
74
|
plan,
|
|
75
|
-
displayCommand: (command
|
|
76
|
-
confirmCommand: (command
|
|
75
|
+
displayCommand: (command , tool ) => console.error(`[INFO] ${tool.displayName}: ${commandText(command)}`),
|
|
76
|
+
confirmCommand: (command , tool , action ) => confirm(`Run ${tool.displayName} ${action}: ${commandText(command)}?`, false),
|
|
77
77
|
});
|
|
78
78
|
// Keep processing independent tools so the user receives every outcome, but make a confirmed
|
|
79
79
|
// command failure visible to scripts and CI through the process result as well as the report.
|
|
80
|
-
const hasFailures = execution.results.some((result
|
|
80
|
+
const hasFailures = execution.results.some((result ) => result.status === 'failed');
|
|
81
81
|
if (o.json) {
|
|
82
82
|
console.log(JSON.stringify({ action: o.action, dryRun: false, results: toolJsonResults(plan, execution) }, null, 2));
|
|
83
83
|
if (hasFailures) process.exitCode = 1;
|
|
@@ -4,30 +4,30 @@
|
|
|
4
4
|
// TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
|
|
5
5
|
const os = require('node:os');
|
|
6
6
|
const path = require('node:path');
|
|
7
|
-
const { resolveTargets, toolDirs } = require('../../install/targets.
|
|
8
|
-
const { resolveContext, printContext } = require('../../install/context.
|
|
9
|
-
const { DEFAULT_BACKUP_RETENTION, createFileBackup, applyRetention, retentionNote } = require('../../install/backup.
|
|
10
|
-
const { backupSetFromPlan } = require('../../install/backup-set.
|
|
11
|
-
const { ledgerPath } = require('../../state/index.
|
|
12
|
-
const { backupStep, reportBackup, printBackupDryRun, applyBackupRetention } = require('./install.
|
|
13
|
-
const { writeManifest, readInstallManifest } = require('../../install/manifest.
|
|
14
|
-
const { confirm } = require('../../helper/prompt.
|
|
15
|
-
const { sourceCommit } = require('../../helper/git.
|
|
16
|
-
const { chmodHooksExecutable } = require('../../helper/settings-scope.
|
|
17
|
-
const { resolveMcpSelections } = require('../../install/mcp.
|
|
18
|
-
const { loadRegistry } = require('../../registry/index.
|
|
19
|
-
const { storageAfterInstall } = require('../../runtime/storage/upkeep.
|
|
20
|
-
const { applyLifecycle, recordMcpOwnership, retentionSummary } = require('../../lifecycle/index.
|
|
7
|
+
const { resolveTargets, toolDirs } = require('../../install/targets.js');
|
|
8
|
+
const { resolveContext, printContext } = require('../../install/context.js');
|
|
9
|
+
const { DEFAULT_BACKUP_RETENTION, createFileBackup, applyRetention, retentionNote } = require('../../install/backup.js');
|
|
10
|
+
const { backupSetFromPlan } = require('../../install/backup-set.js');
|
|
11
|
+
const { ledgerPath } = require('../../state/index.js');
|
|
12
|
+
const { backupStep, reportBackup, printBackupDryRun, applyBackupRetention } = require('./install.js');
|
|
13
|
+
const { writeManifest, readInstallManifest } = require('../../install/manifest.js');
|
|
14
|
+
const { confirm } = require('../../helper/prompt.js');
|
|
15
|
+
const { sourceCommit } = require('../../helper/git.js');
|
|
16
|
+
const { chmodHooksExecutable } = require('../../helper/settings-scope.js');
|
|
17
|
+
const { resolveMcpSelections } = require('../../install/mcp.js');
|
|
18
|
+
const { loadRegistry } = require('../../registry/index.js');
|
|
19
|
+
const { storageAfterInstall } = require('../../runtime/storage/upkeep.js');
|
|
20
|
+
const { applyLifecycle, recordMcpOwnership, retentionSummary } = require('../../lifecycle/index.js');
|
|
21
21
|
const {
|
|
22
22
|
codexScope, registryLifecycleView, printRegistryLifecycle, printPlanNotices, assertSafeRegistryPlan,
|
|
23
23
|
lockDocument, lockDelta, recordLock,
|
|
24
|
-
} = require('../../lifecycle/view.
|
|
24
|
+
} = require('../../lifecycle/view.js');
|
|
25
25
|
const {
|
|
26
26
|
REPO_ROOT, SCRIPT_DIR, pkg, scopeOf, installPaths, reportRetiredMcp, scopeSelectionState, printMcpSelection, plannedMcpSelections,
|
|
27
27
|
printRecordedMcpOwnership, buildAdapterRegistry, refuseHomeRootedProject, holdRunLock, checkpointRunLock,
|
|
28
|
-
} = require('../shared.
|
|
28
|
+
} = require('../shared.js');
|
|
29
29
|
|
|
30
|
-
function cmdUpdate(o
|
|
30
|
+
function cmdUpdate(o ) {
|
|
31
31
|
refuseHomeRootedProject(o, 'update');
|
|
32
32
|
const targets = resolveTargets(o.targets);
|
|
33
33
|
const scope = scopeOf(o);
|
|
@@ -51,7 +51,7 @@ function cmdUpdate(o: any): void {
|
|
|
51
51
|
// One lifecycle view across every requested target — computed unconditionally (not only under
|
|
52
52
|
// --dry-run) so its safety gate and its plan are the exact same object the real apply below uses.
|
|
53
53
|
const lifecycleView = registryLifecycleView({ registry, repoRoot: REPO_ROOT, scope, dirs, targets,
|
|
54
|
-
mcpSelections: selection.selections, mcpAdoptable: selection.adoptable, retainedMcpIds: selection.retainedMcpIds,
|
|
54
|
+
mcpSelections: selection.selections, mcpAdoptable: selection.adoptable, retainedMcpIds: selection.retainedMcpIds, operation: 'update',
|
|
55
55
|
force: o.force, permissions: o.permissions === true, statusline: o.statusline === true });
|
|
56
56
|
if (!lifecycleView.plan.safe) { assertSafeRegistryPlan(lifecycleView); return; }
|
|
57
57
|
printMcpSelection(lifecycleView, selection.sources, { requested: o.mcp, prefix: o.dryRun ? '[DRY]' : '[INFO]' });
|
|
@@ -69,7 +69,7 @@ function cmdUpdate(o: any): void {
|
|
|
69
69
|
const keep = o.prune ?? DEFAULT_BACKUP_RETENTION;
|
|
70
70
|
|
|
71
71
|
const lockArgs = scope.global ? { scope: 'global', homeDir: os.homedir() } : { scope: 'project', projectRoot: path.resolve(scope.projectRoot) };
|
|
72
|
-
const nextLock = (ledgerAfter
|
|
72
|
+
const nextLock = (ledgerAfter ) => lockDocument({
|
|
73
73
|
registry, scope: codexScope(scope), scopeRoot: scope.global ? os.homedir() : path.resolve(scope.projectRoot),
|
|
74
74
|
previous: lock, ledger: ledgerAfter, plannedTargets: targets, mcpSelections: plannedMcpSelections(lifecycleView),
|
|
75
75
|
});
|
|
@@ -136,7 +136,7 @@ function cmdUpdate(o: any): void {
|
|
|
136
136
|
stateRoot: lifecycleView.stateRoot, ledger: lifecycleView.ledger });
|
|
137
137
|
for (const target of lifecycleView.plan.targets) {
|
|
138
138
|
if (target.skipped || !target.changes.length) continue;
|
|
139
|
-
const owned = result.ledger.resources.filter((resource
|
|
139
|
+
const owned = result.ledger.resources.filter((resource ) => resource.harness === target.harness).length;
|
|
140
140
|
console.log(`[INFO] ${target.harness}: lifecycle verified (${owned} owned resource(s))`);
|
|
141
141
|
}
|
|
142
142
|
printPlanNotices(lifecycleView);
|
|
@@ -11,25 +11,25 @@
|
|
|
11
11
|
const {
|
|
12
12
|
handleCapabilitiesCommand, handleReadinessCommand, handleEvidenceCommand,
|
|
13
13
|
EVIDENCE_SCORE_FIELDS, scoreFieldRefusal,
|
|
14
|
-
} = require('../runtime/cli.
|
|
15
|
-
const { pkg } = require('./shared.
|
|
16
|
-
const { VALID: VALID_TARGETS, DEFAULT_TARGETS } = require('../install/targets.
|
|
17
|
-
const { dispatchRuntimeCommand } = require('./runtime-commands.
|
|
18
|
-
const { usageError } = require('../runtime/cli-result.
|
|
14
|
+
} = require('../runtime/cli.js');
|
|
15
|
+
const { pkg } = require('./shared.js');
|
|
16
|
+
const { VALID: VALID_TARGETS, DEFAULT_TARGETS } = require('../install/targets.js');
|
|
17
|
+
const { dispatchRuntimeCommand } = require('./runtime-commands.js');
|
|
18
|
+
const { usageError } = require('../runtime/cli-result.js');
|
|
19
19
|
|
|
20
|
-
const cmdInstall = require('./commands/install.
|
|
21
|
-
const cmdUpdate = require('./commands/update.
|
|
22
|
-
const cmdReconcile = require('./commands/reconcile.
|
|
23
|
-
const cmdRemove = require('./commands/remove.
|
|
24
|
-
const cmdStatus = require('./commands/status.
|
|
25
|
-
const cmdTools = require('./commands/tools.
|
|
26
|
-
const cmdListBackups = require('./commands/list-backups.
|
|
27
|
-
const cmdRollback = require('./commands/rollback.
|
|
28
|
-
const cmdSelfUpdate = require('./commands/self-update.
|
|
20
|
+
const cmdInstall = require('./commands/install.js');
|
|
21
|
+
const cmdUpdate = require('./commands/update.js');
|
|
22
|
+
const cmdReconcile = require('./commands/reconcile.js');
|
|
23
|
+
const cmdRemove = require('./commands/remove.js');
|
|
24
|
+
const cmdStatus = require('./commands/status.js');
|
|
25
|
+
const cmdTools = require('./commands/tools.js');
|
|
26
|
+
const cmdListBackups = require('./commands/list-backups.js');
|
|
27
|
+
const cmdRollback = require('./commands/rollback.js');
|
|
28
|
+
const cmdSelfUpdate = require('./commands/self-update.js');
|
|
29
29
|
|
|
30
30
|
/** The installer command surface, written down once. The runtime verbs are dispatched separately
|
|
31
31
|
* (see ./runtime-commands) because their namespace is owned by the doflow-run verb table. */
|
|
32
|
-
const COMMANDS
|
|
32
|
+
const COMMANDS = {
|
|
33
33
|
install: cmdInstall,
|
|
34
34
|
update: cmdUpdate,
|
|
35
35
|
reconcile: cmdReconcile,
|
|
@@ -42,15 +42,15 @@ const COMMANDS: Record<string, (o: any) => any> = {
|
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
/** "skip all backup protection" must be an explicit, deliberate choice, never a default combo. */
|
|
45
|
-
function assertNoBackupRequiresForce(o
|
|
45
|
+
function assertNoBackupRequiresForce(o ) {
|
|
46
46
|
if (o.noBackup && !o.force) {
|
|
47
47
|
console.error('doflow: --no-backup skips all backup protection and requires --force');
|
|
48
48
|
process.exit(1);
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
function parseArgs(argv
|
|
53
|
-
const o
|
|
52
|
+
function parseArgs(argv ) {
|
|
53
|
+
const o = { cmd: null, positional: [], targets: [], mcp: null, dryRun: false, force: false, adopt: false,
|
|
54
54
|
noBackup: false, prune: null, global: false, json: false, help: false, version: false,
|
|
55
55
|
tools: null, action: 'status', days: null, slug: null,
|
|
56
56
|
// Explicitly null, not absent. `handleReadinessCommand` declares defaults of `'feature'` and
|
|
@@ -70,6 +70,8 @@ function parseArgs(argv: string[]): any {
|
|
|
70
70
|
case '--permissions': o.permissions = true; break;
|
|
71
71
|
case '--statusline': o.statusline = true; break;
|
|
72
72
|
case '--json': o.json = true; break;
|
|
73
|
+
case '--bare': o.bare = true; break;
|
|
74
|
+
case '--no-record': o.noRecord = true; break;
|
|
73
75
|
case '--check': o.check = true; break;
|
|
74
76
|
// decision --action list: every decision by id, not just the live ones.
|
|
75
77
|
case '--all': o.all = true; break;
|
|
@@ -136,6 +138,7 @@ function parseArgs(argv: string[]): any {
|
|
|
136
138
|
o.node = val; i++; break;
|
|
137
139
|
}
|
|
138
140
|
case '--forced': o.forced = true; break;
|
|
141
|
+
case '--absence': o.absence = true; break;
|
|
139
142
|
case '--decision': {
|
|
140
143
|
const val = argv[i + 1];
|
|
141
144
|
if (val === undefined || val.startsWith('-')) { console.error(`doflow: ${a} requires a value`); process.exit(1); }
|
|
@@ -258,6 +261,9 @@ const RUNTIME_STRING_FLAGS = new Map([
|
|
|
258
261
|
// change scope, <path>[,<path>...], unioned with the plan's bound
|
|
259
262
|
['--invariants', 'invariants'], // readiness: the invariants a refactor must preserve
|
|
260
263
|
['--objective', 'objective'], // context-pack
|
|
264
|
+
['--mandatory-file', 'mandatoryFile'], // context-pack: caller-supplied mandatory fields
|
|
265
|
+
['--max-bytes', 'maxBytes'], // context-pack: per-call cap in bytes
|
|
266
|
+
['--expand', 'expand'], // context-pack: pointer id to expand
|
|
261
267
|
['--stage-id', 'stageId'], // research-request: active feature stage
|
|
262
268
|
['--question', 'question'], // research-request: external question
|
|
263
269
|
['--blocking', 'blocking'], // research-request: true | false
|
|
@@ -266,6 +272,7 @@ const RUNTIME_STRING_FLAGS = new Map([
|
|
|
266
272
|
['--gap', 'gap'], // research-request: unresolved reason
|
|
267
273
|
['--stage', 'stage'], // retrieval-plan: the stage id declaring the plan;
|
|
268
274
|
// outcome: the stage writing it, refused unless terminal
|
|
275
|
+
['--status', 'attemptStatus'], // retrieval-plan: attempt status (EMPTY|UNREACHED|UNVERIFIED)
|
|
269
276
|
['--state', 'state'], // outcome: the terminal state being recorded
|
|
270
277
|
['--result', 'result'], // orchestrate complete-stage: the stage's own outcome, passed | failed (omit → unverified)
|
|
271
278
|
// outcome: the verdicts the run saw, stated by it and validated against the vocabulary the
|
|
@@ -281,6 +288,8 @@ const RUNTIME_STRING_FLAGS = new Map([
|
|
|
281
288
|
['--owner', 'owner'], // brief-tools: the agent type the brief is for
|
|
282
289
|
['--tier', 'tier'], // brief-tools: the task line's tier (light | standard | frontier)
|
|
283
290
|
['--harness', 'harness'], // brief-tools: the harness the brief is for
|
|
291
|
+
['--policy', 'policy'], // enforcement: lifecycle policy id
|
|
292
|
+
['--profile', 'profile'], // enforcement: coverage profile filter
|
|
284
293
|
['--heading-level', 'headingLevel'], // brief-tools: 2 (default) or 3
|
|
285
294
|
['--tasks', 'tasks'], // brief-tools: comma-separated plan task ids for tier advice
|
|
286
295
|
['--plan-path', 'planPath'], // verify: a feature plan.md whose doflow-verification
|
|
@@ -324,12 +333,12 @@ const RUNTIME_INT_FLAGS = new Map([
|
|
|
324
333
|
*
|
|
325
334
|
* Returns the new loop index, or null when `arg` is not a runtime flag.
|
|
326
335
|
*/
|
|
327
|
-
function parseRuntimeFlag(arg
|
|
336
|
+
function parseRuntimeFlag(arg , argv , i , o ) {
|
|
328
337
|
const eq = arg.indexOf('=');
|
|
329
338
|
const name = eq === -1 ? arg : arg.slice(0, eq);
|
|
330
339
|
// A score-shaped flag is refused by name rather than falling through to "unknown flag", which
|
|
331
340
|
// reads as "not built yet" and invites someone to build it. The name set and the reason both
|
|
332
|
-
// come from the evidence write boundary (src/runtime/cli.
|
|
341
|
+
// come from the evidence write boundary (src/runtime/cli.js), so argv and a --batch JSON file
|
|
333
342
|
// are refused by one rule with two enforcement points rather than two rules.
|
|
334
343
|
const camel = name.replace(/^--/, '').replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
335
344
|
if (EVIDENCE_SCORE_FIELDS.has(camel)) { console.error(`doflow: ${scoreFieldRefusal(name)}`); process.exit(2); }
|
|
@@ -337,7 +346,7 @@ function parseRuntimeFlag(arg: string, argv: string[], i: number, o: any): numbe
|
|
|
337
346
|
const key = RUNTIME_STRING_FLAGS.get(name) || RUNTIME_LIST_FLAGS.get(name) || RUNTIME_INT_FLAGS.get(name);
|
|
338
347
|
if (!key) return null;
|
|
339
348
|
|
|
340
|
-
let value
|
|
349
|
+
let value = inline;
|
|
341
350
|
let next = i;
|
|
342
351
|
if (value === null) {
|
|
343
352
|
value = argv[i + 1];
|
|
@@ -363,7 +372,7 @@ function parseRuntimeFlag(arg: string, argv: string[], i: number, o: any): numbe
|
|
|
363
372
|
// spelling's comma-splitting, this generic path handling both spellings but never splitting),
|
|
364
373
|
// so `--exclude=bin,src` silently excluded nothing while `--exclude bin,src` worked. One path,
|
|
365
374
|
// both spellings, same behavior now.
|
|
366
|
-
const parts = name === '--exclude' ? value.split(',').map((s
|
|
375
|
+
const parts = name === '--exclude' ? value.split(',').map((s ) => s.trim()).filter(Boolean) : [value];
|
|
367
376
|
(o[key] = o[key] || []).push(...parts);
|
|
368
377
|
} else if (name === '--evidence-id' && o.cmd === 'research-request') {
|
|
369
378
|
(o.evidenceIds = o.evidenceIds || []).push(value);
|
|
@@ -388,12 +397,13 @@ Commands:
|
|
|
388
397
|
self-update git pull + reinstall
|
|
389
398
|
tools Inspect or manage registered external tools
|
|
390
399
|
capabilities Show registered abstract capabilities and resolved providers
|
|
400
|
+
enforcement Report lifecycle policy enforcement coverage (--harness, --policy)
|
|
391
401
|
doctor System health and capability smoke check diagnostics
|
|
392
402
|
readiness Evaluate task readiness contract (--task-class, --task-id, both required)
|
|
393
403
|
evidence Record a stage's evidence batch, or inspect what is recorded (--task-id)
|
|
394
404
|
claim Record a claim, link evidence to it, or list them (--task-id, --action)
|
|
395
405
|
context-pack Compile a task's evidence and claims into a context block (--task-id)
|
|
396
|
-
retrieval-plan Declare a stage's information needs, then report every declared item
|
|
406
|
+
retrieval-plan Declare a stage's information needs, attempt retrieval, then report every declared item
|
|
397
407
|
outcome Record a task's terminal state with its basis, or show it (--task-id)
|
|
398
408
|
classify Validate a proposed task class and return its workflow (--task-class)
|
|
399
409
|
workflow Resolve a task class to its stages, gates and readiness templates
|
|
@@ -453,7 +463,7 @@ Runtime verb arguments (accept --flag value or --flag=value):
|
|
|
453
463
|
--task-class classify, workflow, readiness, context-pack, outcome --action record
|
|
454
464
|
--task-id readiness, evidence, claim, context-pack, retrieval-plan, outcome, verify, advise
|
|
455
465
|
--action claim: list|add|link|retract|supersede · evidence: list|add|supersede
|
|
456
|
-
verify: report|contract · retrieval-plan: declare|report
|
|
466
|
+
verify: report|contract · retrieval-plan: declare|report|attempt
|
|
457
467
|
outcome: record|show · advise: ask|outcome|configure · tools: see above
|
|
458
468
|
followup: add|list|take|settle|promote|report
|
|
459
469
|
task-attempt: claim|finish|release|status
|
|
@@ -470,7 +480,9 @@ Runtime verb arguments (accept --flag value or --flag=value):
|
|
|
470
480
|
--statement, --claim-id,
|
|
471
481
|
--evidence-id, --relation claim
|
|
472
482
|
--kind, --provenance, --provider,
|
|
473
|
-
--capability, --locator, --content
|
|
483
|
+
--capability, --locator, --content,
|
|
484
|
+
--absence evidence --action add (one item)
|
|
485
|
+
--need <intent> evidence --action add (bind evidence to retrieval needs)
|
|
474
486
|
--batch <file|-> evidence --action add (a stage's JSON batch)
|
|
475
487
|
--evidence-id, --replaced-by evidence --action supersede (retire one item, point
|
|
476
488
|
forward to the item that replaces it)
|
|
@@ -480,7 +492,7 @@ Runtime verb arguments (accept --flag value or --flag=value):
|
|
|
480
492
|
evidence establishes; reported back as such
|
|
481
493
|
--objective context-pack
|
|
482
494
|
--need <intent[,intent]>,
|
|
483
|
-
--stage
|
|
495
|
+
--stage, --status retrieval-plan (--need is repeatable), outcome
|
|
484
496
|
--mcp-outcome <server>=<outcome> orchestrate --action handoff, repeatable: used | nothing-usable |
|
|
485
497
|
skipped:<reason> | unavailable (a server left out only warns)
|
|
486
498
|
--state <COMPLETED|BLOCKED|
|
|
@@ -527,14 +539,14 @@ External tools:
|
|
|
527
539
|
const COMMAND_NAMES = new Set([...Object.keys(COMMANDS), ...[...HELP.matchAll(/^ ([a-z][a-z-]*) {2,}\S/gm)].map((m) => m[1])]);
|
|
528
540
|
|
|
529
541
|
/** `name` when it is one of DoFlow's own command names, else `unknown`. */
|
|
530
|
-
function commandName(name
|
|
542
|
+
function commandName(name ) { return typeof name === 'string' && COMMAND_NAMES.has(name) ? name : 'unknown'; }
|
|
531
543
|
|
|
532
544
|
/**
|
|
533
545
|
* Run one CLI invocation. Same behavior as the pre-extraction monolith's main(): --version and
|
|
534
546
|
* --help answer first, --no-backup-without-force is refused, then the command resolves either
|
|
535
547
|
* through the installer table above or through the runtime-verb dispatcher.
|
|
536
548
|
*/
|
|
537
|
-
async function main(argv
|
|
549
|
+
async function main(argv ) {
|
|
538
550
|
const o = parseArgs(argv);
|
|
539
551
|
if (o.version) { console.log(pkg.version); return; }
|
|
540
552
|
if (o.help || !o.cmd) { console.log(HELP); return; }
|
|
@@ -546,11 +558,11 @@ async function main(argv: string[]): Promise<any> {
|
|
|
546
558
|
const handler = COMMANDS[o.cmd];
|
|
547
559
|
if (handler) return handler(o);
|
|
548
560
|
return await dispatchRuntimeCommand(o);
|
|
549
|
-
} catch (error
|
|
561
|
+
} catch (error ) {
|
|
550
562
|
// Recorded silently when it is a programming error (IC-016); the output and exit status below
|
|
551
563
|
// are the same whether or not anything was written.
|
|
552
564
|
// Required here, not at load, so a CLI whose failure modules cannot be loaded still runs as today.
|
|
553
|
-
try { require('../runtime/failure/capture.
|
|
565
|
+
try { require('../runtime/failure/capture.js').captureError(error, { command: commandName(o.cmd), exit: 1 }); } catch { /* best-effort */ }
|
|
554
566
|
// A lifecycle apply/remove can throw mid-mutation (fs error, TOCTOU ownership mismatch on a
|
|
555
567
|
// multi-harness run) — surface a clean, actionable message instead of a raw stack trace, and
|
|
556
568
|
// point at the recovery record applyLifecycle already wrote before rethrowing.
|
|
@@ -565,4 +577,4 @@ async function main(argv: string[]): Promise<any> {
|
|
|
565
577
|
}
|
|
566
578
|
}
|
|
567
579
|
|
|
568
|
-
module.exports = { main, COMMANDS, commandName };
|
|
580
|
+
module.exports = { main, COMMANDS, commandName, parseArgs };
|