@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
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
const fs = require('node:fs');
|
|
6
6
|
const path = require('node:path');
|
|
7
|
-
const { parseYamlFile } = require('./capability-router.
|
|
8
|
-
const { finishRuntime, usageError } = require('./cli-result.
|
|
9
|
-
const { REPO_ROOT } = require('../helper/repo-root.
|
|
7
|
+
const { parseYamlFile } = require('./capability-router.js');
|
|
8
|
+
const { finishRuntime, usageError } = require('./cli-result.js');
|
|
9
|
+
const { REPO_ROOT } = require('../helper/repo-root.js');
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -32,17 +32,17 @@ const READINESS_REGISTRY_FILE = 'readiness-templates.json';
|
|
|
32
32
|
const CALLER_ROLES = Object.freeze({ ROUTER: 'router', STAGE: 'stage', STANDALONE: 'standalone' });
|
|
33
33
|
const CALLER_ROLE_VALUES = Object.freeze(Object.values(CALLER_ROLES));
|
|
34
34
|
|
|
35
|
-
function isPlainObject(value
|
|
35
|
+
function isPlainObject(value ) {
|
|
36
36
|
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
function isNonEmptyString(value
|
|
39
|
+
function isNonEmptyString(value ) {
|
|
40
40
|
return typeof value === 'string' && value.trim().length > 0;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/** Accepts the several shapes a caller may already hold readiness templates in: the parsed
|
|
44
44
|
* registry document, its `templates` map, a Set, or a plain list of names. */
|
|
45
|
-
function normalizeTemplateNames(input
|
|
45
|
+
function normalizeTemplateNames(input ) {
|
|
46
46
|
if (Array.isArray(input)) return new Set(input);
|
|
47
47
|
if (input instanceof Set) return new Set(input);
|
|
48
48
|
if (isPlainObject(input)) {
|
|
@@ -55,7 +55,7 @@ function normalizeTemplateNames(input: any) {
|
|
|
55
55
|
);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
function deepFreeze(value
|
|
58
|
+
function deepFreeze(value ) {
|
|
59
59
|
if (!value || typeof value !== 'object' || Object.isFrozen(value)) return value;
|
|
60
60
|
Object.freeze(value);
|
|
61
61
|
for (const key of Object.keys(value)) deepFreeze(value[key]);
|
|
@@ -63,15 +63,15 @@ function deepFreeze(value: any) {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
class WorkflowEngine {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
75
|
/**
|
|
76
76
|
* @param {Object} [options]
|
|
77
77
|
* @param {string} [options.repoRoot]
|
|
@@ -83,7 +83,7 @@ class WorkflowEngine {
|
|
|
83
83
|
* registry itself came from disk, so an injected document never forces a filesystem read.
|
|
84
84
|
* @param {Object} [options.fsImpl]
|
|
85
85
|
*/
|
|
86
|
-
constructor(options
|
|
86
|
+
constructor(options = {}) {
|
|
87
87
|
this.fsImpl = options.fsImpl || fs;
|
|
88
88
|
this.repoRoot = options.repoRoot || REPO_ROOT;
|
|
89
89
|
this.registryPath = options.registryPath
|
|
@@ -141,7 +141,7 @@ class WorkflowEngine {
|
|
|
141
141
|
* @param {Set<string>|null} [options.readinessTemplates]
|
|
142
142
|
* @returns {Array<string>}
|
|
143
143
|
*/
|
|
144
|
-
static validateRegistry(document
|
|
144
|
+
static validateRegistry(document , options = {}) {
|
|
145
145
|
const problems = [];
|
|
146
146
|
if (!isPlainObject(document)) {
|
|
147
147
|
return ['registry document is not an object'];
|
|
@@ -158,7 +158,7 @@ class WorkflowEngine {
|
|
|
158
158
|
}
|
|
159
159
|
if (problems.length > 0) return problems;
|
|
160
160
|
|
|
161
|
-
for (const [callerId, caller] of (Object.entries(document.callers)
|
|
161
|
+
for (const [callerId, caller] of (Object.entries(document.callers) )) {
|
|
162
162
|
if (!isPlainObject(caller)) {
|
|
163
163
|
problems.push(`caller '${callerId}' must be an object`);
|
|
164
164
|
continue;
|
|
@@ -186,7 +186,7 @@ class WorkflowEngine {
|
|
|
186
186
|
const knownTemplates = options.readinessTemplates || null;
|
|
187
187
|
const kindIds = new Set(Object.keys(document.stageKinds));
|
|
188
188
|
|
|
189
|
-
for (const [kindId, kind] of (Object.entries(document.stageKinds)
|
|
189
|
+
for (const [kindId, kind] of (Object.entries(document.stageKinds) )) {
|
|
190
190
|
if (!isPlainObject(kind)) {
|
|
191
191
|
problems.push(`stageKind '${kindId}' must be an object`);
|
|
192
192
|
continue;
|
|
@@ -199,7 +199,7 @@ class WorkflowEngine {
|
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
-
for (const [classId, definition] of (Object.entries(document.classes)
|
|
202
|
+
for (const [classId, definition] of (Object.entries(document.classes) )) {
|
|
203
203
|
if (!isPlainObject(definition)) {
|
|
204
204
|
problems.push(`class '${classId}' must be an object`);
|
|
205
205
|
continue;
|
|
@@ -220,7 +220,7 @@ class WorkflowEngine {
|
|
|
220
220
|
const stageIds = new Set();
|
|
221
221
|
let hasRequiredStage = false;
|
|
222
222
|
|
|
223
|
-
definition.stages.forEach((stage
|
|
223
|
+
definition.stages.forEach((stage , index ) => {
|
|
224
224
|
const where = `class '${classId}' stage #${index + 1}`;
|
|
225
225
|
if (!isPlainObject(stage)) {
|
|
226
226
|
problems.push(`${where} must be an object`);
|
|
@@ -321,7 +321,7 @@ class WorkflowEngine {
|
|
|
321
321
|
* @param {*} taskClass
|
|
322
322
|
* @returns {boolean} true only for an exactly-matching declared class id.
|
|
323
323
|
*/
|
|
324
|
-
hasClass(taskClass
|
|
324
|
+
hasClass(taskClass ) {
|
|
325
325
|
return typeof taskClass === 'string'
|
|
326
326
|
&& Object.prototype.hasOwnProperty.call(this.classes, taskClass);
|
|
327
327
|
}
|
|
@@ -335,7 +335,7 @@ class WorkflowEngine {
|
|
|
335
335
|
* @param {*} skillId
|
|
336
336
|
* @returns {boolean} true only for an exactly-matching declared caller id.
|
|
337
337
|
*/
|
|
338
|
-
hasCaller(skillId
|
|
338
|
+
hasCaller(skillId ) {
|
|
339
339
|
return typeof skillId === 'string'
|
|
340
340
|
&& Object.prototype.hasOwnProperty.call(this.callers, skillId);
|
|
341
341
|
}
|
|
@@ -344,7 +344,7 @@ class WorkflowEngine {
|
|
|
344
344
|
* @param {string} skillId
|
|
345
345
|
* @returns {'router'|'stage'|'standalone'|null} null when the id is not a declared caller.
|
|
346
346
|
*/
|
|
347
|
-
callerRole(skillId
|
|
347
|
+
callerRole(skillId ) {
|
|
348
348
|
return this.hasCaller(skillId) ? this.callers[skillId].role : null;
|
|
349
349
|
}
|
|
350
350
|
|
|
@@ -352,7 +352,7 @@ class WorkflowEngine {
|
|
|
352
352
|
* @param {string} skillId
|
|
353
353
|
* @returns {string|null} the declared exemption reason, or null.
|
|
354
354
|
*/
|
|
355
|
-
callerReason(skillId
|
|
355
|
+
callerReason(skillId ) {
|
|
356
356
|
if (!this.hasCaller(skillId)) return null;
|
|
357
357
|
const { reason } = this.callers[skillId];
|
|
358
358
|
return isNonEmptyString(reason) ? reason : null;
|
|
@@ -364,11 +364,11 @@ class WorkflowEngine {
|
|
|
364
364
|
* @param {string} skillId
|
|
365
365
|
* @returns {Array<string>}
|
|
366
366
|
*/
|
|
367
|
-
stagesHosting(taskClass
|
|
367
|
+
stagesHosting(taskClass , skillId ) {
|
|
368
368
|
if (typeof skillId !== 'string' || !this.hasClass(taskClass)) return [];
|
|
369
369
|
return this.resolveWorkflow(taskClass).stages
|
|
370
|
-
.filter((stage
|
|
371
|
-
.map((stage
|
|
370
|
+
.filter((stage ) => stage.skill === skillId)
|
|
371
|
+
.map((stage ) => stage.id);
|
|
372
372
|
}
|
|
373
373
|
|
|
374
374
|
/**
|
|
@@ -377,7 +377,7 @@ class WorkflowEngine {
|
|
|
377
377
|
* @param {string} skillId
|
|
378
378
|
* @returns {Array<{taskClass: string, stageIds: Array<string>}>}
|
|
379
379
|
*/
|
|
380
|
-
classesHosting(skillId
|
|
380
|
+
classesHosting(skillId ) {
|
|
381
381
|
const hosting = [];
|
|
382
382
|
for (const taskClass of this.listClasses()) {
|
|
383
383
|
const stageIds = this.stagesHosting(taskClass, skillId);
|
|
@@ -387,7 +387,7 @@ class WorkflowEngine {
|
|
|
387
387
|
}
|
|
388
388
|
|
|
389
389
|
/** @param {string} kind @returns {boolean} */
|
|
390
|
-
isImplementationKind(kind
|
|
390
|
+
isImplementationKind(kind ) {
|
|
391
391
|
const declared = this.stageKinds[kind];
|
|
392
392
|
if (!declared) {
|
|
393
393
|
throw new Error(
|
|
@@ -423,7 +423,7 @@ class WorkflowEngine {
|
|
|
423
423
|
* @param {string} taskClass
|
|
424
424
|
* @returns {Object} frozen ResolvedWorkflow
|
|
425
425
|
*/
|
|
426
|
-
resolveWorkflow(taskClass
|
|
426
|
+
resolveWorkflow(taskClass ) {
|
|
427
427
|
if (!isNonEmptyString(taskClass)) {
|
|
428
428
|
throw new Error(
|
|
429
429
|
`A task class is required to resolve a workflow (received ${JSON.stringify(taskClass)}). `
|
|
@@ -440,19 +440,19 @@ class WorkflowEngine {
|
|
|
440
440
|
}
|
|
441
441
|
|
|
442
442
|
const definition = this.classes[taskClass];
|
|
443
|
-
const gates = definition.gates.map((gate
|
|
443
|
+
const gates = definition.gates.map((gate ) => ({ ...gate }));
|
|
444
444
|
|
|
445
|
-
const stages = definition.stages.map((stage
|
|
445
|
+
const stages = definition.stages.map((stage , index ) => ({
|
|
446
446
|
...stage,
|
|
447
447
|
index,
|
|
448
448
|
mutatesSource: this.isImplementationKind(stage.kind),
|
|
449
449
|
kindDescription: this.stageKinds[stage.kind].description,
|
|
450
|
-
gatesAfter: gates.filter((gate
|
|
450
|
+
gatesAfter: gates.filter((gate ) => gate.afterStage === stage.id),
|
|
451
451
|
}));
|
|
452
452
|
|
|
453
|
-
const implementationStages = stages.filter((stage
|
|
453
|
+
const implementationStages = stages.filter((stage ) => stage.mutatesSource);
|
|
454
454
|
const readinessTemplates = [
|
|
455
|
-
...new Set(stages.map((stage
|
|
455
|
+
...new Set(stages.map((stage ) => stage.readinessTemplate).filter(Boolean)),
|
|
456
456
|
];
|
|
457
457
|
|
|
458
458
|
const workflow = deepFreeze({
|
|
@@ -463,13 +463,13 @@ class WorkflowEngine {
|
|
|
463
463
|
handoff: definition.handoff || null,
|
|
464
464
|
readinessNote: definition.readinessNote,
|
|
465
465
|
stages,
|
|
466
|
-
stageIds: stages.map((stage
|
|
467
|
-
stageSkills: [...new Set(stages.map((stage
|
|
468
|
-
requiredStageIds: stages.filter((stage
|
|
469
|
-
optionalStageIds: stages.filter((stage
|
|
466
|
+
stageIds: stages.map((stage ) => stage.id),
|
|
467
|
+
stageSkills: [...new Set(stages.map((stage ) => stage.skill))],
|
|
468
|
+
requiredStageIds: stages.filter((stage ) => !stage.optional).map((stage ) => stage.id),
|
|
469
|
+
optionalStageIds: stages.filter((stage ) => stage.optional).map((stage ) => stage.id),
|
|
470
470
|
gates,
|
|
471
|
-
gateIds: gates.map((gate
|
|
472
|
-
implementationStageIds: implementationStages.map((stage
|
|
471
|
+
gateIds: gates.map((gate ) => gate.id),
|
|
472
|
+
implementationStageIds: implementationStages.map((stage ) => stage.id),
|
|
473
473
|
hasImplementationStage: implementationStages.length > 0,
|
|
474
474
|
requiresImplementationReadiness: readinessTemplates.length > 0,
|
|
475
475
|
readinessTemplates,
|
|
@@ -485,9 +485,9 @@ class WorkflowEngine {
|
|
|
485
485
|
* @param {string} stageId
|
|
486
486
|
* @returns {Object} the resolved stage
|
|
487
487
|
*/
|
|
488
|
-
describeStage(taskClass
|
|
488
|
+
describeStage(taskClass , stageId ) {
|
|
489
489
|
const workflow = this.resolveWorkflow(taskClass);
|
|
490
|
-
const stage = workflow.stages.find((candidate
|
|
490
|
+
const stage = workflow.stages.find((candidate ) => candidate.id === stageId);
|
|
491
491
|
if (!stage) {
|
|
492
492
|
throw new Error(
|
|
493
493
|
`Unknown stage '${stageId}' for task class '${taskClass}'. `
|
|
@@ -506,7 +506,7 @@ class WorkflowEngine {
|
|
|
506
506
|
* @param {Array<string>} [completedStageIds]
|
|
507
507
|
* @returns {Object|null} the next stage, or null when the workflow is exhausted
|
|
508
508
|
*/
|
|
509
|
-
nextStage(taskClass
|
|
509
|
+
nextStage(taskClass , completedStageIds = []) {
|
|
510
510
|
const workflow = this.resolveWorkflow(taskClass);
|
|
511
511
|
if (!Array.isArray(completedStageIds)) {
|
|
512
512
|
throw new TypeError('completedStageIds must be an array of stage ids');
|
|
@@ -521,7 +521,7 @@ class WorkflowEngine {
|
|
|
521
521
|
}
|
|
522
522
|
}
|
|
523
523
|
const done = new Set(completedStageIds);
|
|
524
|
-
return workflow.stages.find((stage
|
|
524
|
+
return workflow.stages.find((stage ) => !done.has(stage.id)) || null;
|
|
525
525
|
}
|
|
526
526
|
|
|
527
527
|
/**
|
|
@@ -529,7 +529,7 @@ class WorkflowEngine {
|
|
|
529
529
|
* @param {string} stageId
|
|
530
530
|
* @returns {Array<Object>} gates that fire after the named stage
|
|
531
531
|
*/
|
|
532
|
-
gatesAfter(taskClass
|
|
532
|
+
gatesAfter(taskClass , stageId ) {
|
|
533
533
|
return this.describeStage(taskClass, stageId).gatesAfter;
|
|
534
534
|
}
|
|
535
535
|
}
|
|
@@ -546,12 +546,12 @@ class WorkflowEngine {
|
|
|
546
546
|
* @param {boolean} [options.json=false]
|
|
547
547
|
* @returns {number} exit code
|
|
548
548
|
*/
|
|
549
|
-
function handleWorkflowCommand({ taskClass, json = false }
|
|
549
|
+
function handleWorkflowCommand({ taskClass, json = false } = {}) {
|
|
550
550
|
const engine = new WorkflowEngine({ repoRoot: REPO_ROOT });
|
|
551
551
|
let workflow;
|
|
552
552
|
try {
|
|
553
553
|
workflow = engine.resolveWorkflow(taskClass);
|
|
554
|
-
} catch (error
|
|
554
|
+
} catch (error ) {
|
|
555
555
|
// The engine's own message already names every valid class; restating it here would be a
|
|
556
556
|
// second inventory to keep in step with the registry.
|
|
557
557
|
return usageError('workflow', error.message, json, error);
|