@workflow-cannon/workspace-kit 0.17.0 → 0.24.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/README.md +23 -9
- package/dist/cli/doctor-planning-issues.js +3 -22
- package/dist/cli/run-command.js +22 -38
- package/dist/cli.js +95 -4
- package/dist/contracts/command-manifest.d.ts +17 -0
- package/dist/contracts/command-manifest.js +1 -0
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/module-contract.d.ts +12 -11
- package/dist/core/agent-instruction-surface.d.ts +33 -0
- package/dist/core/agent-instruction-surface.js +46 -0
- package/dist/core/config-cli.js +13 -17
- package/dist/core/config-metadata.js +101 -2
- package/dist/core/index.d.ts +4 -1
- package/dist/core/index.js +3 -0
- package/dist/core/module-command-router.js +19 -1
- package/dist/core/module-registry-resolve.d.ts +27 -0
- package/dist/core/module-registry-resolve.js +91 -0
- package/dist/core/module-registry.d.ts +14 -0
- package/dist/core/module-registry.js +57 -0
- package/dist/core/planning/build-plan-session-file.d.ts +29 -0
- package/dist/core/planning/build-plan-session-file.js +58 -0
- package/dist/core/planning/index.d.ts +17 -0
- package/dist/core/planning/index.js +15 -0
- package/dist/core/policy.js +18 -8
- package/dist/core/state/unified-state-db.d.ts +21 -0
- package/dist/core/state/unified-state-db.js +80 -0
- package/dist/core/workspace-kit-config.js +13 -1
- package/dist/modules/agent-behavior/builtins.d.ts +3 -0
- package/dist/modules/agent-behavior/builtins.js +71 -0
- package/dist/modules/agent-behavior/explain.d.ts +6 -0
- package/dist/modules/agent-behavior/explain.js +46 -0
- package/dist/modules/agent-behavior/index.d.ts +4 -0
- package/dist/modules/agent-behavior/index.js +461 -0
- package/dist/modules/agent-behavior/interview-session-file.d.ts +9 -0
- package/dist/modules/agent-behavior/interview-session-file.js +43 -0
- package/dist/modules/agent-behavior/interview.d.ts +13 -0
- package/dist/modules/agent-behavior/interview.js +88 -0
- package/dist/modules/agent-behavior/persistence.d.ts +6 -0
- package/dist/modules/agent-behavior/persistence.js +89 -0
- package/dist/modules/agent-behavior/store.d.ts +34 -0
- package/dist/modules/agent-behavior/store.js +119 -0
- package/dist/modules/agent-behavior/types.d.ts +28 -0
- package/dist/modules/agent-behavior/types.js +1 -0
- package/dist/modules/agent-behavior/validate.d.ts +11 -0
- package/dist/modules/agent-behavior/validate.js +123 -0
- package/dist/modules/approvals/index.js +54 -51
- package/dist/modules/approvals/policy-sensitive-commands.d.ts +4 -0
- package/dist/modules/approvals/policy-sensitive-commands.js +4 -0
- package/dist/modules/approvals/review-runtime.js +1 -2
- package/dist/modules/documentation/index.js +47 -45
- package/dist/modules/documentation/normalizer.d.ts +3 -0
- package/dist/modules/documentation/normalizer.js +171 -0
- package/dist/modules/documentation/parser.d.ts +7 -0
- package/dist/modules/documentation/parser.js +39 -0
- package/dist/modules/documentation/policy-sensitive-commands.d.ts +5 -0
- package/dist/modules/documentation/policy-sensitive-commands.js +8 -0
- package/dist/modules/documentation/renderer.d.ts +23 -0
- package/dist/modules/documentation/renderer.js +105 -0
- package/dist/modules/documentation/runtime-batch.d.ts +10 -0
- package/dist/modules/documentation/runtime-batch.js +67 -0
- package/dist/modules/documentation/runtime-config.d.ts +11 -0
- package/dist/modules/documentation/runtime-config.js +54 -0
- package/dist/modules/documentation/runtime-render-support.d.ts +8 -0
- package/dist/modules/documentation/runtime-render-support.js +36 -0
- package/dist/modules/documentation/runtime.js +22 -510
- package/dist/modules/documentation/types.d.ts +182 -0
- package/dist/modules/documentation/validator.d.ts +8 -0
- package/dist/modules/documentation/validator.js +234 -0
- package/dist/modules/documentation/view-models.d.ts +3 -0
- package/dist/modules/documentation/view-models.js +124 -0
- package/dist/modules/improvement/generate-recommendations-runtime.js +3 -3
- package/dist/modules/improvement/improvement-state.d.ts +2 -2
- package/dist/modules/improvement/improvement-state.js +52 -23
- package/dist/modules/improvement/index.js +140 -138
- package/dist/modules/improvement/ingest.d.ts +1 -1
- package/dist/modules/improvement/policy-sensitive-commands.d.ts +4 -0
- package/dist/modules/improvement/policy-sensitive-commands.js +7 -0
- package/dist/modules/index.d.ts +6 -0
- package/dist/modules/index.js +17 -0
- package/dist/modules/planning/artifact.d.ts +19 -0
- package/dist/modules/planning/artifact.js +72 -0
- package/dist/modules/planning/index.js +605 -6
- package/dist/modules/planning/question-engine.d.ts +25 -0
- package/dist/modules/planning/question-engine.js +284 -0
- package/dist/modules/planning/types.d.ts +9 -0
- package/dist/modules/planning/types.js +39 -0
- package/dist/modules/task-engine/doctor-planning-persistence.js +21 -13
- package/dist/modules/task-engine/index.d.ts +1 -2
- package/dist/modules/task-engine/index.js +1 -1143
- package/dist/modules/task-engine/migrate-task-persistence-runtime.js +31 -4
- package/dist/modules/task-engine/migrate-wishlist-intake-runtime.d.ts +2 -0
- package/dist/modules/task-engine/migrate-wishlist-intake-runtime.js +146 -0
- package/dist/modules/task-engine/planning-open.d.ts +2 -9
- package/dist/modules/task-engine/planning-open.js +4 -15
- package/dist/modules/task-engine/policy-sensitive-commands.d.ts +5 -0
- package/dist/modules/task-engine/policy-sensitive-commands.js +5 -0
- package/dist/modules/task-engine/sqlite-dual-planning.d.ts +11 -2
- package/dist/modules/task-engine/sqlite-dual-planning.js +134 -28
- package/dist/modules/task-engine/strict-task-validation.js +3 -0
- package/dist/modules/task-engine/suggestions.js +2 -1
- package/dist/modules/task-engine/task-engine-internal.d.ts +2 -0
- package/dist/modules/task-engine/task-engine-internal.js +1304 -0
- package/dist/modules/task-engine/task-type-validation.js +40 -0
- package/dist/modules/task-engine/wishlist-intake.d.ts +22 -0
- package/dist/modules/task-engine/wishlist-intake.js +180 -0
- package/dist/modules/task-engine/wishlist-validation.d.ts +4 -0
- package/dist/modules/task-engine/wishlist-validation.js +19 -0
- package/dist/modules/workspace-config/index.js +9 -11
- package/package.json +2 -2
- package/schemas/agent-behavior-profile.schema.json +52 -0
- package/schemas/task-engine-run-contracts.schema.json +80 -5
- package/src/modules/documentation/README.md +16 -25
- package/src/modules/documentation/RULES.md +9 -9
- package/src/modules/documentation/index.ts +54 -49
- package/src/modules/documentation/instructions/document-project.md +6 -6
- package/src/modules/documentation/instructions/generate-document.md +4 -4
- package/src/modules/documentation/normalizer.ts +187 -0
- package/src/modules/documentation/parser.ts +41 -0
- package/src/modules/documentation/policy-sensitive-commands.ts +8 -0
- package/src/modules/documentation/renderer.ts +121 -0
- package/src/modules/documentation/runtime-batch.ts +74 -0
- package/src/modules/documentation/runtime-config.ts +68 -0
- package/src/modules/documentation/runtime-render-support.ts +39 -0
- package/src/modules/documentation/runtime.ts +28 -600
- package/src/modules/documentation/schemas/documentation-schema.md +37 -54
- package/src/modules/documentation/types.ts +228 -0
- package/src/modules/documentation/validator.ts +247 -0
- package/src/modules/documentation/view-models.ts +132 -0
- package/src/modules/documentation/views/agents.view.yaml +18 -0
- package/src/modules/documentation/views/architecture.view.yaml +18 -0
- package/src/modules/documentation/views/principles.view.yaml +18 -0
- package/src/modules/documentation/views/readme.view.yaml +18 -0
- package/src/modules/documentation/views/releasing.view.yaml +18 -0
- package/src/modules/documentation/views/roadmap.view.yaml +18 -0
- package/src/modules/documentation/views/runbooks-consumer-cadence.view.yaml +18 -0
- package/src/modules/documentation/views/runbooks-parity-validation-flow.view.yaml +18 -0
- package/src/modules/documentation/views/runbooks-release-channels.view.yaml +18 -0
- package/src/modules/documentation/views/security.view.yaml +18 -0
- package/src/modules/documentation/views/support.view.yaml +18 -0
- package/src/modules/documentation/views/terms.view.yaml +18 -0
- package/src/modules/documentation/views/workbooks-phase2-config-policy-workbook.view.yaml +18 -0
- package/src/modules/documentation/views/workbooks-task-engine-workbook.view.yaml +18 -0
- package/src/modules/documentation/views/workbooks-transcript-automation-baseline.view.yaml +18 -0
- package/src/modules/documentation/state.md +0 -8
|
@@ -69,6 +69,86 @@ const REGISTRY = {
|
|
|
69
69
|
exposure: "public",
|
|
70
70
|
writableLayers: ["project", "user"]
|
|
71
71
|
},
|
|
72
|
+
"modules.enabled": {
|
|
73
|
+
key: "modules.enabled",
|
|
74
|
+
type: "array",
|
|
75
|
+
description: "When non-empty, only these module ids are enabled (whitelist); then modules.disabled subtracts. When empty, all modules use registration.enabledByDefault.",
|
|
76
|
+
default: [],
|
|
77
|
+
domainScope: "project",
|
|
78
|
+
owningModule: "workspace-kit",
|
|
79
|
+
sensitive: false,
|
|
80
|
+
requiresRestart: false,
|
|
81
|
+
requiresApproval: false,
|
|
82
|
+
exposure: "maintainer",
|
|
83
|
+
writableLayers: ["project", "user"]
|
|
84
|
+
},
|
|
85
|
+
"modules.disabled": {
|
|
86
|
+
key: "modules.disabled",
|
|
87
|
+
type: "array",
|
|
88
|
+
description: "Module ids to disable after computing the candidate enabled set (default-by-flag or modules.enabled whitelist).",
|
|
89
|
+
default: [],
|
|
90
|
+
domainScope: "project",
|
|
91
|
+
owningModule: "workspace-kit",
|
|
92
|
+
sensitive: false,
|
|
93
|
+
requiresRestart: false,
|
|
94
|
+
requiresApproval: false,
|
|
95
|
+
exposure: "maintainer",
|
|
96
|
+
writableLayers: ["project", "user"]
|
|
97
|
+
},
|
|
98
|
+
"planning.defaultQuestionDepth": {
|
|
99
|
+
key: "planning.defaultQuestionDepth",
|
|
100
|
+
type: "string",
|
|
101
|
+
description: "Planning interview depth mode: minimal (critical only), guided (critical + static follow-ups), or adaptive (context-driven follow-ups).",
|
|
102
|
+
default: "adaptive",
|
|
103
|
+
allowedValues: ["minimal", "guided", "adaptive"],
|
|
104
|
+
domainScope: "project",
|
|
105
|
+
owningModule: "planning",
|
|
106
|
+
sensitive: false,
|
|
107
|
+
requiresRestart: false,
|
|
108
|
+
requiresApproval: false,
|
|
109
|
+
exposure: "maintainer",
|
|
110
|
+
writableLayers: ["project", "user"]
|
|
111
|
+
},
|
|
112
|
+
"planning.hardBlockCriticalUnknowns": {
|
|
113
|
+
key: "planning.hardBlockCriticalUnknowns",
|
|
114
|
+
type: "boolean",
|
|
115
|
+
description: "When true, planning finalize requests fail until critical unknown questions are answered.",
|
|
116
|
+
default: true,
|
|
117
|
+
domainScope: "project",
|
|
118
|
+
owningModule: "planning",
|
|
119
|
+
sensitive: false,
|
|
120
|
+
requiresRestart: false,
|
|
121
|
+
requiresApproval: false,
|
|
122
|
+
exposure: "maintainer",
|
|
123
|
+
writableLayers: ["project", "user"]
|
|
124
|
+
},
|
|
125
|
+
"planning.adaptiveFinalizePolicy": {
|
|
126
|
+
key: "planning.adaptiveFinalizePolicy",
|
|
127
|
+
type: "string",
|
|
128
|
+
description: "Controls finalize handling for unresolved adaptive follow-up questions: off (ignore), warn (allow finalize with warnings), block (deny finalize).",
|
|
129
|
+
default: "off",
|
|
130
|
+
allowedValues: ["off", "warn", "block"],
|
|
131
|
+
domainScope: "project",
|
|
132
|
+
owningModule: "planning",
|
|
133
|
+
sensitive: false,
|
|
134
|
+
requiresRestart: false,
|
|
135
|
+
requiresApproval: false,
|
|
136
|
+
exposure: "maintainer",
|
|
137
|
+
writableLayers: ["project", "user"]
|
|
138
|
+
},
|
|
139
|
+
"planning.rulePacks": {
|
|
140
|
+
key: "planning.rulePacks",
|
|
141
|
+
type: "object",
|
|
142
|
+
description: "Optional object overrides for planning rule packs by workflow type (`baseQuestions` and `adaptiveQuestions`).",
|
|
143
|
+
default: {},
|
|
144
|
+
domainScope: "project",
|
|
145
|
+
owningModule: "planning",
|
|
146
|
+
sensitive: false,
|
|
147
|
+
requiresRestart: false,
|
|
148
|
+
requiresApproval: false,
|
|
149
|
+
exposure: "maintainer",
|
|
150
|
+
writableLayers: ["project", "user"]
|
|
151
|
+
},
|
|
72
152
|
"policy.extraSensitiveModuleCommands": {
|
|
73
153
|
key: "policy.extraSensitiveModuleCommands",
|
|
74
154
|
type: "array",
|
|
@@ -299,6 +379,13 @@ export function validateValueForMetadata(meta, value) {
|
|
|
299
379
|
}
|
|
300
380
|
}
|
|
301
381
|
}
|
|
382
|
+
if (meta.key === "modules.enabled" || meta.key === "modules.disabled") {
|
|
383
|
+
for (const item of value) {
|
|
384
|
+
if (typeof item !== "string" || item.trim().length === 0) {
|
|
385
|
+
throw new Error(`config-type-error(${meta.key}): array entries must be non-empty strings`);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
302
389
|
return;
|
|
303
390
|
}
|
|
304
391
|
if (meta.type === "string" && typeof value !== "string") {
|
|
@@ -417,8 +504,20 @@ export function validatePersistedConfigDocument(data, label) {
|
|
|
417
504
|
}
|
|
418
505
|
const mods = data.modules;
|
|
419
506
|
if (mods !== undefined) {
|
|
420
|
-
if (typeof mods !== "object" || mods === null || Array.isArray(mods)
|
|
421
|
-
throw new Error(`config-invalid(${label}): modules must be
|
|
507
|
+
if (typeof mods !== "object" || mods === null || Array.isArray(mods)) {
|
|
508
|
+
throw new Error(`config-invalid(${label}): modules must be an object`);
|
|
509
|
+
}
|
|
510
|
+
const m = mods;
|
|
511
|
+
for (const k of Object.keys(m)) {
|
|
512
|
+
if (k !== "enabled" && k !== "disabled") {
|
|
513
|
+
throw new Error(`config-invalid(${label}): unknown modules.${k}`);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
if (m.enabled !== undefined) {
|
|
517
|
+
validateValueForMetadata(REGISTRY["modules.enabled"], m.enabled);
|
|
518
|
+
}
|
|
519
|
+
if (m.disabled !== undefined) {
|
|
520
|
+
validateValueForMetadata(REGISTRY["modules.disabled"], m.disabled);
|
|
422
521
|
}
|
|
423
522
|
}
|
|
424
523
|
const improvement = data.improvement;
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
export { ModuleRegistry, ModuleRegistryError, validateModuleSet, type ModuleRegistryOptions } from "./module-registry.js";
|
|
1
|
+
export { ModuleRegistry, ModuleRegistryError, validateModuleSet, type ModuleActivationEntry, type ModuleActivationReport, type ModuleRegistryOptions } from "./module-registry.js";
|
|
2
|
+
export { moduleRegistryOptionsFromEffectiveConfig, pickModuleContractWorkspacePath, resolveRegistryAndConfig } from "./module-registry-resolve.js";
|
|
2
3
|
export { ModuleCommandRouter, ModuleCommandRouterError, type ModuleCommandDescriptor, type ModuleCommandRouterOptions } from "./module-command-router.js";
|
|
4
|
+
export { buildAgentInstructionSurface, classifyInstructionExecution, isInstructionExecutableForRegistry, type AgentInstructionDegradation, type AgentInstructionSurfacePayload, type AgentInstructionSurfaceRow } from "./agent-instruction-surface.js";
|
|
3
5
|
export { buildBaseConfigLayers, deepMerge, envToConfigOverlay, explainConfigPath, getAtPath, getProjectConfigPath, getUserConfigFilePath, KIT_CONFIG_DEFAULTS, loadUserLayer, mergeConfigLayers, MODULE_CONFIG_CONTRIBUTIONS, normalizeConfigForExport, PROJECT_CONFIG_REL, resolveWorkspaceConfigWithLayers, stableStringifyConfig, type ConfigLayer, type ConfigLayerId, type EffectiveWorkspaceConfig, type ExplainConfigResult, type ResolveWorkspaceConfigOptions } from "./workspace-kit-config.js";
|
|
4
6
|
export { appendPolicyTrace, getExtraSensitiveModuleCommandsFromEffective, getOperationIdForCommand, isSensitiveModuleCommand, isSensitiveModuleCommandForEffective, parsePolicyApproval, parsePolicyApprovalFromEnv, POLICY_APPROVAL_HUMAN_DOC, POLICY_TRACE_SCHEMA_VERSION, resolveActor, resolvePolicyOperationIdForCommand, type PolicyOperationId, type PolicyTraceRecord, type PolicyTraceRecordInput } from "./policy.js";
|
|
5
7
|
export { getSessionGrant, loadSessionPolicyDocument, recordSessionGrant, resolveSessionId, SESSION_POLICY_SCHEMA_VERSION, type SessionPolicyDocument, type SessionPolicyGrant } from "./session-policy.js";
|
|
@@ -13,4 +15,5 @@ export { appendConfigMutation, CONFIG_MUTATIONS_SCHEMA_VERSION, summarizeForEvid
|
|
|
13
15
|
export { generateConfigReferenceDocs, runWorkspaceConfigCli, type ConfigCliIo } from "./config-cli.js";
|
|
14
16
|
export { LINEAGE_SCHEMA_VERSION, lineageCorrelationRoot, type LineageAppPayload, type LineageCorrPayload, type LineageDecPayload, type LineageEvent, type LineageEventType, type LineageRecPayload } from "./lineage-contract.js";
|
|
15
17
|
export { appendLineageEvent, newLineageEventId, queryLineageChain, readLineageEvents } from "./lineage-store.js";
|
|
18
|
+
export { UnifiedStateDb, type ModuleStateRow } from "./state/unified-state-db.js";
|
|
16
19
|
export type CoreRuntimeVersion = "0.1";
|
package/dist/core/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { ModuleRegistry, ModuleRegistryError, validateModuleSet } from "./module-registry.js";
|
|
2
|
+
export { moduleRegistryOptionsFromEffectiveConfig, pickModuleContractWorkspacePath, resolveRegistryAndConfig } from "./module-registry-resolve.js";
|
|
2
3
|
export { ModuleCommandRouter, ModuleCommandRouterError } from "./module-command-router.js";
|
|
4
|
+
export { buildAgentInstructionSurface, classifyInstructionExecution, isInstructionExecutableForRegistry } from "./agent-instruction-surface.js";
|
|
3
5
|
export { buildBaseConfigLayers, deepMerge, envToConfigOverlay, explainConfigPath, getAtPath, getProjectConfigPath, getUserConfigFilePath, KIT_CONFIG_DEFAULTS, loadUserLayer, mergeConfigLayers, MODULE_CONFIG_CONTRIBUTIONS, normalizeConfigForExport, PROJECT_CONFIG_REL, resolveWorkspaceConfigWithLayers, stableStringifyConfig } from "./workspace-kit-config.js";
|
|
4
6
|
export { appendPolicyTrace, getExtraSensitiveModuleCommandsFromEffective, getOperationIdForCommand, isSensitiveModuleCommand, isSensitiveModuleCommandForEffective, parsePolicyApproval, parsePolicyApprovalFromEnv, POLICY_APPROVAL_HUMAN_DOC, POLICY_TRACE_SCHEMA_VERSION, resolveActor, resolvePolicyOperationIdForCommand } from "./policy.js";
|
|
5
7
|
export { getSessionGrant, loadSessionPolicyDocument, recordSessionGrant, resolveSessionId, SESSION_POLICY_SCHEMA_VERSION } from "./session-policy.js";
|
|
@@ -13,3 +15,4 @@ export { appendConfigMutation, CONFIG_MUTATIONS_SCHEMA_VERSION, summarizeForEvid
|
|
|
13
15
|
export { generateConfigReferenceDocs, runWorkspaceConfigCli } from "./config-cli.js";
|
|
14
16
|
export { LINEAGE_SCHEMA_VERSION, lineageCorrelationRoot } from "./lineage-contract.js";
|
|
15
17
|
export { appendLineageEvent, newLineageEventId, queryLineageChain, readLineageEvents } from "./lineage-store.js";
|
|
18
|
+
export { UnifiedStateDb } from "./state/unified-state-db.js";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { classifyInstructionExecution, isInstructionExecutableForRegistry } from "./agent-instruction-surface.js";
|
|
1
2
|
export class ModuleCommandRouterError extends Error {
|
|
2
3
|
code;
|
|
3
4
|
constructor(code, message) {
|
|
@@ -40,6 +41,19 @@ export class ModuleCommandRouter {
|
|
|
40
41
|
if (!indexed.module.onCommand) {
|
|
41
42
|
throw new ModuleCommandRouterError("command-not-implemented", `Module '${indexed.descriptor.moduleId}' does not implement onCommand for '${commandName}'`);
|
|
42
43
|
}
|
|
44
|
+
if (!isInstructionExecutableForRegistry(indexed.module, indexed.entry, this.registry)) {
|
|
45
|
+
const deg = classifyInstructionExecution(indexed.module, indexed.entry, this.registry);
|
|
46
|
+
const detail = deg.kind === "peer_disabled"
|
|
47
|
+
? `missing peers: ${deg.missingPeers.join(", ")}`
|
|
48
|
+
: deg.kind === "module_disabled"
|
|
49
|
+
? "owning module disabled"
|
|
50
|
+
: "not executable";
|
|
51
|
+
return {
|
|
52
|
+
ok: false,
|
|
53
|
+
code: "peer-module-disabled",
|
|
54
|
+
message: `Command '${commandName}' is not executable (${detail}). Enable required modules or follow the instruction markdown for manual guidance. Instruction: ${indexed.descriptor.instructionFile}`
|
|
55
|
+
};
|
|
56
|
+
}
|
|
43
57
|
const command = {
|
|
44
58
|
name: commandName,
|
|
45
59
|
args
|
|
@@ -49,6 +63,9 @@ export class ModuleCommandRouter {
|
|
|
49
63
|
indexEnabledModuleCommands() {
|
|
50
64
|
for (const module of this.registry.getEnabledModules()) {
|
|
51
65
|
for (const entry of module.registration.instructions.entries) {
|
|
66
|
+
if (!isInstructionExecutableForRegistry(module, entry, this.registry)) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
52
69
|
if (this.commands.has(entry.name)) {
|
|
53
70
|
const existing = this.commands.get(entry.name);
|
|
54
71
|
throw new ModuleCommandRouterError("duplicate-command", `Command '${entry.name}' is declared by both '${existing?.descriptor.moduleId}' and '${module.registration.id}'`);
|
|
@@ -60,7 +77,8 @@ export class ModuleCommandRouter {
|
|
|
60
77
|
instructionFile: `${module.registration.instructions.directory}/${entry.file}`,
|
|
61
78
|
description: entry.description
|
|
62
79
|
},
|
|
63
|
-
module
|
|
80
|
+
module,
|
|
81
|
+
entry
|
|
64
82
|
});
|
|
65
83
|
}
|
|
66
84
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { WorkflowModule } from "../contracts/module-contract.js";
|
|
2
|
+
import { ModuleRegistry, type ModuleRegistryOptions } from "./module-registry.js";
|
|
3
|
+
import { type ConfigLayer, type EffectiveWorkspaceConfig } from "./workspace-kit-config.js";
|
|
4
|
+
/**
|
|
5
|
+
* Instruction paths in module registration are repo-relative. Use `workspacePath` when it
|
|
6
|
+
* contains the kit sources; otherwise fall back to `process.cwd()` (tests / ephemeral cwd).
|
|
7
|
+
*/
|
|
8
|
+
export declare function pickModuleContractWorkspacePath(workspacePath: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Reads `modules.enabled` / `modules.disabled` from effective config and maps them
|
|
11
|
+
* to ModuleRegistryOptions. Unknown module ids throw — fail fast on typos.
|
|
12
|
+
*
|
|
13
|
+
* Semantics (matches resolveEnabledModuleIds):
|
|
14
|
+
* - If `modules.enabled` is non-empty: only those ids are candidates, then `modules.disabled` subtracts.
|
|
15
|
+
* - If `modules.enabled` is empty/absent: start from each module's enabledByDefault, then subtract disabled.
|
|
16
|
+
*/
|
|
17
|
+
export declare function moduleRegistryOptionsFromEffectiveConfig(effective: Record<string, unknown>, knownModuleIds: Set<string>): Pick<ModuleRegistryOptions, "enabledModules" | "disabledModules">;
|
|
18
|
+
/**
|
|
19
|
+
* Resolves layered config together with module enablement toggles from that config.
|
|
20
|
+
* Iterates until the enabled module set stabilizes (module config contributions can
|
|
21
|
+
* change when modules drop out of startup order).
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveRegistryAndConfig(workspacePath: string, allModules: WorkflowModule[], invocationConfig?: Record<string, unknown>): Promise<{
|
|
24
|
+
registry: ModuleRegistry;
|
|
25
|
+
effective: EffectiveWorkspaceConfig;
|
|
26
|
+
layers: ConfigLayer[];
|
|
27
|
+
}>;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { ModuleRegistry, ModuleRegistryError } from "./module-registry.js";
|
|
4
|
+
import { resolveWorkspaceConfigWithLayers } from "./workspace-kit-config.js";
|
|
5
|
+
/**
|
|
6
|
+
* Instruction paths in module registration are repo-relative. Use `workspacePath` when it
|
|
7
|
+
* contains the kit sources; otherwise fall back to `process.cwd()` (tests / ephemeral cwd).
|
|
8
|
+
*/
|
|
9
|
+
export function pickModuleContractWorkspacePath(workspacePath) {
|
|
10
|
+
const marker = resolve(workspacePath, "src/modules/task-engine/config.md");
|
|
11
|
+
if (existsSync(marker)) {
|
|
12
|
+
return workspacePath;
|
|
13
|
+
}
|
|
14
|
+
return process.cwd();
|
|
15
|
+
}
|
|
16
|
+
function readNonEmptyStringArray(value) {
|
|
17
|
+
if (!Array.isArray(value)) {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
const out = value.filter((x) => typeof x === "string" && x.trim().length > 0);
|
|
21
|
+
return out.length > 0 ? out : undefined;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Reads `modules.enabled` / `modules.disabled` from effective config and maps them
|
|
25
|
+
* to ModuleRegistryOptions. Unknown module ids throw — fail fast on typos.
|
|
26
|
+
*
|
|
27
|
+
* Semantics (matches resolveEnabledModuleIds):
|
|
28
|
+
* - If `modules.enabled` is non-empty: only those ids are candidates, then `modules.disabled` subtracts.
|
|
29
|
+
* - If `modules.enabled` is empty/absent: start from each module's enabledByDefault, then subtract disabled.
|
|
30
|
+
*/
|
|
31
|
+
export function moduleRegistryOptionsFromEffectiveConfig(effective, knownModuleIds) {
|
|
32
|
+
const root = effective.modules;
|
|
33
|
+
if (root === undefined || root === null) {
|
|
34
|
+
return {};
|
|
35
|
+
}
|
|
36
|
+
if (typeof root !== "object" || Array.isArray(root)) {
|
|
37
|
+
throw new ModuleRegistryError("invalid-modules-config", "effectiveConfig.modules must be an object when present");
|
|
38
|
+
}
|
|
39
|
+
const mod = root;
|
|
40
|
+
const enabled = readNonEmptyStringArray(mod.enabled);
|
|
41
|
+
const disabled = readNonEmptyStringArray(mod.disabled);
|
|
42
|
+
for (const id of [...(enabled ?? []), ...(disabled ?? [])]) {
|
|
43
|
+
if (!knownModuleIds.has(id)) {
|
|
44
|
+
throw new ModuleRegistryError("unknown-module-in-config", `Unknown module id in modules.enabled / modules.disabled: '${id}'`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
enabledModules: enabled,
|
|
49
|
+
disabledModules: disabled
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function enabledSignature(registry) {
|
|
53
|
+
return registry
|
|
54
|
+
.getEnabledModules()
|
|
55
|
+
.map((m) => m.registration.id)
|
|
56
|
+
.sort()
|
|
57
|
+
.join(",");
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Resolves layered config together with module enablement toggles from that config.
|
|
61
|
+
* Iterates until the enabled module set stabilizes (module config contributions can
|
|
62
|
+
* change when modules drop out of startup order).
|
|
63
|
+
*/
|
|
64
|
+
export async function resolveRegistryAndConfig(workspacePath, allModules, invocationConfig) {
|
|
65
|
+
const knownIds = new Set(allModules.map((m) => m.registration.id));
|
|
66
|
+
const moduleContractPath = pickModuleContractWorkspacePath(workspacePath);
|
|
67
|
+
let registry = new ModuleRegistry(allModules, { workspacePath: moduleContractPath });
|
|
68
|
+
for (let i = 0; i < 8; i++) {
|
|
69
|
+
const { effective, layers } = await resolveWorkspaceConfigWithLayers({
|
|
70
|
+
workspacePath,
|
|
71
|
+
registry,
|
|
72
|
+
invocationConfig
|
|
73
|
+
});
|
|
74
|
+
const extra = moduleRegistryOptionsFromEffectiveConfig(effective, knownIds);
|
|
75
|
+
const candidate = new ModuleRegistry(allModules, { workspacePath: moduleContractPath, ...extra });
|
|
76
|
+
if (enabledSignature(registry) === enabledSignature(candidate)) {
|
|
77
|
+
const fin = await resolveWorkspaceConfigWithLayers({
|
|
78
|
+
workspacePath,
|
|
79
|
+
registry: candidate,
|
|
80
|
+
invocationConfig
|
|
81
|
+
});
|
|
82
|
+
return {
|
|
83
|
+
registry: candidate,
|
|
84
|
+
effective: fin.effective,
|
|
85
|
+
layers: fin.layers
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
registry = candidate;
|
|
89
|
+
}
|
|
90
|
+
throw new ModuleRegistryError("module-enablement-unstable", "modules.enabled / modules.disabled did not stabilize after repeated config resolution; check config layers");
|
|
91
|
+
}
|
|
@@ -3,6 +3,18 @@ export declare class ModuleRegistryError extends Error {
|
|
|
3
3
|
readonly code: string;
|
|
4
4
|
constructor(code: string, message: string);
|
|
5
5
|
}
|
|
6
|
+
export type ModuleActivationEntry = {
|
|
7
|
+
moduleId: string;
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
/** dependsOn entries not present in the enabled set (non-empty only if misconfigured). */
|
|
10
|
+
unsatisfiedHardDependencies: string[];
|
|
11
|
+
/** optionalPeers not currently enabled (informational). */
|
|
12
|
+
missingOptionalPeers: string[];
|
|
13
|
+
};
|
|
14
|
+
export type ModuleActivationReport = {
|
|
15
|
+
schemaVersion: 1;
|
|
16
|
+
modules: ModuleActivationEntry[];
|
|
17
|
+
};
|
|
6
18
|
export declare function validateModuleSet(modules: WorkflowModule[], workspacePath?: string): void;
|
|
7
19
|
export type ModuleRegistryOptions = {
|
|
8
20
|
enabledModules?: string[];
|
|
@@ -21,4 +33,6 @@ export declare class ModuleRegistry {
|
|
|
21
33
|
isModuleEnabled(id: string): boolean;
|
|
22
34
|
getEnabledModules(): WorkflowModule[];
|
|
23
35
|
getStartupOrder(): WorkflowModule[];
|
|
36
|
+
/** Snapshot for doctor / tooling: enablement and peer satisfaction. */
|
|
37
|
+
getActivationReport(): ModuleActivationReport;
|
|
24
38
|
}
|
|
@@ -32,6 +32,32 @@ function validateDependencies(moduleMap) {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
+
function validateOptionalPeers(moduleMap) {
|
|
36
|
+
for (const module of moduleMap.values()) {
|
|
37
|
+
const moduleId = module.registration.id;
|
|
38
|
+
const peers = module.registration.optionalPeers ?? [];
|
|
39
|
+
const hard = new Set(module.registration.dependsOn);
|
|
40
|
+
for (const peerId of peers) {
|
|
41
|
+
if (peerId === moduleId) {
|
|
42
|
+
throw new ModuleRegistryError("self-optional-peer", `Module '${moduleId}' cannot list itself in optionalPeers`);
|
|
43
|
+
}
|
|
44
|
+
if (!moduleMap.has(peerId)) {
|
|
45
|
+
throw new ModuleRegistryError("missing-optional-peer", `Module '${moduleId}' lists unknown optional peer '${peerId}'`);
|
|
46
|
+
}
|
|
47
|
+
if (hard.has(peerId)) {
|
|
48
|
+
throw new ModuleRegistryError("optional-peer-overlap-dependsOn", `Module '${moduleId}' lists '${peerId}' in both dependsOn and optionalPeers`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function validateRegistrationSchemas(moduleMap) {
|
|
54
|
+
for (const module of moduleMap.values()) {
|
|
55
|
+
const schema = module.registration.stateSchema;
|
|
56
|
+
if (!Number.isInteger(schema) || schema < 1) {
|
|
57
|
+
throw new ModuleRegistryError("invalid-state-schema", `Module '${module.registration.id}' must declare integer stateSchema >= 1`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
35
61
|
function topologicalSort(moduleMap) {
|
|
36
62
|
const visited = new Set();
|
|
37
63
|
const inStack = new Set();
|
|
@@ -139,12 +165,23 @@ function validateInstructionContracts(moduleMap, workspacePath) {
|
|
|
139
165
|
if (!statSync(instructionFilePath).isFile()) {
|
|
140
166
|
throw new ModuleRegistryError("invalid-instruction-file", `Module '${id}' instruction path '${instructionFilePath}' is not a file`);
|
|
141
167
|
}
|
|
168
|
+
const reqPeers = entry.requiresPeers ?? [];
|
|
169
|
+
for (const peerId of reqPeers) {
|
|
170
|
+
if (peerId === id) {
|
|
171
|
+
throw new ModuleRegistryError("instruction-requires-self", `Module '${id}' instruction '${entry.name}' cannot list its own module id in requiresPeers`);
|
|
172
|
+
}
|
|
173
|
+
if (!moduleMap.has(peerId)) {
|
|
174
|
+
throw new ModuleRegistryError("unknown-requires-peer", `Module '${id}' instruction '${entry.name}' lists unknown requiresPeers module '${peerId}'`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
142
177
|
}
|
|
143
178
|
}
|
|
144
179
|
}
|
|
145
180
|
export function validateModuleSet(modules, workspacePath) {
|
|
146
181
|
const moduleMap = buildModuleMap(modules);
|
|
147
182
|
validateDependencies(moduleMap);
|
|
183
|
+
validateOptionalPeers(moduleMap);
|
|
184
|
+
validateRegistrationSchemas(moduleMap);
|
|
148
185
|
validateInstructionContracts(moduleMap, workspacePath ?? process.cwd());
|
|
149
186
|
topologicalSort(moduleMap);
|
|
150
187
|
}
|
|
@@ -157,6 +194,8 @@ export class ModuleRegistry {
|
|
|
157
194
|
constructor(modules, options) {
|
|
158
195
|
this.moduleMap = buildModuleMap(modules);
|
|
159
196
|
validateDependencies(this.moduleMap);
|
|
197
|
+
validateOptionalPeers(this.moduleMap);
|
|
198
|
+
validateRegistrationSchemas(this.moduleMap);
|
|
160
199
|
validateInstructionContracts(this.moduleMap, options?.workspacePath ?? process.cwd());
|
|
161
200
|
this.modules = [...modules];
|
|
162
201
|
const enabledModuleIds = resolveEnabledModuleIds(this.modules, options);
|
|
@@ -180,4 +219,22 @@ export class ModuleRegistry {
|
|
|
180
219
|
getStartupOrder() {
|
|
181
220
|
return [...this.sortedModules];
|
|
182
221
|
}
|
|
222
|
+
/** Snapshot for doctor / tooling: enablement and peer satisfaction. */
|
|
223
|
+
getActivationReport() {
|
|
224
|
+
const enabledIds = new Set(this.enabledModuleMap.keys());
|
|
225
|
+
const modules = [];
|
|
226
|
+
for (const mod of this.modules) {
|
|
227
|
+
const id = mod.registration.id;
|
|
228
|
+
const optionalPeers = mod.registration.optionalPeers ?? [];
|
|
229
|
+
const missingOptionalPeers = optionalPeers.filter((p) => !enabledIds.has(p));
|
|
230
|
+
const unsatisfiedHardDependencies = mod.registration.dependsOn.filter((d) => !enabledIds.has(d));
|
|
231
|
+
modules.push({
|
|
232
|
+
moduleId: id,
|
|
233
|
+
enabled: enabledIds.has(id),
|
|
234
|
+
unsatisfiedHardDependencies,
|
|
235
|
+
missingOptionalPeers
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
return { schemaVersion: 1, modules };
|
|
239
|
+
}
|
|
183
240
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Local operator snapshot so dashboards and agents can resume `build-plan` without re-entering answers. */
|
|
2
|
+
export type BuildPlanSessionSnapshotV1 = {
|
|
3
|
+
schemaVersion: 1;
|
|
4
|
+
updatedAt: string;
|
|
5
|
+
planningType: string;
|
|
6
|
+
outputMode: string;
|
|
7
|
+
status: string;
|
|
8
|
+
completionPct: number;
|
|
9
|
+
answeredCritical: number;
|
|
10
|
+
totalCritical: number;
|
|
11
|
+
answers: Record<string, unknown>;
|
|
12
|
+
/** Single-line `workspace-kit run build-plan '…'` hint (shell-escaped JSON inside quotes is caller responsibility). */
|
|
13
|
+
resumeCli: string;
|
|
14
|
+
};
|
|
15
|
+
export type DashboardPlanningSessionV1 = {
|
|
16
|
+
schemaVersion: 1;
|
|
17
|
+
updatedAt: string;
|
|
18
|
+
planningType: string;
|
|
19
|
+
outputMode: string;
|
|
20
|
+
status: string;
|
|
21
|
+
completionPct: number;
|
|
22
|
+
answeredCritical: number;
|
|
23
|
+
totalCritical: number;
|
|
24
|
+
resumeCli: string;
|
|
25
|
+
};
|
|
26
|
+
export declare function persistBuildPlanSession(workspacePath: string, snapshot: Omit<BuildPlanSessionSnapshotV1, "schemaVersion" | "updatedAt">): Promise<void>;
|
|
27
|
+
export declare function clearBuildPlanSession(workspacePath: string): Promise<void>;
|
|
28
|
+
export declare function readBuildPlanSession(workspacePath: string): Promise<BuildPlanSessionSnapshotV1 | null>;
|
|
29
|
+
export declare function toDashboardPlanningSession(snap: BuildPlanSessionSnapshotV1 | null): DashboardPlanningSessionV1 | null;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const REL_DIR = path.join(".workspace-kit", "planning");
|
|
4
|
+
const FILE_NAME = "build-plan-session.json";
|
|
5
|
+
function sessionPath(workspacePath) {
|
|
6
|
+
return path.join(workspacePath, REL_DIR, FILE_NAME);
|
|
7
|
+
}
|
|
8
|
+
export async function persistBuildPlanSession(workspacePath, snapshot) {
|
|
9
|
+
const dir = path.join(workspacePath, REL_DIR);
|
|
10
|
+
await fs.mkdir(dir, { recursive: true });
|
|
11
|
+
const full = {
|
|
12
|
+
schemaVersion: 1,
|
|
13
|
+
updatedAt: new Date().toISOString(),
|
|
14
|
+
...snapshot
|
|
15
|
+
};
|
|
16
|
+
await fs.writeFile(sessionPath(workspacePath), `${JSON.stringify(full, null, 2)}\n`, "utf8");
|
|
17
|
+
}
|
|
18
|
+
export async function clearBuildPlanSession(workspacePath) {
|
|
19
|
+
try {
|
|
20
|
+
await fs.unlink(sessionPath(workspacePath));
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
const code = err.code;
|
|
24
|
+
if (code !== "ENOENT")
|
|
25
|
+
throw err;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export async function readBuildPlanSession(workspacePath) {
|
|
29
|
+
try {
|
|
30
|
+
const raw = await fs.readFile(sessionPath(workspacePath), "utf8");
|
|
31
|
+
const parsed = JSON.parse(raw);
|
|
32
|
+
if (parsed?.schemaVersion !== 1 || typeof parsed.planningType !== "string") {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
if (typeof parsed.resumeCli !== "string") {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
return parsed;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export function toDashboardPlanningSession(snap) {
|
|
45
|
+
if (!snap)
|
|
46
|
+
return null;
|
|
47
|
+
return {
|
|
48
|
+
schemaVersion: 1,
|
|
49
|
+
updatedAt: snap.updatedAt,
|
|
50
|
+
planningType: snap.planningType,
|
|
51
|
+
outputMode: snap.outputMode,
|
|
52
|
+
status: snap.status,
|
|
53
|
+
completionPct: snap.completionPct,
|
|
54
|
+
answeredCritical: snap.answeredCritical,
|
|
55
|
+
totalCritical: snap.totalCritical,
|
|
56
|
+
resumeCli: snap.resumeCli
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared planning-domain exports for cross-module consumers.
|
|
3
|
+
*
|
|
4
|
+
* **Planning persistence** (task + wishlist stores, SQLite/JSON) lives in `src/modules/task-engine/`.
|
|
5
|
+
* The **`planning` module** (`src/modules/planning/`) is the CLI interview surface (`build-plan`, …).
|
|
6
|
+
* This facade keeps non-task-engine modules from importing deep task-engine paths; implementations stay in task-engine.
|
|
7
|
+
*/
|
|
8
|
+
export { openPlanningStores } from "../../modules/task-engine/planning-open.js";
|
|
9
|
+
export { TaskStore } from "../../modules/task-engine/store.js";
|
|
10
|
+
export { WishlistStore } from "../../modules/task-engine/wishlist-store.js";
|
|
11
|
+
export { TransitionService } from "../../modules/task-engine/service.js";
|
|
12
|
+
export { validateKnownTaskTypeRequirements } from "../../modules/task-engine/task-type-validation.js";
|
|
13
|
+
export { buildWishlistItemFromIntake, validateWishlistContentFields, validateWishlistIntakePayload, validateWishlistUpdatePayload, WISHLIST_ID_RE } from "../../modules/task-engine/wishlist-validation.js";
|
|
14
|
+
export { allocateNextTaskNumericId, taskEntityFromNewIntake } from "../../modules/task-engine/wishlist-intake.js";
|
|
15
|
+
export type { TaskEntity, TaskPriority, TaskStatus, TransitionEvidence, TransitionGuard, TransitionContext, GuardResult } from "../../modules/task-engine/types.js";
|
|
16
|
+
export type { WishlistItem, WishlistStatus, WishlistConversionDecomposition } from "../../modules/task-engine/wishlist-types.js";
|
|
17
|
+
export { persistBuildPlanSession, clearBuildPlanSession, readBuildPlanSession, toDashboardPlanningSession, type BuildPlanSessionSnapshotV1, type DashboardPlanningSessionV1 } from "./build-plan-session-file.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared planning-domain exports for cross-module consumers.
|
|
3
|
+
*
|
|
4
|
+
* **Planning persistence** (task + wishlist stores, SQLite/JSON) lives in `src/modules/task-engine/`.
|
|
5
|
+
* The **`planning` module** (`src/modules/planning/`) is the CLI interview surface (`build-plan`, …).
|
|
6
|
+
* This facade keeps non-task-engine modules from importing deep task-engine paths; implementations stay in task-engine.
|
|
7
|
+
*/
|
|
8
|
+
export { openPlanningStores } from "../../modules/task-engine/planning-open.js";
|
|
9
|
+
export { TaskStore } from "../../modules/task-engine/store.js";
|
|
10
|
+
export { WishlistStore } from "../../modules/task-engine/wishlist-store.js";
|
|
11
|
+
export { TransitionService } from "../../modules/task-engine/service.js";
|
|
12
|
+
export { validateKnownTaskTypeRequirements } from "../../modules/task-engine/task-type-validation.js";
|
|
13
|
+
export { buildWishlistItemFromIntake, validateWishlistContentFields, validateWishlistIntakePayload, validateWishlistUpdatePayload, WISHLIST_ID_RE } from "../../modules/task-engine/wishlist-validation.js";
|
|
14
|
+
export { allocateNextTaskNumericId, taskEntityFromNewIntake } from "../../modules/task-engine/wishlist-intake.js";
|
|
15
|
+
export { persistBuildPlanSession, clearBuildPlanSession, readBuildPlanSession, toDashboardPlanningSession } from "./build-plan-session-file.js";
|
package/dist/core/policy.js
CHANGED
|
@@ -1,19 +1,29 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { execFile } from "node:child_process";
|
|
4
|
+
import { APPROVALS_POLICY_COMMAND_NAMES } from "../modules/approvals/policy-sensitive-commands.js";
|
|
5
|
+
import { DOCUMENTATION_POLICY_COMMAND_NAMES } from "../modules/documentation/policy-sensitive-commands.js";
|
|
6
|
+
import { IMPROVEMENT_POLICY_COMMAND_NAMES } from "../modules/improvement/policy-sensitive-commands.js";
|
|
7
|
+
import { TASK_ENGINE_POLICY_COMMAND_NAMES } from "../modules/task-engine/policy-sensitive-commands.js";
|
|
4
8
|
export const POLICY_TRACE_SCHEMA_VERSION = 1;
|
|
5
9
|
/** Maintainer doc (repo-relative) linked from policy denial output for `workspace-kit run`. */
|
|
6
10
|
export const POLICY_APPROVAL_HUMAN_DOC = "docs/maintainers/POLICY-APPROVAL.md";
|
|
7
11
|
/** Maintainer doc: tier table + copy-paste patterns for agents (Tier A/B `run` vs CLI env approval). */
|
|
8
12
|
export const AGENT_CLI_MAP_HUMAN_DOC = "docs/maintainers/AGENT-CLI-MAP.md";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
};
|
|
13
|
+
function buildBuiltinCommandToOperation() {
|
|
14
|
+
const pairs = [
|
|
15
|
+
...DOCUMENTATION_POLICY_COMMAND_NAMES,
|
|
16
|
+
...TASK_ENGINE_POLICY_COMMAND_NAMES,
|
|
17
|
+
...APPROVALS_POLICY_COMMAND_NAMES,
|
|
18
|
+
...IMPROVEMENT_POLICY_COMMAND_NAMES
|
|
19
|
+
];
|
|
20
|
+
const out = {};
|
|
21
|
+
for (const [name, op] of pairs) {
|
|
22
|
+
out[name] = op;
|
|
23
|
+
}
|
|
24
|
+
return out;
|
|
25
|
+
}
|
|
26
|
+
const COMMAND_TO_OPERATION = buildBuiltinCommandToOperation();
|
|
17
27
|
export function getOperationIdForCommand(commandName) {
|
|
18
28
|
return COMMAND_TO_OPERATION[commandName];
|
|
19
29
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type ModuleStateRow = {
|
|
2
|
+
moduleId: string;
|
|
3
|
+
stateSchemaVersion: number;
|
|
4
|
+
state: Record<string, unknown>;
|
|
5
|
+
updatedAt: string;
|
|
6
|
+
};
|
|
7
|
+
type UnifiedStateDbOptions = {
|
|
8
|
+
exportSnapshotRelativePath?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare class UnifiedStateDb {
|
|
11
|
+
private db;
|
|
12
|
+
readonly dbPath: string;
|
|
13
|
+
readonly exportSnapshotPath: string | null;
|
|
14
|
+
constructor(workspacePath: string, databaseRelativePath: string, options?: UnifiedStateDbOptions);
|
|
15
|
+
private ensureDb;
|
|
16
|
+
getModuleState(moduleId: string): ModuleStateRow | null;
|
|
17
|
+
setModuleState(moduleId: string, stateSchemaVersion: number, state: Record<string, unknown>): void;
|
|
18
|
+
listModuleStates(): ModuleStateRow[];
|
|
19
|
+
private maybeExportSnapshot;
|
|
20
|
+
}
|
|
21
|
+
export {};
|