@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
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { UnifiedStateDb } from "../../core/state/unified-state-db.js";
|
|
4
|
+
import { getTaskPersistenceBackend, planningSqliteDatabaseRelativePath } from "../task-engine/planning-config.js";
|
|
3
5
|
export const IMPROVEMENT_STATE_SCHEMA_VERSION = 2;
|
|
4
6
|
const DEFAULT_REL = ".workspace-kit/improvement/state.json";
|
|
7
|
+
const IMPROVEMENT_MODULE_STATE_ID = "improvement";
|
|
5
8
|
function statePath(workspacePath) {
|
|
6
9
|
return path.join(workspacePath, DEFAULT_REL);
|
|
7
10
|
}
|
|
@@ -31,43 +34,69 @@ function migrateFromV1(raw) {
|
|
|
31
34
|
lastIngestRunAt: typeof raw.lastIngestRunAt === "string" ? raw.lastIngestRunAt : null
|
|
32
35
|
};
|
|
33
36
|
}
|
|
34
|
-
|
|
37
|
+
function normalizeLoadedDoc(raw) {
|
|
38
|
+
const ver = raw.schemaVersion;
|
|
39
|
+
if (ver === 1) {
|
|
40
|
+
return migrateFromV1(raw);
|
|
41
|
+
}
|
|
42
|
+
if (ver !== IMPROVEMENT_STATE_SCHEMA_VERSION) {
|
|
43
|
+
return emptyImprovementState();
|
|
44
|
+
}
|
|
45
|
+
const doc = raw;
|
|
46
|
+
return {
|
|
47
|
+
...emptyImprovementState(),
|
|
48
|
+
...doc,
|
|
49
|
+
transcriptLineCursors: doc.transcriptLineCursors ?? {},
|
|
50
|
+
transcriptRetryQueue: Array.isArray(doc.transcriptRetryQueue)
|
|
51
|
+
? doc.transcriptRetryQueue.filter((e) => e !== null &&
|
|
52
|
+
typeof e === "object" &&
|
|
53
|
+
typeof e.relativePath === "string")
|
|
54
|
+
: []
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
async function loadImprovementStateFromFile(workspacePath) {
|
|
35
58
|
const fp = statePath(workspacePath);
|
|
36
59
|
try {
|
|
37
60
|
const rawText = await fs.readFile(fp, "utf8");
|
|
38
61
|
const raw = JSON.parse(rawText);
|
|
39
|
-
|
|
40
|
-
if (ver === 1) {
|
|
41
|
-
return migrateFromV1(raw);
|
|
42
|
-
}
|
|
43
|
-
if (ver !== IMPROVEMENT_STATE_SCHEMA_VERSION) {
|
|
44
|
-
return emptyImprovementState();
|
|
45
|
-
}
|
|
46
|
-
const doc = raw;
|
|
47
|
-
return {
|
|
48
|
-
...emptyImprovementState(),
|
|
49
|
-
...doc,
|
|
50
|
-
transcriptLineCursors: doc.transcriptLineCursors ?? {},
|
|
51
|
-
transcriptRetryQueue: Array.isArray(doc.transcriptRetryQueue)
|
|
52
|
-
? doc.transcriptRetryQueue.filter((e) => e !== null &&
|
|
53
|
-
typeof e === "object" &&
|
|
54
|
-
typeof e.relativePath === "string")
|
|
55
|
-
: []
|
|
56
|
-
};
|
|
62
|
+
return normalizeLoadedDoc(raw);
|
|
57
63
|
}
|
|
58
64
|
catch (e) {
|
|
59
65
|
if (e.code === "ENOENT") {
|
|
60
|
-
return
|
|
66
|
+
return null;
|
|
61
67
|
}
|
|
62
68
|
throw e;
|
|
63
69
|
}
|
|
64
70
|
}
|
|
65
|
-
export async function
|
|
66
|
-
|
|
67
|
-
|
|
71
|
+
export async function loadImprovementState(workspacePath, effectiveConfig) {
|
|
72
|
+
if (getTaskPersistenceBackend(effectiveConfig) === "sqlite") {
|
|
73
|
+
const ctx = { workspacePath, effectiveConfig };
|
|
74
|
+
const unified = new UnifiedStateDb(workspacePath, planningSqliteDatabaseRelativePath(ctx));
|
|
75
|
+
const row = unified.getModuleState(IMPROVEMENT_MODULE_STATE_ID);
|
|
76
|
+
if (row?.state) {
|
|
77
|
+
return normalizeLoadedDoc(row.state);
|
|
78
|
+
}
|
|
79
|
+
const fromFile = await loadImprovementStateFromFile(workspacePath);
|
|
80
|
+
if (fromFile) {
|
|
81
|
+
return fromFile;
|
|
82
|
+
}
|
|
83
|
+
return emptyImprovementState();
|
|
84
|
+
}
|
|
85
|
+
const fromFile = await loadImprovementStateFromFile(workspacePath);
|
|
86
|
+
return fromFile ?? emptyImprovementState();
|
|
87
|
+
}
|
|
88
|
+
export async function saveImprovementState(workspacePath, doc, effectiveConfig) {
|
|
68
89
|
const out = {
|
|
69
90
|
...doc,
|
|
70
91
|
schemaVersion: IMPROVEMENT_STATE_SCHEMA_VERSION
|
|
71
92
|
};
|
|
93
|
+
if (getTaskPersistenceBackend(effectiveConfig) === "sqlite") {
|
|
94
|
+
const ctx = { workspacePath, effectiveConfig };
|
|
95
|
+
const unified = new UnifiedStateDb(workspacePath, planningSqliteDatabaseRelativePath(ctx));
|
|
96
|
+
unified.setModuleState(IMPROVEMENT_MODULE_STATE_ID, out.schemaVersion, out);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const fp = statePath(workspacePath);
|
|
100
|
+
await fs.mkdir(path.dirname(fp), { recursive: true });
|
|
72
101
|
await fs.writeFile(fp, `${JSON.stringify(out, null, 2)}\n`, "utf8");
|
|
73
102
|
}
|
|
@@ -8,19 +8,16 @@ export const improvementModule = {
|
|
|
8
8
|
id: "improvement",
|
|
9
9
|
version: "0.8.0",
|
|
10
10
|
contractVersion: "1",
|
|
11
|
+
stateSchema: 1,
|
|
11
12
|
capabilities: ["improvement"],
|
|
12
13
|
dependsOn: ["task-engine", "planning"],
|
|
14
|
+
optionalPeers: ["documentation"],
|
|
13
15
|
enabledByDefault: true,
|
|
14
16
|
config: {
|
|
15
17
|
path: "src/modules/improvement/config.md",
|
|
16
18
|
format: "md",
|
|
17
19
|
description: "Improvement module configuration contract."
|
|
18
20
|
},
|
|
19
|
-
state: {
|
|
20
|
-
path: "src/modules/improvement/state.md",
|
|
21
|
-
format: "md",
|
|
22
|
-
description: "Improvement module recommendation state contract."
|
|
23
|
-
},
|
|
24
21
|
instructions: {
|
|
25
22
|
directory: "src/modules/improvement/instructions",
|
|
26
23
|
entries: [
|
|
@@ -54,153 +51,158 @@ export const improvementModule = {
|
|
|
54
51
|
},
|
|
55
52
|
async onCommand(command, ctx) {
|
|
56
53
|
const args = command.args ?? {};
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
const state = await loadImprovementState(ctx.workspacePath);
|
|
67
|
-
const sync = await runSyncTranscripts(ctx, syncArgs, state);
|
|
68
|
-
state.lastSyncRunAt = new Date().toISOString();
|
|
69
|
-
await saveImprovementState(ctx.workspacePath, state);
|
|
70
|
-
const result = await runGenerateRecommendations(ctx, {
|
|
71
|
-
transcriptsRoot: sync.archivePath,
|
|
72
|
-
fromTag,
|
|
73
|
-
toTag
|
|
74
|
-
});
|
|
75
|
-
return {
|
|
76
|
-
ok: true,
|
|
77
|
-
code: "recommendations-generated",
|
|
78
|
-
message: `After sync (${sync.copied} copied): created ${result.created.length} improvement task(s); skipped ${result.skipped} duplicate(s)`,
|
|
79
|
-
data: { sync, ...result }
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
catch (e) {
|
|
83
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
84
|
-
return { ok: false, code: "generate-failed", message: msg };
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
if (command.name === "sync-transcripts") {
|
|
88
|
-
const syncArgs = {
|
|
89
|
-
sourcePath: typeof args.sourcePath === "string" ? args.sourcePath : undefined,
|
|
90
|
-
archivePath: typeof args.archivePath === "string" ? args.archivePath : undefined
|
|
91
|
-
};
|
|
92
|
-
try {
|
|
93
|
-
const state = await loadImprovementState(ctx.workspacePath);
|
|
94
|
-
const sync = await runSyncTranscripts(ctx, syncArgs, state);
|
|
95
|
-
state.lastSyncRunAt = new Date().toISOString();
|
|
96
|
-
await saveImprovementState(ctx.workspacePath, state);
|
|
97
|
-
return {
|
|
98
|
-
ok: true,
|
|
99
|
-
code: "transcripts-synced",
|
|
100
|
-
message: `Copied ${sync.copied} transcript file(s); skipped ${sync.skippedExisting} existing`,
|
|
101
|
-
data: sync
|
|
54
|
+
const handlers = {
|
|
55
|
+
"generate-recommendations": async () => {
|
|
56
|
+
const transcriptsRoot = typeof args.transcriptsRoot === "string" ? args.transcriptsRoot : undefined;
|
|
57
|
+
const fromTag = typeof args.fromTag === "string" ? args.fromTag : undefined;
|
|
58
|
+
const toTag = typeof args.toTag === "string" ? args.toTag : undefined;
|
|
59
|
+
const syncArgs = {
|
|
60
|
+
sourcePath: typeof args.sourcePath === "string" ? args.sourcePath : undefined,
|
|
61
|
+
archivePath: transcriptsRoot
|
|
102
62
|
};
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
archivePath: typeof args.archivePath === "string" ? args.archivePath : undefined
|
|
113
|
-
};
|
|
114
|
-
const now = new Date();
|
|
115
|
-
try {
|
|
116
|
-
const state = await loadImprovementState(ctx.workspacePath);
|
|
117
|
-
const sync = await runSyncTranscripts(ctx, syncArgs, state);
|
|
118
|
-
const cfg = resolveImprovementTranscriptConfig(ctx, syncArgs);
|
|
119
|
-
const cadenceDecision = resolveCadenceDecision(now, state.lastIngestRunAt, cfg.minIntervalMinutes, sync.copied, cfg.skipIfNoNewTranscripts);
|
|
120
|
-
state.lastSyncRunAt = now.toISOString();
|
|
121
|
-
const generate = cadenceDecision.shouldRunGenerate || args.forceGenerate === true || args.runGenerate === true;
|
|
122
|
-
let recommendations = null;
|
|
123
|
-
if (generate) {
|
|
124
|
-
recommendations = await runGenerateRecommendations(ctx, {
|
|
125
|
-
transcriptsRoot: sync.archivePath
|
|
63
|
+
try {
|
|
64
|
+
const state = await loadImprovementState(ctx.workspacePath, ctx.effectiveConfig);
|
|
65
|
+
const sync = await runSyncTranscripts(ctx, syncArgs, state);
|
|
66
|
+
state.lastSyncRunAt = new Date().toISOString();
|
|
67
|
+
await saveImprovementState(ctx.workspacePath, state, ctx.effectiveConfig);
|
|
68
|
+
const result = await runGenerateRecommendations(ctx, {
|
|
69
|
+
transcriptsRoot: sync.archivePath,
|
|
70
|
+
fromTag,
|
|
71
|
+
toTag
|
|
126
72
|
});
|
|
127
|
-
|
|
73
|
+
return {
|
|
74
|
+
ok: true,
|
|
75
|
+
code: "recommendations-generated",
|
|
76
|
+
message: `After sync (${sync.copied} copied): created ${result.created.length} improvement task(s); skipped ${result.skipped} duplicate(s)`,
|
|
77
|
+
data: { sync, ...result }
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
82
|
+
return { ok: false, code: "generate-failed", message: msg };
|
|
128
83
|
}
|
|
129
|
-
|
|
130
|
-
|
|
84
|
+
},
|
|
85
|
+
"sync-transcripts": async () => {
|
|
86
|
+
const syncArgs = {
|
|
87
|
+
sourcePath: typeof args.sourcePath === "string" ? args.sourcePath : undefined,
|
|
88
|
+
archivePath: typeof args.archivePath === "string" ? args.archivePath : undefined
|
|
89
|
+
};
|
|
90
|
+
try {
|
|
91
|
+
const state = await loadImprovementState(ctx.workspacePath, ctx.effectiveConfig);
|
|
92
|
+
const sync = await runSyncTranscripts(ctx, syncArgs, state);
|
|
93
|
+
state.lastSyncRunAt = new Date().toISOString();
|
|
94
|
+
await saveImprovementState(ctx.workspacePath, state, ctx.effectiveConfig);
|
|
95
|
+
return {
|
|
96
|
+
ok: true,
|
|
97
|
+
code: "transcripts-synced",
|
|
98
|
+
message: `Copied ${sync.copied} transcript file(s); skipped ${sync.skippedExisting} existing`,
|
|
99
|
+
data: sync
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
104
|
+
return { ok: false, code: "sync-failed", message: msg };
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"ingest-transcripts": async () => {
|
|
108
|
+
const syncArgs = {
|
|
109
|
+
sourcePath: typeof args.sourcePath === "string" ? args.sourcePath : undefined,
|
|
110
|
+
archivePath: typeof args.archivePath === "string" ? args.archivePath : undefined
|
|
111
|
+
};
|
|
112
|
+
const now = new Date();
|
|
113
|
+
try {
|
|
114
|
+
const state = await loadImprovementState(ctx.workspacePath, ctx.effectiveConfig);
|
|
115
|
+
const sync = await runSyncTranscripts(ctx, syncArgs, state);
|
|
116
|
+
const cfg = resolveImprovementTranscriptConfig(ctx, syncArgs);
|
|
117
|
+
const cadenceDecision = resolveCadenceDecision(now, state.lastIngestRunAt, cfg.minIntervalMinutes, sync.copied, cfg.skipIfNoNewTranscripts);
|
|
118
|
+
state.lastSyncRunAt = now.toISOString();
|
|
119
|
+
const generate = cadenceDecision.shouldRunGenerate || args.forceGenerate === true || args.runGenerate === true;
|
|
120
|
+
let recommendations = null;
|
|
121
|
+
if (generate) {
|
|
122
|
+
recommendations = await runGenerateRecommendations(ctx, {
|
|
123
|
+
transcriptsRoot: sync.archivePath
|
|
124
|
+
});
|
|
125
|
+
state.lastIngestRunAt = now.toISOString();
|
|
126
|
+
}
|
|
127
|
+
await saveImprovementState(ctx.workspacePath, state, ctx.effectiveConfig);
|
|
128
|
+
const status = generate ? "generated" : "skipped";
|
|
129
|
+
return {
|
|
130
|
+
ok: true,
|
|
131
|
+
code: "transcripts-ingested",
|
|
132
|
+
message: `Ingest ${status}; sync copied ${sync.copied} file(s)`,
|
|
133
|
+
data: {
|
|
134
|
+
sync,
|
|
135
|
+
cadence: {
|
|
136
|
+
minIntervalMinutes: cfg.minIntervalMinutes,
|
|
137
|
+
skipIfNoNewTranscripts: cfg.skipIfNoNewTranscripts,
|
|
138
|
+
decision: cadenceDecision.reason
|
|
139
|
+
},
|
|
140
|
+
generatedRecommendations: recommendations
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
146
|
+
return { ok: false, code: "ingest-failed", message: msg };
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
"transcript-automation-status": async () => {
|
|
150
|
+
const syncArgs = {
|
|
151
|
+
sourcePath: typeof args.sourcePath === "string" ? args.sourcePath : undefined,
|
|
152
|
+
archivePath: typeof args.archivePath === "string" ? args.archivePath : undefined
|
|
153
|
+
};
|
|
154
|
+
const state = await loadImprovementState(ctx.workspacePath, ctx.effectiveConfig);
|
|
155
|
+
const cfg = resolveImprovementTranscriptConfig(ctx, syncArgs);
|
|
131
156
|
return {
|
|
132
157
|
ok: true,
|
|
133
|
-
code: "
|
|
134
|
-
message:
|
|
158
|
+
code: "transcript-automation-status",
|
|
159
|
+
message: "Transcript automation status",
|
|
135
160
|
data: {
|
|
136
|
-
|
|
161
|
+
schemaVersion: 1,
|
|
162
|
+
lastSyncRunAt: state.lastSyncRunAt,
|
|
163
|
+
lastIngestRunAt: state.lastIngestRunAt,
|
|
137
164
|
cadence: {
|
|
138
165
|
minIntervalMinutes: cfg.minIntervalMinutes,
|
|
139
166
|
skipIfNoNewTranscripts: cfg.skipIfNoNewTranscripts,
|
|
140
|
-
|
|
167
|
+
maxRecommendationCandidatesPerRun: getMaxRecommendationCandidatesPerRun(ctx)
|
|
141
168
|
},
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
return {
|
|
159
|
-
ok: true,
|
|
160
|
-
code: "transcript-automation-status",
|
|
161
|
-
message: "Transcript automation status",
|
|
162
|
-
data: {
|
|
163
|
-
schemaVersion: 1,
|
|
164
|
-
lastSyncRunAt: state.lastSyncRunAt,
|
|
165
|
-
lastIngestRunAt: state.lastIngestRunAt,
|
|
166
|
-
cadence: {
|
|
167
|
-
minIntervalMinutes: cfg.minIntervalMinutes,
|
|
168
|
-
skipIfNoNewTranscripts: cfg.skipIfNoNewTranscripts,
|
|
169
|
-
maxRecommendationCandidatesPerRun: getMaxRecommendationCandidatesPerRun(ctx)
|
|
170
|
-
},
|
|
171
|
-
transcripts: {
|
|
172
|
-
sourcePath: cfg.sourcePath || null,
|
|
173
|
-
archivePath: cfg.archivePath,
|
|
174
|
-
discoveryPaths: cfg.discoveryPaths,
|
|
175
|
-
budgets: {
|
|
176
|
-
maxFilesPerSync: cfg.maxFilesPerSync,
|
|
177
|
-
maxBytesPerFile: cfg.maxBytesPerFile,
|
|
178
|
-
maxTotalScanBytes: cfg.maxTotalScanBytes
|
|
169
|
+
transcripts: {
|
|
170
|
+
sourcePath: cfg.sourcePath || null,
|
|
171
|
+
archivePath: cfg.archivePath,
|
|
172
|
+
discoveryPaths: cfg.discoveryPaths,
|
|
173
|
+
budgets: {
|
|
174
|
+
maxFilesPerSync: cfg.maxFilesPerSync,
|
|
175
|
+
maxBytesPerFile: cfg.maxBytesPerFile,
|
|
176
|
+
maxTotalScanBytes: cfg.maxTotalScanBytes
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
retryQueue: {
|
|
180
|
+
pending: state.transcriptRetryQueue?.length ?? 0,
|
|
181
|
+
entries: state.transcriptRetryQueue ?? []
|
|
182
|
+
},
|
|
183
|
+
policySession: {
|
|
184
|
+
sessionId: resolveSessionId(process.env)
|
|
179
185
|
}
|
|
180
|
-
},
|
|
181
|
-
retryQueue: {
|
|
182
|
-
pending: state.transcriptRetryQueue?.length ?? 0,
|
|
183
|
-
entries: state.transcriptRetryQueue ?? []
|
|
184
|
-
},
|
|
185
|
-
policySession: {
|
|
186
|
-
sessionId: resolveSessionId(process.env)
|
|
187
186
|
}
|
|
187
|
+
};
|
|
188
|
+
},
|
|
189
|
+
"query-lineage": async () => {
|
|
190
|
+
const taskId = typeof args.taskId === "string" ? args.taskId.trim() : "";
|
|
191
|
+
if (!taskId) {
|
|
192
|
+
return { ok: false, code: "invalid-args", message: "query-lineage requires taskId" };
|
|
188
193
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
194
|
+
const chain = await queryLineageChain(ctx.workspacePath, taskId);
|
|
195
|
+
return {
|
|
196
|
+
ok: true,
|
|
197
|
+
code: "lineage-queried",
|
|
198
|
+
message: `${chain.events.length} lineage event(s) for ${taskId}`,
|
|
199
|
+
data: chain
|
|
200
|
+
};
|
|
195
201
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
message: `${chain.events.length} lineage event(s) for ${taskId}`,
|
|
201
|
-
data: chain
|
|
202
|
-
};
|
|
203
|
-
}
|
|
202
|
+
};
|
|
203
|
+
const handler = handlers[command.name];
|
|
204
|
+
if (handler)
|
|
205
|
+
return handler();
|
|
204
206
|
return {
|
|
205
207
|
ok: false,
|
|
206
208
|
code: "unsupported-command",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TransitionEvidence } from "
|
|
1
|
+
import type { TransitionEvidence } from "../../core/planning/index.js";
|
|
2
2
|
import type { EvidenceKind, ConfidenceSignals } from "./confidence.js";
|
|
3
3
|
import { computeHeuristicConfidence } from "./confidence.js";
|
|
4
4
|
import type { ImprovementStateDocument } from "./improvement-state.js";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy-gated `workspace-kit run` commands owned by the improvement module.
|
|
3
|
+
*/
|
|
4
|
+
export declare const IMPROVEMENT_POLICY_COMMAND_NAMES: readonly [readonly ["generate-recommendations", "improvement.generate-recommendations"], readonly ["ingest-transcripts", "improvement.ingest-transcripts"]];
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy-gated `workspace-kit run` commands owned by the improvement module.
|
|
3
|
+
*/
|
|
4
|
+
export const IMPROVEMENT_POLICY_COMMAND_NAMES = [
|
|
5
|
+
["generate-recommendations", "improvement.generate-recommendations"],
|
|
6
|
+
["ingest-transcripts", "improvement.ingest-transcripts"]
|
|
7
|
+
];
|
package/dist/modules/index.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default module bundle + selective re-exports. Policy: see `docs/maintainers/module-build-guide.md` (Barrel export policy).
|
|
3
|
+
*/
|
|
4
|
+
import type { WorkflowModule } from "../contracts/module-contract.js";
|
|
5
|
+
export declare const defaultRegistryModules: WorkflowModule[];
|
|
6
|
+
export { agentBehaviorModule, BUILTIN_PROFILES, DEFAULT_BUILTIN_PROFILE_ID, mergeDimensions, validateBehaviorProfile } from "./agent-behavior/index.js";
|
|
1
7
|
export { approvalsModule } from "./approvals/index.js";
|
|
2
8
|
export { documentationModule } from "./documentation/index.js";
|
|
3
9
|
export type { DocumentationConflict, DocumentationGenerateOptions, DocumentationGenerateResult, DocumentationGenerationEvidence, DocumentationValidationIssue } from "./documentation/types.js";
|
package/dist/modules/index.js
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
import { agentBehaviorModule } from "./agent-behavior/index.js";
|
|
2
|
+
import { approvalsModule } from "./approvals/index.js";
|
|
3
|
+
import { documentationModule } from "./documentation/index.js";
|
|
4
|
+
import { improvementModule } from "./improvement/index.js";
|
|
5
|
+
import { planningModule } from "./planning/index.js";
|
|
6
|
+
import { taskEngineModule } from "./task-engine/index.js";
|
|
7
|
+
import { workspaceConfigModule } from "./workspace-config/index.js";
|
|
8
|
+
export const defaultRegistryModules = [
|
|
9
|
+
workspaceConfigModule,
|
|
10
|
+
documentationModule,
|
|
11
|
+
agentBehaviorModule,
|
|
12
|
+
taskEngineModule,
|
|
13
|
+
approvalsModule,
|
|
14
|
+
planningModule,
|
|
15
|
+
improvementModule
|
|
16
|
+
];
|
|
17
|
+
export { agentBehaviorModule, BUILTIN_PROFILES, DEFAULT_BUILTIN_PROFILE_ID, mergeDimensions, validateBehaviorProfile } from "./agent-behavior/index.js";
|
|
1
18
|
export { approvalsModule } from "./approvals/index.js";
|
|
2
19
|
export { documentationModule } from "./documentation/index.js";
|
|
3
20
|
export { improvementModule } from "./improvement/index.js";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { PlanningWorkflowType } from "./types.js";
|
|
2
|
+
export type PlanningWishlistArtifact = {
|
|
3
|
+
schemaVersion: 1;
|
|
4
|
+
planningType: PlanningWorkflowType;
|
|
5
|
+
generatedAt: string;
|
|
6
|
+
goals: string[];
|
|
7
|
+
approach: string;
|
|
8
|
+
majorTechnicalDecisions: string[];
|
|
9
|
+
candidateFeaturesOrChanges: string[];
|
|
10
|
+
assumptions: string[];
|
|
11
|
+
openQuestions: string[];
|
|
12
|
+
risksAndConstraints: string[];
|
|
13
|
+
sourceAnswers: Record<string, string>;
|
|
14
|
+
};
|
|
15
|
+
export declare function composePlanningWishlistArtifact(args: {
|
|
16
|
+
planningType: PlanningWorkflowType;
|
|
17
|
+
answers: Record<string, unknown>;
|
|
18
|
+
unresolvedCriticalQuestionIds: string[];
|
|
19
|
+
}): PlanningWishlistArtifact;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
function answer(answers, key, fallback) {
|
|
2
|
+
const value = answers[key];
|
|
3
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
4
|
+
return fallback;
|
|
5
|
+
}
|
|
6
|
+
return value.trim();
|
|
7
|
+
}
|
|
8
|
+
function list(answers, key) {
|
|
9
|
+
const value = answers[key];
|
|
10
|
+
if (Array.isArray(value)) {
|
|
11
|
+
return value.filter((x) => typeof x === "string" && x.trim().length > 0).map((x) => x.trim());
|
|
12
|
+
}
|
|
13
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
14
|
+
return [value.trim()];
|
|
15
|
+
}
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
export function composePlanningWishlistArtifact(args) {
|
|
19
|
+
const { planningType, answers, unresolvedCriticalQuestionIds } = args;
|
|
20
|
+
const sourceAnswers = {};
|
|
21
|
+
for (const [key, value] of Object.entries(answers)) {
|
|
22
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
23
|
+
sourceAnswers[key] = value.trim();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const goals = list(answers, "goals");
|
|
27
|
+
if (goals.length === 0) {
|
|
28
|
+
const inferredGoal = answer(answers, "goal", "") ||
|
|
29
|
+
answer(answers, "featureGoal", "") ||
|
|
30
|
+
answer(answers, "changeGoal", "");
|
|
31
|
+
if (inferredGoal)
|
|
32
|
+
goals.push(inferredGoal);
|
|
33
|
+
}
|
|
34
|
+
const candidate = list(answers, "candidateFeaturesOrChanges");
|
|
35
|
+
if (candidate.length === 0) {
|
|
36
|
+
const inferred = answer(answers, "scope", "");
|
|
37
|
+
if (inferred)
|
|
38
|
+
candidate.push(inferred);
|
|
39
|
+
}
|
|
40
|
+
const majorTechnicalDecisions = list(answers, "majorTechnicalDecisions");
|
|
41
|
+
const decisionRationale = answer(answers, "decisionRationale", "");
|
|
42
|
+
if (decisionRationale && majorTechnicalDecisions.length === 0) {
|
|
43
|
+
majorTechnicalDecisions.push(decisionRationale);
|
|
44
|
+
}
|
|
45
|
+
const assumptions = list(answers, "assumptions");
|
|
46
|
+
const openQuestions = [
|
|
47
|
+
...list(answers, "openQuestions"),
|
|
48
|
+
...unresolvedCriticalQuestionIds.map((id) => `Unresolved critical question: ${id}`)
|
|
49
|
+
];
|
|
50
|
+
const risksAndConstraints = list(answers, "risksAndConstraints");
|
|
51
|
+
const constraints = answer(answers, "constraints", "");
|
|
52
|
+
if (constraints) {
|
|
53
|
+
risksAndConstraints.push(`Constraint: ${constraints}`);
|
|
54
|
+
}
|
|
55
|
+
const riskPriority = answer(answers, "riskPriority", "");
|
|
56
|
+
if (riskPriority) {
|
|
57
|
+
risksAndConstraints.push(`Risk priority: ${riskPriority}`);
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
schemaVersion: 1,
|
|
61
|
+
planningType,
|
|
62
|
+
generatedAt: new Date().toISOString(),
|
|
63
|
+
goals,
|
|
64
|
+
approach: answer(answers, "approach", "Context-driven workflow guided by planning rules."),
|
|
65
|
+
majorTechnicalDecisions,
|
|
66
|
+
candidateFeaturesOrChanges: candidate,
|
|
67
|
+
assumptions,
|
|
68
|
+
openQuestions,
|
|
69
|
+
risksAndConstraints,
|
|
70
|
+
sourceAnswers
|
|
71
|
+
};
|
|
72
|
+
}
|