@workflow-cannon/workspace-kit 0.7.0 → 0.9.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 +5 -4
- package/dist/cli/run-command.d.ts +11 -0
- package/dist/cli/run-command.js +138 -0
- package/dist/cli.js +18 -135
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/module-contract.d.ts +13 -0
- package/dist/core/config-cli.js +4 -4
- package/dist/core/config-metadata.js +199 -5
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.js +6 -0
- package/dist/core/instruction-template-mapper.d.ts +9 -0
- package/dist/core/instruction-template-mapper.js +35 -0
- package/dist/core/lineage-contract.d.ts +1 -1
- package/dist/core/lineage-contract.js +1 -1
- package/dist/core/policy.d.ts +13 -2
- package/dist/core/policy.js +42 -25
- package/dist/core/response-template-contract.d.ts +15 -0
- package/dist/core/response-template-contract.js +10 -0
- package/dist/core/response-template-registry.d.ts +4 -0
- package/dist/core/response-template-registry.js +44 -0
- package/dist/core/response-template-shaping.d.ts +6 -0
- package/dist/core/response-template-shaping.js +128 -0
- package/dist/core/session-policy.d.ts +18 -0
- package/dist/core/session-policy.js +57 -0
- package/dist/core/transcript-completion-hook.d.ts +7 -0
- package/dist/core/transcript-completion-hook.js +128 -0
- package/dist/core/workspace-kit-config.d.ts +2 -1
- package/dist/core/workspace-kit-config.js +19 -23
- package/dist/modules/approvals/index.js +2 -2
- package/dist/modules/documentation/runtime.js +413 -20
- package/dist/modules/improvement/generate-recommendations-runtime.d.ts +7 -0
- package/dist/modules/improvement/generate-recommendations-runtime.js +37 -4
- package/dist/modules/improvement/improvement-state.d.ts +10 -1
- package/dist/modules/improvement/improvement-state.js +36 -7
- package/dist/modules/improvement/index.js +70 -23
- package/dist/modules/improvement/ingest.js +2 -1
- package/dist/modules/improvement/transcript-redaction.d.ts +4 -0
- package/dist/modules/improvement/transcript-redaction.js +10 -0
- package/dist/modules/improvement/transcript-sync-runtime.d.ts +42 -1
- package/dist/modules/improvement/transcript-sync-runtime.js +215 -9
- package/dist/modules/index.d.ts +1 -1
- package/dist/modules/index.js +1 -1
- package/dist/modules/task-engine/index.d.ts +0 -2
- package/dist/modules/task-engine/index.js +4 -78
- package/package.json +6 -2
- package/src/modules/documentation/README.md +39 -0
- package/src/modules/documentation/RULES.md +70 -0
- package/src/modules/documentation/config.md +14 -0
- package/src/modules/documentation/index.ts +120 -0
- package/src/modules/documentation/instructions/document-project.md +44 -0
- package/src/modules/documentation/instructions/documentation-maintainer.md +81 -0
- package/src/modules/documentation/instructions/generate-document.md +44 -0
- package/src/modules/documentation/runtime.ts +870 -0
- package/src/modules/documentation/schemas/documentation-schema.md +54 -0
- package/src/modules/documentation/state.md +8 -0
- package/src/modules/documentation/templates/AGENTS.md +84 -0
- package/src/modules/documentation/templates/ARCHITECTURE.md +71 -0
- package/src/modules/documentation/templates/PRINCIPLES.md +122 -0
- package/src/modules/documentation/templates/RELEASING.md +96 -0
- package/src/modules/documentation/templates/ROADMAP.md +131 -0
- package/src/modules/documentation/templates/SECURITY.md +53 -0
- package/src/modules/documentation/templates/SUPPORT.md +40 -0
- package/src/modules/documentation/templates/TERMS.md +61 -0
- package/src/modules/documentation/templates/runbooks/consumer-cadence.md +55 -0
- package/src/modules/documentation/templates/runbooks/parity-validation-flow.md +68 -0
- package/src/modules/documentation/templates/runbooks/release-channels.md +30 -0
- package/src/modules/documentation/templates/workbooks/phase2-config-policy-workbook.md +42 -0
- package/src/modules/documentation/templates/workbooks/task-engine-workbook.md +42 -0
- package/src/modules/documentation/templates/workbooks/transcript-automation-baseline.md +68 -0
- package/src/modules/documentation/types.ts +51 -0
- package/dist/modules/task-engine/generator.d.ts +0 -3
- package/dist/modules/task-engine/generator.js +0 -118
- package/dist/modules/task-engine/importer.d.ts +0 -8
- package/dist/modules/task-engine/importer.js +0 -163
package/README.md
CHANGED
|
@@ -62,7 +62,7 @@ This keeps automation adaptive without sacrificing safety, governance, or develo
|
|
|
62
62
|
## Current Status
|
|
63
63
|
|
|
64
64
|
- **Phase 0** and **Phase 1** (task engine, `v0.3.0`) are complete.
|
|
65
|
-
- **Phase 2** (layered config, policy gates, cutover docs, `v0.4.0`) is complete in-repo; see
|
|
65
|
+
- **Phase 2** (layered config, policy gates, cutover docs, `v0.4.0`) is complete in-repo; see `.workspace-kit/tasks/state.json` and `docs/maintainers/ROADMAP.md`.
|
|
66
66
|
- **Phase 2b** (policy + config UX, `v0.4.1`) and **Phase 3** (enhancement loop MVP, `v0.5.0`) are complete in-repo: evidence-driven **improvement** tasks, **`approvals`** (`review-item`), heuristic confidence, and append-only lineage.
|
|
67
67
|
- **Phase 4** (`v0.6.0`) is complete in-repo: compatibility matrix/gates, diagnostics/SLO baseline evidence, release-channel mapping, and planning-doc consistency checks.
|
|
68
68
|
|
|
@@ -87,7 +87,7 @@ npm install @workflow-cannon/workspace-kit
|
|
|
87
87
|
- `README.md` - project entry point
|
|
88
88
|
- `.ai/PRINCIPLES.md` - project goals and decision principles (canonical AI)
|
|
89
89
|
- `docs/maintainers/ROADMAP.md` - roadmap and decision log
|
|
90
|
-
-
|
|
90
|
+
- `.workspace-kit/tasks/state.json` - execution tracking
|
|
91
91
|
- `docs/maintainers/ARCHITECTURE.md` - architecture direction
|
|
92
92
|
- `docs/maintainers/DECISIONS.md` - focused design/decision notes
|
|
93
93
|
- `docs/maintainers/RELEASING.md` - release checklist and validation expectations
|
|
@@ -100,12 +100,13 @@ npm install @workflow-cannon/workspace-kit
|
|
|
100
100
|
|
|
101
101
|
- Project goals and decision principles: `.ai/PRINCIPLES.md`
|
|
102
102
|
- Strategy and long-range direction: `docs/maintainers/ROADMAP.md`
|
|
103
|
-
- Active execution tasks:
|
|
103
|
+
- Active execution tasks: `.workspace-kit/tasks/state.json`
|
|
104
104
|
- Glossary and agent-guidance terms: `docs/maintainers/TERMS.md`
|
|
105
105
|
- Architecture direction: `docs/maintainers/ARCHITECTURE.md`
|
|
106
106
|
- Project decisions: `docs/maintainers/DECISIONS.md`
|
|
107
|
-
-
|
|
107
|
+
- Governance policy surface: `docs/maintainers/GOVERNANCE.md`
|
|
108
108
|
- Release process and gates: `docs/maintainers/RELEASING.md`
|
|
109
|
+
- Canonical changelog: `docs/maintainers/CHANGELOG.md` (`CHANGELOG.md` at repo root is pointer-only)
|
|
109
110
|
- Canonical AI module build guidance: `.ai/module-build.md`
|
|
110
111
|
- Human module build guide: `docs/maintainers/module-build-guide.md`
|
|
111
112
|
- Security, support, and governance: `docs/maintainers/SECURITY.md`, `docs/maintainers/SUPPORT.md`, `docs/maintainers/GOVERNANCE.md`
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type RunCommandIo = {
|
|
2
|
+
writeLine: (message: string) => void;
|
|
3
|
+
writeError: (message: string) => void;
|
|
4
|
+
};
|
|
5
|
+
export type RunCommandExitCodes = {
|
|
6
|
+
success: number;
|
|
7
|
+
validationFailure: number;
|
|
8
|
+
usageError: number;
|
|
9
|
+
internalError: number;
|
|
10
|
+
};
|
|
11
|
+
export declare function handleRunCommand(cwd: string, args: string[], io: RunCommandIo, codes: RunCommandExitCodes): Promise<number>;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { ModuleRegistry } from "../core/module-registry.js";
|
|
2
|
+
import { ModuleCommandRouter } from "../core/module-command-router.js";
|
|
3
|
+
import { appendPolicyTrace, isSensitiveModuleCommandForEffective, parsePolicyApproval, resolveActorWithFallback, resolvePolicyOperationIdForCommand } from "../core/policy.js";
|
|
4
|
+
import { getSessionGrant, recordSessionGrant, resolveSessionId } from "../core/session-policy.js";
|
|
5
|
+
import { applyResponseTemplateApplication } from "../core/response-template-shaping.js";
|
|
6
|
+
import { resolveWorkspaceConfigWithLayers } from "../core/workspace-kit-config.js";
|
|
7
|
+
import { documentationModule } from "../modules/documentation/index.js";
|
|
8
|
+
import { taskEngineModule } from "../modules/task-engine/index.js";
|
|
9
|
+
import { approvalsModule } from "../modules/approvals/index.js";
|
|
10
|
+
import { planningModule } from "../modules/planning/index.js";
|
|
11
|
+
import { improvementModule } from "../modules/improvement/index.js";
|
|
12
|
+
import { workspaceConfigModule } from "../modules/workspace-config/index.js";
|
|
13
|
+
export async function handleRunCommand(cwd, args, io, codes) {
|
|
14
|
+
const { writeLine, writeError } = io;
|
|
15
|
+
const allModules = [
|
|
16
|
+
workspaceConfigModule,
|
|
17
|
+
documentationModule,
|
|
18
|
+
taskEngineModule,
|
|
19
|
+
approvalsModule,
|
|
20
|
+
planningModule,
|
|
21
|
+
improvementModule
|
|
22
|
+
];
|
|
23
|
+
const registry = new ModuleRegistry(allModules);
|
|
24
|
+
const router = new ModuleCommandRouter(registry);
|
|
25
|
+
const subcommand = args[1];
|
|
26
|
+
if (!subcommand) {
|
|
27
|
+
const commands = router.listCommands();
|
|
28
|
+
writeLine("Available module commands:");
|
|
29
|
+
for (const cmd of commands) {
|
|
30
|
+
const desc = cmd.description ? ` — ${cmd.description}` : "";
|
|
31
|
+
writeLine(` ${cmd.name} (${cmd.moduleId})${desc}`);
|
|
32
|
+
}
|
|
33
|
+
writeLine("");
|
|
34
|
+
writeLine("Usage: workspace-kit run <command> [json-args]");
|
|
35
|
+
return codes.success;
|
|
36
|
+
}
|
|
37
|
+
let commandArgs = {};
|
|
38
|
+
if (args[2]) {
|
|
39
|
+
try {
|
|
40
|
+
const parsed = JSON.parse(args[2]);
|
|
41
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
42
|
+
commandArgs = parsed;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
writeError("Command args must be a JSON object.");
|
|
46
|
+
return codes.usageError;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
writeError(`Invalid JSON args: ${args[2]}`);
|
|
51
|
+
return codes.usageError;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const invocationConfig = typeof commandArgs.config === "object" &&
|
|
55
|
+
commandArgs.config !== null &&
|
|
56
|
+
!Array.isArray(commandArgs.config)
|
|
57
|
+
? commandArgs.config
|
|
58
|
+
: {};
|
|
59
|
+
let effective;
|
|
60
|
+
try {
|
|
61
|
+
const resolved = await resolveWorkspaceConfigWithLayers({
|
|
62
|
+
workspacePath: cwd,
|
|
63
|
+
registry,
|
|
64
|
+
invocationConfig
|
|
65
|
+
});
|
|
66
|
+
effective = resolved.effective;
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
70
|
+
writeError(`Config resolution failed: ${message}`);
|
|
71
|
+
return codes.validationFailure;
|
|
72
|
+
}
|
|
73
|
+
const actor = await resolveActorWithFallback(cwd, commandArgs, process.env);
|
|
74
|
+
const sensitive = isSensitiveModuleCommandForEffective(subcommand, commandArgs, effective);
|
|
75
|
+
const sessionId = resolveSessionId(process.env);
|
|
76
|
+
const policyOp = resolvePolicyOperationIdForCommand(subcommand, effective);
|
|
77
|
+
const explicitPolicyApproval = parsePolicyApproval(commandArgs);
|
|
78
|
+
let resolvedSensitiveApproval = explicitPolicyApproval;
|
|
79
|
+
if (sensitive) {
|
|
80
|
+
if (!resolvedSensitiveApproval && policyOp) {
|
|
81
|
+
const grant = await getSessionGrant(cwd, policyOp, sessionId);
|
|
82
|
+
if (grant) {
|
|
83
|
+
resolvedSensitiveApproval = { confirmed: true, rationale: grant.rationale };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (!resolvedSensitiveApproval) {
|
|
87
|
+
if (policyOp) {
|
|
88
|
+
await appendPolicyTrace(cwd, {
|
|
89
|
+
timestamp: new Date().toISOString(),
|
|
90
|
+
operationId: policyOp,
|
|
91
|
+
command: `run ${subcommand}`,
|
|
92
|
+
actor,
|
|
93
|
+
allowed: false,
|
|
94
|
+
message: "missing policyApproval in JSON args"
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
writeLine(JSON.stringify({
|
|
98
|
+
ok: false,
|
|
99
|
+
code: "policy-denied",
|
|
100
|
+
message: 'Sensitive command requires policyApproval in JSON args (or an existing session grant for this operation): {"policyApproval":{"confirmed":true,"rationale":"why","scope":"session"}}'
|
|
101
|
+
}, null, 2));
|
|
102
|
+
return codes.validationFailure;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const ctx = {
|
|
106
|
+
runtimeVersion: "0.1",
|
|
107
|
+
workspacePath: cwd,
|
|
108
|
+
effectiveConfig: effective,
|
|
109
|
+
resolvedActor: actor,
|
|
110
|
+
moduleRegistry: registry
|
|
111
|
+
};
|
|
112
|
+
try {
|
|
113
|
+
const rawResult = await router.execute(subcommand, commandArgs, ctx);
|
|
114
|
+
if (sensitive && resolvedSensitiveApproval && policyOp) {
|
|
115
|
+
await appendPolicyTrace(cwd, {
|
|
116
|
+
timestamp: new Date().toISOString(),
|
|
117
|
+
operationId: policyOp,
|
|
118
|
+
command: `run ${subcommand}`,
|
|
119
|
+
actor,
|
|
120
|
+
allowed: true,
|
|
121
|
+
rationale: resolvedSensitiveApproval.rationale,
|
|
122
|
+
commandOk: rawResult.ok,
|
|
123
|
+
message: rawResult.message
|
|
124
|
+
});
|
|
125
|
+
if (explicitPolicyApproval?.scope === "session" && rawResult.ok) {
|
|
126
|
+
await recordSessionGrant(cwd, policyOp, sessionId, explicitPolicyApproval.rationale);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const result = applyResponseTemplateApplication(subcommand, commandArgs, rawResult, effective);
|
|
130
|
+
writeLine(JSON.stringify(result, null, 2));
|
|
131
|
+
return result.ok ? codes.success : codes.validationFailure;
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
135
|
+
writeError(`Module command failed: ${message}`);
|
|
136
|
+
return codes.internalError;
|
|
137
|
+
}
|
|
138
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -2,21 +2,14 @@
|
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
|
-
import {
|
|
6
|
-
import { ModuleCommandRouter } from "./core/module-command-router.js";
|
|
7
|
-
import { appendPolicyTrace, isSensitiveModuleCommandForEffective, parsePolicyApproval, parsePolicyApprovalFromEnv, resolveActor, resolvePolicyOperationIdForCommand } from "./core/policy.js";
|
|
5
|
+
import { appendPolicyTrace, parsePolicyApprovalFromEnv, resolveActorWithFallback } from "./core/policy.js";
|
|
8
6
|
import { runWorkspaceConfigCli } from "./core/config-cli.js";
|
|
9
|
-
import {
|
|
10
|
-
import { documentationModule } from "./modules/documentation/index.js";
|
|
11
|
-
import { taskEngineModule } from "./modules/task-engine/index.js";
|
|
12
|
-
import { approvalsModule } from "./modules/approvals/index.js";
|
|
13
|
-
import { planningModule } from "./modules/planning/index.js";
|
|
14
|
-
import { improvementModule } from "./modules/improvement/index.js";
|
|
15
|
-
import { workspaceConfigModule } from "./modules/workspace-config/index.js";
|
|
7
|
+
import { handleRunCommand } from "./cli/run-command.js";
|
|
16
8
|
const EXIT_SUCCESS = 0;
|
|
17
9
|
const EXIT_VALIDATION_FAILURE = 1;
|
|
18
10
|
const EXIT_USAGE_ERROR = 2;
|
|
19
11
|
const EXIT_INTERNAL_ERROR = 3;
|
|
12
|
+
const CANONICAL_KIT_NAME = "@workflow-cannon/workspace-kit";
|
|
20
13
|
export const defaultWorkspaceKitPaths = {
|
|
21
14
|
profile: "workspace-kit.profile.json",
|
|
22
15
|
profileSchema: "schemas/workspace-kit-profile.schema.json",
|
|
@@ -106,7 +99,7 @@ async function requireCliPolicyApproval(cwd, operationId, commandLabel, writeErr
|
|
|
106
99
|
timestamp: new Date().toISOString(),
|
|
107
100
|
operationId,
|
|
108
101
|
command: commandLabel,
|
|
109
|
-
actor:
|
|
102
|
+
actor: await resolveActorWithFallback(cwd, {}, process.env),
|
|
110
103
|
allowed: false,
|
|
111
104
|
message: "missing WORKSPACE_KIT_POLICY_APPROVAL"
|
|
112
105
|
});
|
|
@@ -119,7 +112,7 @@ async function recordCliPolicySuccess(cwd, operationId, commandLabel, rationale,
|
|
|
119
112
|
timestamp: new Date().toISOString(),
|
|
120
113
|
operationId,
|
|
121
114
|
command: commandLabel,
|
|
122
|
-
actor:
|
|
115
|
+
actor: await resolveActorWithFallback(cwd, {}, process.env),
|
|
123
116
|
allowed: true,
|
|
124
117
|
rationale,
|
|
125
118
|
commandOk
|
|
@@ -273,7 +266,8 @@ async function resolvePackageVersion(cwd) {
|
|
|
273
266
|
const version = parsed.version;
|
|
274
267
|
const name = parsed.name;
|
|
275
268
|
if (typeof version === "string" && version.length > 0 && typeof name === "string") {
|
|
276
|
-
if (name ===
|
|
269
|
+
if (name === CANONICAL_KIT_NAME ||
|
|
270
|
+
name === "quicktask-workspace-kit" ||
|
|
277
271
|
candidatePath.endsWith("packages/workspace-kit/package.json")) {
|
|
278
272
|
return version;
|
|
279
273
|
}
|
|
@@ -418,11 +412,7 @@ export async function runCli(args, options = {}) {
|
|
|
418
412
|
const mergedManifest = {
|
|
419
413
|
schemaVersion: 1,
|
|
420
414
|
kit: {
|
|
421
|
-
name:
|
|
422
|
-
existingManifest.kit &&
|
|
423
|
-
typeof existingManifest.kit.name === "string"
|
|
424
|
-
? existingManifest.kit.name
|
|
425
|
-
: "quicktask-workspace-kit",
|
|
415
|
+
name: CANONICAL_KIT_NAME,
|
|
426
416
|
version: typeof existingManifest.kit === "object" &&
|
|
427
417
|
existingManifest.kit &&
|
|
428
418
|
typeof existingManifest.kit.version === "string"
|
|
@@ -552,12 +542,14 @@ export async function runCli(args, options = {}) {
|
|
|
552
542
|
if (!manifestKitName || !manifestKitVersion) {
|
|
553
543
|
driftFindings.push(`${defaultWorkspaceKitPaths.manifest}: kit.name and kit.version are required`);
|
|
554
544
|
}
|
|
555
|
-
else if (manifestKitName === "quicktask-workspace-kit" &&
|
|
545
|
+
else if ((manifestKitName === CANONICAL_KIT_NAME || manifestKitName === "quicktask-workspace-kit") &&
|
|
546
|
+
packageVersion) {
|
|
556
547
|
if (manifestKitVersion !== packageVersion) {
|
|
557
548
|
driftFindings.push(`${defaultWorkspaceKitPaths.manifest}: kit.version (${manifestKitVersion}) does not match package version (${packageVersion})`);
|
|
558
549
|
}
|
|
559
550
|
}
|
|
560
|
-
else if (manifestKitName !==
|
|
551
|
+
else if (manifestKitName !== CANONICAL_KIT_NAME &&
|
|
552
|
+
manifestKitName !== "quicktask-workspace-kit") {
|
|
561
553
|
warnings.push(`${defaultWorkspaceKitPaths.manifest}: kit.name is '${manifestKitName}', skipping package-version drift comparison`);
|
|
562
554
|
}
|
|
563
555
|
}
|
|
@@ -579,121 +571,12 @@ export async function runCli(args, options = {}) {
|
|
|
579
571
|
return EXIT_SUCCESS;
|
|
580
572
|
}
|
|
581
573
|
if (command === "run") {
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
improvementModule
|
|
589
|
-
];
|
|
590
|
-
const registry = new ModuleRegistry(allModules);
|
|
591
|
-
const router = new ModuleCommandRouter(registry);
|
|
592
|
-
const subcommand = args[1];
|
|
593
|
-
if (!subcommand) {
|
|
594
|
-
const commands = router.listCommands();
|
|
595
|
-
writeLine("Available module commands:");
|
|
596
|
-
for (const cmd of commands) {
|
|
597
|
-
const desc = cmd.description ? ` — ${cmd.description}` : "";
|
|
598
|
-
writeLine(` ${cmd.name} (${cmd.moduleId})${desc}`);
|
|
599
|
-
}
|
|
600
|
-
writeLine("");
|
|
601
|
-
writeLine("Usage: workspace-kit run <command> [json-args]");
|
|
602
|
-
return EXIT_SUCCESS;
|
|
603
|
-
}
|
|
604
|
-
let commandArgs = {};
|
|
605
|
-
if (args[2]) {
|
|
606
|
-
try {
|
|
607
|
-
const parsed = JSON.parse(args[2]);
|
|
608
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
609
|
-
commandArgs = parsed;
|
|
610
|
-
}
|
|
611
|
-
else {
|
|
612
|
-
writeError("Command args must be a JSON object.");
|
|
613
|
-
return EXIT_USAGE_ERROR;
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
catch {
|
|
617
|
-
writeError(`Invalid JSON args: ${args[2]}`);
|
|
618
|
-
return EXIT_USAGE_ERROR;
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
const invocationConfig = typeof commandArgs.config === "object" &&
|
|
622
|
-
commandArgs.config !== null &&
|
|
623
|
-
!Array.isArray(commandArgs.config)
|
|
624
|
-
? commandArgs.config
|
|
625
|
-
: {};
|
|
626
|
-
let effective;
|
|
627
|
-
try {
|
|
628
|
-
const resolved = await resolveWorkspaceConfigWithLayers({
|
|
629
|
-
workspacePath: cwd,
|
|
630
|
-
registry,
|
|
631
|
-
invocationConfig
|
|
632
|
-
});
|
|
633
|
-
effective = resolved.effective;
|
|
634
|
-
}
|
|
635
|
-
catch (err) {
|
|
636
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
637
|
-
writeError(`Config resolution failed: ${message}`);
|
|
638
|
-
return EXIT_VALIDATION_FAILURE;
|
|
639
|
-
}
|
|
640
|
-
const actor = resolveActor(cwd, commandArgs, process.env);
|
|
641
|
-
const sensitive = isSensitiveModuleCommandForEffective(subcommand, commandArgs, effective);
|
|
642
|
-
if (sensitive) {
|
|
643
|
-
const approval = parsePolicyApproval(commandArgs);
|
|
644
|
-
if (!approval) {
|
|
645
|
-
const op = resolvePolicyOperationIdForCommand(subcommand, effective);
|
|
646
|
-
if (op) {
|
|
647
|
-
await appendPolicyTrace(cwd, {
|
|
648
|
-
timestamp: new Date().toISOString(),
|
|
649
|
-
operationId: op,
|
|
650
|
-
command: `run ${subcommand}`,
|
|
651
|
-
actor,
|
|
652
|
-
allowed: false,
|
|
653
|
-
message: "missing policyApproval in JSON args"
|
|
654
|
-
});
|
|
655
|
-
}
|
|
656
|
-
writeLine(JSON.stringify({
|
|
657
|
-
ok: false,
|
|
658
|
-
code: "policy-denied",
|
|
659
|
-
message: 'Sensitive command requires policyApproval in JSON args: {"policyApproval":{"confirmed":true,"rationale":"user approved in chat"}}'
|
|
660
|
-
}, null, 2));
|
|
661
|
-
return EXIT_VALIDATION_FAILURE;
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
const ctx = {
|
|
665
|
-
runtimeVersion: "0.1",
|
|
666
|
-
workspacePath: cwd,
|
|
667
|
-
effectiveConfig: effective,
|
|
668
|
-
resolvedActor: actor,
|
|
669
|
-
moduleRegistry: registry
|
|
670
|
-
};
|
|
671
|
-
try {
|
|
672
|
-
const result = await router.execute(subcommand, commandArgs, ctx);
|
|
673
|
-
if (sensitive) {
|
|
674
|
-
const approval = parsePolicyApproval(commandArgs);
|
|
675
|
-
const op = resolvePolicyOperationIdForCommand(subcommand, effective);
|
|
676
|
-
if (approval && op) {
|
|
677
|
-
await appendPolicyTrace(cwd, {
|
|
678
|
-
timestamp: new Date().toISOString(),
|
|
679
|
-
operationId: op,
|
|
680
|
-
command: `run ${subcommand}`,
|
|
681
|
-
actor,
|
|
682
|
-
allowed: true,
|
|
683
|
-
rationale: approval.rationale,
|
|
684
|
-
commandOk: result.ok,
|
|
685
|
-
message: result.message
|
|
686
|
-
});
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
writeLine(JSON.stringify(result, null, 2));
|
|
690
|
-
return result.ok ? EXIT_SUCCESS : EXIT_VALIDATION_FAILURE;
|
|
691
|
-
}
|
|
692
|
-
catch (error) {
|
|
693
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
694
|
-
writeError(`Module command failed: ${message}`);
|
|
695
|
-
return EXIT_INTERNAL_ERROR;
|
|
696
|
-
}
|
|
574
|
+
return handleRunCommand(cwd, args, { writeLine, writeError }, {
|
|
575
|
+
success: EXIT_SUCCESS,
|
|
576
|
+
validationFailure: EXIT_VALIDATION_FAILURE,
|
|
577
|
+
usageError: EXIT_USAGE_ERROR,
|
|
578
|
+
internalError: EXIT_INTERNAL_ERROR
|
|
579
|
+
});
|
|
697
580
|
}
|
|
698
581
|
if (command !== "doctor") {
|
|
699
582
|
writeError(`Unknown command '${command}'. Supported commands: init, doctor, check, upgrade, drift-check, run, config.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type { ConfigRegistryView, ModuleCommand, ModuleCommandResult, ModuleCapability, ModuleDocumentContract, ModuleEvent, ModuleInstructionContract, ModuleInstructionEntry, ModuleLifecycleContext, ModuleRegistration, WorkflowModule } from "./module-contract.js";
|
|
1
|
+
export type { ConfigRegistryView, ResponseTemplateApplicationMeta, ModuleCommand, ModuleCommandResult, ModuleCapability, ModuleDocumentContract, ModuleEvent, ModuleInstructionContract, ModuleInstructionEntry, ModuleLifecycleContext, ModuleRegistration, WorkflowModule } from "./module-contract.js";
|
|
@@ -30,11 +30,24 @@ export type ModuleCommand = {
|
|
|
30
30
|
name: string;
|
|
31
31
|
args?: Record<string, unknown>;
|
|
32
32
|
};
|
|
33
|
+
/** Structured response-template application record (Phase 6b); mirrored in core for shaping. */
|
|
34
|
+
export type ResponseTemplateApplicationMeta = {
|
|
35
|
+
requestedTemplateId: string | null;
|
|
36
|
+
appliedTemplateId: string | null;
|
|
37
|
+
enforcementMode: "advisory" | "strict";
|
|
38
|
+
warnings: string[];
|
|
39
|
+
telemetry?: {
|
|
40
|
+
resolveNs: number;
|
|
41
|
+
warningCount: number;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
33
44
|
export type ModuleCommandResult = {
|
|
34
45
|
ok: boolean;
|
|
35
46
|
code: string;
|
|
36
47
|
message?: string;
|
|
37
48
|
data?: Record<string, unknown>;
|
|
49
|
+
/** Advisory response-template shaping metadata; always present for `workspace-kit run` JSON output when enabled. */
|
|
50
|
+
responseTemplate?: ResponseTemplateApplicationMeta;
|
|
38
51
|
};
|
|
39
52
|
/** Subset of module registry used for config layer ordering (avoids core↔contracts cycles). */
|
|
40
53
|
export type ConfigRegistryView = {
|
package/dist/core/config-cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createInterface } from "node:readline/promises";
|
|
|
3
3
|
import { stdin as processStdin, stdout as processStdout } from "node:process";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { ModuleRegistry } from "./module-registry.js";
|
|
6
|
-
import { appendPolicyTrace, parsePolicyApprovalFromEnv,
|
|
6
|
+
import { appendPolicyTrace, parsePolicyApprovalFromEnv, resolveActorWithFallback } from "./policy.js";
|
|
7
7
|
import { appendConfigMutation, summarizeForEvidence } from "./config-mutations.js";
|
|
8
8
|
import { assertWritableKey, getConfigKeyMetadata, listConfigMetadata, validatePersistedConfigDocument, validateValueForMetadata } from "./config-metadata.js";
|
|
9
9
|
import { explainConfigPath, getAtPath, getProjectConfigPath, getUserConfigFilePath, resolveWorkspaceConfigWithLayers, stableStringifyConfig } from "./workspace-kit-config.js";
|
|
@@ -114,7 +114,7 @@ async function requireConfigApproval(cwd, commandLabel, writeError) {
|
|
|
114
114
|
timestamp: new Date().toISOString(),
|
|
115
115
|
operationId: "cli.config-mutate",
|
|
116
116
|
command: commandLabel,
|
|
117
|
-
actor:
|
|
117
|
+
actor: await resolveActorWithFallback(cwd, {}, process.env),
|
|
118
118
|
allowed: false,
|
|
119
119
|
message: "missing WORKSPACE_KIT_POLICY_APPROVAL"
|
|
120
120
|
});
|
|
@@ -303,7 +303,7 @@ export async function runWorkspaceConfigCli(cwd, argv, io) {
|
|
|
303
303
|
const prevVal = getAtPath(before, key);
|
|
304
304
|
const next = setDeep(before, key, parsed);
|
|
305
305
|
validatePersistedConfigDocument(next, scope === "project" ? ".workspace-kit/config.json" : "user config");
|
|
306
|
-
const actor =
|
|
306
|
+
const actor = await resolveActorWithFallback(cwd, {}, process.env);
|
|
307
307
|
try {
|
|
308
308
|
await writeConfigFileAtomic(fp, next);
|
|
309
309
|
await appendConfigMutation(cwd, {
|
|
@@ -380,7 +380,7 @@ export async function runWorkspaceConfigCli(cwd, argv, io) {
|
|
|
380
380
|
const prevVal = getAtPath(before, key);
|
|
381
381
|
const next = unsetDeep(before, key);
|
|
382
382
|
validatePersistedConfigDocument(next, scope === "project" ? ".workspace-kit/config.json" : "user config");
|
|
383
|
-
const actor =
|
|
383
|
+
const actor = await resolveActorWithFallback(cwd, {}, process.env);
|
|
384
384
|
try {
|
|
385
385
|
if (Object.keys(next).length === 0) {
|
|
386
386
|
await fs.rm(fp, { force: true });
|