@workflow-cannon/workspace-kit 0.18.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 +61 -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 +8 -0
- 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/index.js +384 -50
- package/dist/modules/planning/question-engine.d.ts +2 -0
- package/dist/modules/planning/question-engine.js +8 -1
- 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,11 +1,51 @@
|
|
|
1
|
+
import { LEGACY_WISHLIST_ID_METADATA_KEY, WISHLIST_INTAKE_TASK_TYPE } from "./wishlist-intake.js";
|
|
2
|
+
import { WISHLIST_ID_RE } from "./wishlist-validation.js";
|
|
1
3
|
function nonEmptyStringArray(value) {
|
|
2
4
|
return Array.isArray(value) && value.some((entry) => typeof entry === "string" && entry.trim().length > 0);
|
|
3
5
|
}
|
|
6
|
+
function nonEmptyMetaString(metadata, key) {
|
|
7
|
+
const v = metadata?.[key];
|
|
8
|
+
return typeof v === "string" && v.trim().length > 0;
|
|
9
|
+
}
|
|
4
10
|
/**
|
|
5
11
|
* Optional strictness for known task types.
|
|
6
12
|
* Unknown/custom task types remain passthrough for compatibility.
|
|
7
13
|
*/
|
|
8
14
|
export function validateKnownTaskTypeRequirements(task) {
|
|
15
|
+
if (task.type === WISHLIST_INTAKE_TASK_TYPE) {
|
|
16
|
+
const meta = task.metadata;
|
|
17
|
+
if (!meta || typeof meta !== "object" || Array.isArray(meta)) {
|
|
18
|
+
return {
|
|
19
|
+
code: "invalid-task-type-requirements",
|
|
20
|
+
message: `Type '${task.type}' requires a metadata object with intake fields`
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
const m = meta;
|
|
24
|
+
const need = [
|
|
25
|
+
"problemStatement",
|
|
26
|
+
"expectedOutcome",
|
|
27
|
+
"impact",
|
|
28
|
+
"constraints",
|
|
29
|
+
"successSignals",
|
|
30
|
+
"requestor",
|
|
31
|
+
"evidenceRef"
|
|
32
|
+
];
|
|
33
|
+
const missing = need.filter((k) => !nonEmptyMetaString(m, k));
|
|
34
|
+
if (missing.length > 0) {
|
|
35
|
+
return {
|
|
36
|
+
code: "invalid-task-type-requirements",
|
|
37
|
+
message: `Type '${task.type}' requires non-empty metadata fields: ${missing.join(", ")}`
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
const legacy = m[LEGACY_WISHLIST_ID_METADATA_KEY];
|
|
41
|
+
if (legacy !== undefined && (typeof legacy !== "string" || !WISHLIST_ID_RE.test(legacy))) {
|
|
42
|
+
return {
|
|
43
|
+
code: "invalid-task-type-requirements",
|
|
44
|
+
message: `metadata.${LEGACY_WISHLIST_ID_METADATA_KEY} must match W<number> when present`
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
9
49
|
if (task.type !== "improvement") {
|
|
10
50
|
return null;
|
|
11
51
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { TaskEntity } from "./types.js";
|
|
2
|
+
import type { WishlistItem } from "./wishlist-types.js";
|
|
3
|
+
/** Task type for ideation items formerly stored as wishlist `W###` rows (Phase 24). */
|
|
4
|
+
export declare const WISHLIST_INTAKE_TASK_TYPE = "wishlist_intake";
|
|
5
|
+
/** Provenance when migrated from legacy wishlist id (`W1`, …). Omitted for net-new intake tasks. */
|
|
6
|
+
export declare const LEGACY_WISHLIST_ID_METADATA_KEY = "legacyWishlistId";
|
|
7
|
+
declare const INTAKE_META_KEYS: readonly ["problemStatement", "expectedOutcome", "impact", "constraints", "successSignals", "requestor", "evidenceRef"];
|
|
8
|
+
export declare function isWishlistIntakeTask(task: TaskEntity): boolean;
|
|
9
|
+
export declare function allocateNextTaskNumericId(tasks: TaskEntity[]): string;
|
|
10
|
+
/**
|
|
11
|
+
* Build a `wishlist_intake` task from a legacy `WishlistItem`. Caller supplies the new `T###` id.
|
|
12
|
+
*/
|
|
13
|
+
export declare function taskEntityFromWishlistItem(item: WishlistItem, newTaskId: string, now: string): TaskEntity;
|
|
14
|
+
/**
|
|
15
|
+
* Create a new open wishlist-intake task (no legacy wishlist id). `intake` must pass `validateWishlistIntakePayload` shape except `id` may be omitted.
|
|
16
|
+
*/
|
|
17
|
+
export declare function taskEntityFromNewIntake(intake: Record<string, unknown>, newTaskId: string, now: string, extraMetadata?: Record<string, unknown>): TaskEntity;
|
|
18
|
+
/** Map a `wishlist_intake` task to the wire shape consumers expect from list/get-wishlist. */
|
|
19
|
+
export declare function wishlistIntakeTaskToItem(task: TaskEntity): WishlistItem | null;
|
|
20
|
+
export declare function listWishlistIntakeTasksAsItems(tasks: TaskEntity[]): WishlistItem[];
|
|
21
|
+
export declare function findWishlistIntakeTaskByLegacyOrTaskId(tasks: TaskEntity[], wishlistIdOrTaskId: string): TaskEntity | undefined;
|
|
22
|
+
export { INTAKE_META_KEYS };
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { WISHLIST_ID_RE } from "./wishlist-validation.js";
|
|
2
|
+
const TASK_ID_RE = /^T\d+$/;
|
|
3
|
+
/** Task type for ideation items formerly stored as wishlist `W###` rows (Phase 24). */
|
|
4
|
+
export const WISHLIST_INTAKE_TASK_TYPE = "wishlist_intake";
|
|
5
|
+
/** Provenance when migrated from legacy wishlist id (`W1`, …). Omitted for net-new intake tasks. */
|
|
6
|
+
export const LEGACY_WISHLIST_ID_METADATA_KEY = "legacyWishlistId";
|
|
7
|
+
const INTAKE_META_KEYS = [
|
|
8
|
+
"problemStatement",
|
|
9
|
+
"expectedOutcome",
|
|
10
|
+
"impact",
|
|
11
|
+
"constraints",
|
|
12
|
+
"successSignals",
|
|
13
|
+
"requestor",
|
|
14
|
+
"evidenceRef"
|
|
15
|
+
];
|
|
16
|
+
export function isWishlistIntakeTask(task) {
|
|
17
|
+
return task.type === WISHLIST_INTAKE_TASK_TYPE;
|
|
18
|
+
}
|
|
19
|
+
export function allocateNextTaskNumericId(tasks) {
|
|
20
|
+
let max = 0;
|
|
21
|
+
for (const task of tasks) {
|
|
22
|
+
const m = /^T(\d+)$/.exec(task.id);
|
|
23
|
+
if (m) {
|
|
24
|
+
const n = Number(m[1]);
|
|
25
|
+
if (Number.isFinite(n)) {
|
|
26
|
+
max = Math.max(max, n);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return `T${max + 1}`;
|
|
31
|
+
}
|
|
32
|
+
function wishlistStatusToTaskStatus(status) {
|
|
33
|
+
if (status === "open") {
|
|
34
|
+
return "proposed";
|
|
35
|
+
}
|
|
36
|
+
if (status === "cancelled") {
|
|
37
|
+
return "cancelled";
|
|
38
|
+
}
|
|
39
|
+
return "completed";
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Build a `wishlist_intake` task from a legacy `WishlistItem`. Caller supplies the new `T###` id.
|
|
43
|
+
*/
|
|
44
|
+
export function taskEntityFromWishlistItem(item, newTaskId, now) {
|
|
45
|
+
const metadata = {
|
|
46
|
+
[LEGACY_WISHLIST_ID_METADATA_KEY]: item.id,
|
|
47
|
+
problemStatement: item.problemStatement,
|
|
48
|
+
expectedOutcome: item.expectedOutcome,
|
|
49
|
+
impact: item.impact,
|
|
50
|
+
constraints: item.constraints,
|
|
51
|
+
successSignals: item.successSignals,
|
|
52
|
+
requestor: item.requestor,
|
|
53
|
+
evidenceRef: item.evidenceRef
|
|
54
|
+
};
|
|
55
|
+
if (item.convertedToTaskIds?.length) {
|
|
56
|
+
metadata.wishlistConvertedToTaskIds = [...item.convertedToTaskIds];
|
|
57
|
+
}
|
|
58
|
+
if (item.conversionDecomposition) {
|
|
59
|
+
metadata.wishlistConversionDecomposition = item.conversionDecomposition;
|
|
60
|
+
}
|
|
61
|
+
if (item.convertedAt) {
|
|
62
|
+
metadata.wishlistConvertedAt = item.convertedAt;
|
|
63
|
+
}
|
|
64
|
+
const task = {
|
|
65
|
+
id: newTaskId,
|
|
66
|
+
title: item.title,
|
|
67
|
+
type: WISHLIST_INTAKE_TASK_TYPE,
|
|
68
|
+
status: wishlistStatusToTaskStatus(item.status),
|
|
69
|
+
createdAt: item.createdAt,
|
|
70
|
+
updatedAt: now,
|
|
71
|
+
metadata
|
|
72
|
+
};
|
|
73
|
+
return task;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Create a new open wishlist-intake task (no legacy wishlist id). `intake` must pass `validateWishlistIntakePayload` shape except `id` may be omitted.
|
|
77
|
+
*/
|
|
78
|
+
export function taskEntityFromNewIntake(intake, newTaskId, now, extraMetadata) {
|
|
79
|
+
const metadata = {
|
|
80
|
+
problemStatement: String(intake.problemStatement ?? "").trim(),
|
|
81
|
+
expectedOutcome: String(intake.expectedOutcome ?? "").trim(),
|
|
82
|
+
impact: String(intake.impact ?? "").trim(),
|
|
83
|
+
constraints: String(intake.constraints ?? "").trim(),
|
|
84
|
+
successSignals: String(intake.successSignals ?? "").trim(),
|
|
85
|
+
requestor: String(intake.requestor ?? "").trim(),
|
|
86
|
+
evidenceRef: String(intake.evidenceRef ?? "").trim(),
|
|
87
|
+
...(extraMetadata ?? {})
|
|
88
|
+
};
|
|
89
|
+
return {
|
|
90
|
+
id: newTaskId,
|
|
91
|
+
title: String(intake.title ?? "").trim(),
|
|
92
|
+
type: WISHLIST_INTAKE_TASK_TYPE,
|
|
93
|
+
status: "proposed",
|
|
94
|
+
createdAt: now,
|
|
95
|
+
updatedAt: now,
|
|
96
|
+
metadata
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/** Map a `wishlist_intake` task to the wire shape consumers expect from list/get-wishlist. */
|
|
100
|
+
export function wishlistIntakeTaskToItem(task) {
|
|
101
|
+
if (!isWishlistIntakeTask(task) || !task.metadata) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
const m = task.metadata;
|
|
105
|
+
const legacy = m[LEGACY_WISHLIST_ID_METADATA_KEY];
|
|
106
|
+
const id = typeof legacy === "string" && WISHLIST_ID_RE.test(legacy)
|
|
107
|
+
? legacy
|
|
108
|
+
: task.id;
|
|
109
|
+
let status = "open";
|
|
110
|
+
if (task.status === "cancelled") {
|
|
111
|
+
status = "cancelled";
|
|
112
|
+
}
|
|
113
|
+
else if (task.status === "completed") {
|
|
114
|
+
status = "converted";
|
|
115
|
+
}
|
|
116
|
+
const str = (k) => (typeof m[k] === "string" ? m[k] : String(m[k] ?? ""));
|
|
117
|
+
const item = {
|
|
118
|
+
id,
|
|
119
|
+
status,
|
|
120
|
+
title: task.title,
|
|
121
|
+
problemStatement: str("problemStatement"),
|
|
122
|
+
expectedOutcome: str("expectedOutcome"),
|
|
123
|
+
impact: str("impact"),
|
|
124
|
+
constraints: str("constraints"),
|
|
125
|
+
successSignals: str("successSignals"),
|
|
126
|
+
requestor: str("requestor"),
|
|
127
|
+
evidenceRef: str("evidenceRef"),
|
|
128
|
+
createdAt: task.createdAt,
|
|
129
|
+
updatedAt: task.updatedAt
|
|
130
|
+
};
|
|
131
|
+
const convIds = m.wishlistConvertedToTaskIds;
|
|
132
|
+
if (Array.isArray(convIds) && convIds.every((x) => typeof x === "string")) {
|
|
133
|
+
item.convertedToTaskIds = convIds;
|
|
134
|
+
}
|
|
135
|
+
const dec = m.wishlistConversionDecomposition;
|
|
136
|
+
if (dec && typeof dec === "object" && !Array.isArray(dec)) {
|
|
137
|
+
const o = dec;
|
|
138
|
+
if (typeof o.rationale === "string" &&
|
|
139
|
+
typeof o.boundaries === "string" &&
|
|
140
|
+
typeof o.dependencyIntent === "string") {
|
|
141
|
+
item.conversionDecomposition = {
|
|
142
|
+
rationale: o.rationale,
|
|
143
|
+
boundaries: o.boundaries,
|
|
144
|
+
dependencyIntent: o.dependencyIntent
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const cat = m.wishlistConvertedAt;
|
|
149
|
+
if (typeof cat === "string") {
|
|
150
|
+
item.convertedAt = cat;
|
|
151
|
+
}
|
|
152
|
+
return item;
|
|
153
|
+
}
|
|
154
|
+
export function listWishlistIntakeTasksAsItems(tasks) {
|
|
155
|
+
const out = [];
|
|
156
|
+
for (const t of tasks) {
|
|
157
|
+
const row = wishlistIntakeTaskToItem(t);
|
|
158
|
+
if (row) {
|
|
159
|
+
out.push(row);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return out;
|
|
163
|
+
}
|
|
164
|
+
export function findWishlistIntakeTaskByLegacyOrTaskId(tasks, wishlistIdOrTaskId) {
|
|
165
|
+
const q = wishlistIdOrTaskId.trim();
|
|
166
|
+
if (!q) {
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
if (TASK_ID_RE.test(q)) {
|
|
170
|
+
const t = tasks.find((x) => x.id === q);
|
|
171
|
+
return t && isWishlistIntakeTask(t) ? t : undefined;
|
|
172
|
+
}
|
|
173
|
+
if (WISHLIST_ID_RE.test(q)) {
|
|
174
|
+
return tasks.find((t) => isWishlistIntakeTask(t) &&
|
|
175
|
+
t.metadata &&
|
|
176
|
+
t.metadata[LEGACY_WISHLIST_ID_METADATA_KEY] === q);
|
|
177
|
+
}
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
export { INTAKE_META_KEYS };
|
|
@@ -11,6 +11,10 @@ export type WishlistValidationResult = {
|
|
|
11
11
|
* Validates intake fields for creating or replacing content on an open wishlist item.
|
|
12
12
|
* Wishlist items never carry a Task Engine `phase`; reject if present.
|
|
13
13
|
*/
|
|
14
|
+
/**
|
|
15
|
+
* Validates required wishlist intake strings without requiring a `W###` id (Phase 24 task-backed intake).
|
|
16
|
+
*/
|
|
17
|
+
export declare function validateWishlistContentFields(args: Record<string, unknown>): WishlistValidationResult;
|
|
14
18
|
export declare function validateWishlistIntakePayload(args: Record<string, unknown>): WishlistValidationResult;
|
|
15
19
|
export declare function buildWishlistItemFromIntake(args: Record<string, unknown>, timestamp: string): Omit<WishlistItem, "convertedAt" | "convertedToTaskIds" | "conversionDecomposition">;
|
|
16
20
|
export declare function validateWishlistUpdatePayload(updates: Record<string, unknown>): WishlistValidationResult;
|
|
@@ -20,6 +20,25 @@ function nonEmptyString(v, label) {
|
|
|
20
20
|
* Validates intake fields for creating or replacing content on an open wishlist item.
|
|
21
21
|
* Wishlist items never carry a Task Engine `phase`; reject if present.
|
|
22
22
|
*/
|
|
23
|
+
/**
|
|
24
|
+
* Validates required wishlist intake strings without requiring a `W###` id (Phase 24 task-backed intake).
|
|
25
|
+
*/
|
|
26
|
+
export function validateWishlistContentFields(args) {
|
|
27
|
+
const errors = [];
|
|
28
|
+
if ("phase" in args && args.phase !== undefined) {
|
|
29
|
+
errors.push("Wishlist intake must not include 'phase'; only canonical phased tasks use phase.");
|
|
30
|
+
}
|
|
31
|
+
for (const key of REQUIRED_STRING_FIELDS) {
|
|
32
|
+
const s = nonEmptyString(args[key], key);
|
|
33
|
+
if (s === null) {
|
|
34
|
+
errors.push(`Wishlist '${key}' is required and must be a non-empty string.`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (errors.length > 0) {
|
|
38
|
+
return { ok: false, errors };
|
|
39
|
+
}
|
|
40
|
+
return { ok: true };
|
|
41
|
+
}
|
|
23
42
|
export function validateWishlistIntakePayload(args) {
|
|
24
43
|
const errors = [];
|
|
25
44
|
if ("phase" in args && args.phase !== undefined) {
|
|
@@ -46,19 +46,16 @@ export const workspaceConfigModule = {
|
|
|
46
46
|
id: "workspace-config",
|
|
47
47
|
version: "0.4.0",
|
|
48
48
|
contractVersion: "1",
|
|
49
|
+
stateSchema: 1,
|
|
49
50
|
capabilities: ["diagnostics"],
|
|
50
51
|
dependsOn: [],
|
|
52
|
+
optionalPeers: [],
|
|
51
53
|
enabledByDefault: true,
|
|
52
54
|
config: {
|
|
53
55
|
path: "src/modules/workspace-config/config.md",
|
|
54
56
|
format: "md",
|
|
55
57
|
description: "Workspace config registry and explain surface."
|
|
56
58
|
},
|
|
57
|
-
state: {
|
|
58
|
-
path: "src/modules/workspace-config/state.md",
|
|
59
|
-
format: "md",
|
|
60
|
-
description: "Workspace config module runtime state (none)."
|
|
61
|
-
},
|
|
62
59
|
instructions: {
|
|
63
60
|
directory: "src/modules/workspace-config/instructions",
|
|
64
61
|
entries: [
|
|
@@ -85,12 +82,13 @@ export const workspaceConfigModule = {
|
|
|
85
82
|
};
|
|
86
83
|
}
|
|
87
84
|
const baseCtx = { workspacePath: ctx.workspacePath, registry: reg };
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
85
|
+
const handlers = {
|
|
86
|
+
"explain-config": () => handleExplainConfig(command.args ?? {}, baseCtx),
|
|
87
|
+
"resolve-config": () => handleResolveConfig(command.args ?? {}, baseCtx)
|
|
88
|
+
};
|
|
89
|
+
const handler = handlers[command.name];
|
|
90
|
+
if (handler)
|
|
91
|
+
return handler();
|
|
94
92
|
return {
|
|
95
93
|
ok: false,
|
|
96
94
|
code: "unknown-command",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workflow-cannon/workspace-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"packageManager": "pnpm@10.0.0",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
},
|
|
20
20
|
"scripts": {
|
|
21
21
|
"build": "tsc -p tsconfig.json",
|
|
22
|
-
"check": "tsc -p tsconfig.json --noEmit && node scripts/check-task-engine-run-contracts.mjs",
|
|
22
|
+
"check": "tsc -p tsconfig.json --noEmit && node scripts/check-task-engine-run-contracts.mjs && node scripts/check-agent-cli-map-coverage.mjs && node scripts/check-orphan-instructions.mjs",
|
|
23
23
|
"clean": "rm -rf dist",
|
|
24
24
|
"test": "pnpm run build && node --test test/**/*.test.mjs",
|
|
25
25
|
"pack:dry-run": "pnpm run build && pnpm pack --pack-destination ./artifacts/workspace-kit-pack",
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://workflow-cannon.dev/schemas/agent-behavior-profile.schema.json",
|
|
4
|
+
"title": "Agent behavior profile",
|
|
5
|
+
"description": "Advisory interaction posture for AI agents; subordinate to PRINCIPLES and policy.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["schemaVersion", "id", "label", "summary", "dimensions"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"schemaVersion": { "const": 1 },
|
|
11
|
+
"id": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"pattern": "^(builtin|custom):[a-z0-9-]+$"
|
|
14
|
+
},
|
|
15
|
+
"extends": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"pattern": "^(builtin|custom):[a-z0-9-]+$"
|
|
18
|
+
},
|
|
19
|
+
"label": { "type": "string", "minLength": 1, "maxLength": 120 },
|
|
20
|
+
"summary": { "type": "string", "minLength": 1, "maxLength": 500 },
|
|
21
|
+
"dimensions": {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"additionalProperties": false,
|
|
24
|
+
"required": [
|
|
25
|
+
"deliberationDepth",
|
|
26
|
+
"changeAppetite",
|
|
27
|
+
"checkInFrequency",
|
|
28
|
+
"explanationVerbosity",
|
|
29
|
+
"explorationStyle",
|
|
30
|
+
"ambiguityHandling"
|
|
31
|
+
],
|
|
32
|
+
"properties": {
|
|
33
|
+
"deliberationDepth": { "type": "string", "enum": ["low", "medium", "high"] },
|
|
34
|
+
"changeAppetite": { "type": "string", "enum": ["conservative", "balanced", "bold"] },
|
|
35
|
+
"checkInFrequency": { "type": "string", "enum": ["rare", "normal", "often"] },
|
|
36
|
+
"explanationVerbosity": { "type": "string", "enum": ["terse", "normal", "verbose"] },
|
|
37
|
+
"explorationStyle": { "type": "string", "enum": ["linear", "parallel"] },
|
|
38
|
+
"ambiguityHandling": { "type": "string", "enum": ["decide", "ask"] }
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"interactionNotes": { "type": "string", "maxLength": 2000 },
|
|
42
|
+
"metadata": {
|
|
43
|
+
"type": "object",
|
|
44
|
+
"additionalProperties": true,
|
|
45
|
+
"properties": {
|
|
46
|
+
"source": { "type": "string" },
|
|
47
|
+
"updatedAt": { "type": "string" },
|
|
48
|
+
"createdAt": { "type": "string" }
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": ["schemaVersion", "packageVersion", "moduleId", "commands"],
|
|
8
8
|
"additionalProperties": false,
|
|
9
|
-
"packageVersion": "0.
|
|
9
|
+
"packageVersion": "0.24.0",
|
|
10
10
|
"properties": {
|
|
11
11
|
"schemaVersion": {
|
|
12
12
|
"const": 1
|
|
13
13
|
},
|
|
14
14
|
"packageVersion": {
|
|
15
|
-
"const": "0.
|
|
15
|
+
"const": "0.24.0",
|
|
16
16
|
"description": "Must match package.json version."
|
|
17
17
|
},
|
|
18
18
|
"moduleId": {
|
|
@@ -44,7 +44,10 @@
|
|
|
44
44
|
"get-next-actions",
|
|
45
45
|
"explain-task-engine-model",
|
|
46
46
|
"migrate-task-persistence",
|
|
47
|
-
"
|
|
47
|
+
"migrate-wishlist-intake",
|
|
48
|
+
"dashboard-summary",
|
|
49
|
+
"get-module-state",
|
|
50
|
+
"list-module-states"
|
|
48
51
|
],
|
|
49
52
|
"additionalProperties": false,
|
|
50
53
|
"properties": {
|
|
@@ -71,7 +74,10 @@
|
|
|
71
74
|
"get-next-actions": { "$ref": "#/$defs/contractNextActions" },
|
|
72
75
|
"explain-task-engine-model": { "$ref": "#/$defs/contractExplainTaskEngineModel" },
|
|
73
76
|
"migrate-task-persistence": { "$ref": "#/$defs/contractMigrateTaskPersistence" },
|
|
74
|
-
"
|
|
77
|
+
"migrate-wishlist-intake": { "$ref": "#/$defs/contractMigrateWishlistIntake" },
|
|
78
|
+
"dashboard-summary": { "$ref": "#/$defs/contractDashboardSummary" },
|
|
79
|
+
"get-module-state": { "$ref": "#/$defs/contractGetModuleState" },
|
|
80
|
+
"list-module-states": { "$ref": "#/$defs/contractListModuleStates" }
|
|
75
81
|
}
|
|
76
82
|
}
|
|
77
83
|
},
|
|
@@ -358,7 +364,7 @@
|
|
|
358
364
|
"properties": {
|
|
359
365
|
"args": {
|
|
360
366
|
"type": "object",
|
|
361
|
-
"required": ["
|
|
367
|
+
"required": ["decomposition", "tasks"],
|
|
362
368
|
"additionalProperties": true
|
|
363
369
|
},
|
|
364
370
|
"responseData": {
|
|
@@ -526,6 +532,23 @@
|
|
|
526
532
|
}
|
|
527
533
|
]
|
|
528
534
|
},
|
|
535
|
+
"contractMigrateWishlistIntake": {
|
|
536
|
+
"allOf": [
|
|
537
|
+
{ "$ref": "#/$defs/contractBase" },
|
|
538
|
+
{
|
|
539
|
+
"properties": {
|
|
540
|
+
"args": {
|
|
541
|
+
"type": "object",
|
|
542
|
+
"additionalProperties": true
|
|
543
|
+
},
|
|
544
|
+
"responseData": {
|
|
545
|
+
"type": "object",
|
|
546
|
+
"additionalProperties": true
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
]
|
|
551
|
+
},
|
|
529
552
|
"contractDashboardSummary": {
|
|
530
553
|
"allOf": [
|
|
531
554
|
{ "$ref": "#/$defs/contractBase" },
|
|
@@ -541,6 +564,7 @@
|
|
|
541
564
|
"schemaVersion",
|
|
542
565
|
"taskStoreLastUpdated",
|
|
543
566
|
"workspaceStatus",
|
|
567
|
+
"planningSession",
|
|
544
568
|
"stateSummary",
|
|
545
569
|
"readyQueueTop",
|
|
546
570
|
"readyQueueCount",
|
|
@@ -550,6 +574,57 @@
|
|
|
550
574
|
"suggestedNext",
|
|
551
575
|
"blockingAnalysis"
|
|
552
576
|
],
|
|
577
|
+
"additionalProperties": true,
|
|
578
|
+
"properties": {
|
|
579
|
+
"planningSession": {
|
|
580
|
+
"type": ["object", "null"],
|
|
581
|
+
"required": [
|
|
582
|
+
"schemaVersion",
|
|
583
|
+
"updatedAt",
|
|
584
|
+
"planningType",
|
|
585
|
+
"outputMode",
|
|
586
|
+
"status",
|
|
587
|
+
"completionPct",
|
|
588
|
+
"answeredCritical",
|
|
589
|
+
"totalCritical",
|
|
590
|
+
"resumeCli"
|
|
591
|
+
],
|
|
592
|
+
"additionalProperties": true
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
]
|
|
599
|
+
},
|
|
600
|
+
"contractGetModuleState": {
|
|
601
|
+
"allOf": [
|
|
602
|
+
{ "$ref": "#/$defs/contractBase" },
|
|
603
|
+
{
|
|
604
|
+
"properties": {
|
|
605
|
+
"args": {
|
|
606
|
+
"type": "object",
|
|
607
|
+
"additionalProperties": true
|
|
608
|
+
},
|
|
609
|
+
"responseData": {
|
|
610
|
+
"type": "object",
|
|
611
|
+
"additionalProperties": true
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
]
|
|
616
|
+
},
|
|
617
|
+
"contractListModuleStates": {
|
|
618
|
+
"allOf": [
|
|
619
|
+
{ "$ref": "#/$defs/contractBase" },
|
|
620
|
+
{
|
|
621
|
+
"properties": {
|
|
622
|
+
"args": {
|
|
623
|
+
"type": "object",
|
|
624
|
+
"additionalProperties": true
|
|
625
|
+
},
|
|
626
|
+
"responseData": {
|
|
627
|
+
"type": "object",
|
|
553
628
|
"additionalProperties": true
|
|
554
629
|
}
|
|
555
630
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# Documentation Module
|
|
2
2
|
|
|
3
|
-
Translates between canonical AI-optimized documentation and human-readable maintainership docs.
|
|
3
|
+
Translates between canonical AI-optimized documentation and human-readable maintainership docs using a v2 keyed record pipeline.
|
|
4
4
|
|
|
5
5
|
Primary responsibilities:
|
|
6
6
|
|
|
7
7
|
- maintain parity between `/.ai` and configured human docs roots (default: `docs/maintainers`)
|
|
8
8
|
- execute instruction-file driven documentation generation
|
|
9
9
|
- record deterministic documentation generation state and evidence
|
|
10
|
+
- render human docs via view models and named deterministic renderers
|
|
10
11
|
|
|
11
12
|
See `src/modules/documentation/RULES.md` for the canonical usage order and validation rules.
|
|
12
13
|
|
|
@@ -14,27 +15,17 @@ See `src/modules/documentation/RULES.md` for the canonical usage order and valid
|
|
|
14
15
|
|
|
15
16
|
Registered on the documentation module and dispatched through `src/core/module-command-router.ts`:
|
|
16
17
|
|
|
17
|
-
- `document-project` — batch: generate
|
|
18
|
-
- `generate-document` — single: generate
|
|
19
|
-
|
|
20
|
-
##
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
- `
|
|
25
|
-
- `
|
|
26
|
-
- `
|
|
27
|
-
- `
|
|
28
|
-
- `
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
- `SUPPORT.md`
|
|
32
|
-
- `TERMS.md`
|
|
33
|
-
- `runbooks/parity-validation-flow.md`
|
|
34
|
-
- `runbooks/consumer-cadence.md`
|
|
35
|
-
- `runbooks/release-channels.md`
|
|
36
|
-
- `workbooks/transcript-automation-baseline.md`
|
|
37
|
-
- `workbooks/phase2-config-policy-workbook.md`
|
|
38
|
-
- `workbooks/task-engine-workbook.md`
|
|
39
|
-
|
|
40
|
-
Adding a new template: add `templates/<Name>.md`, extend the **Inputs** list in `instructions/document-project.md`, and add the same line here.
|
|
18
|
+
- `document-project` — batch: generate all docs from `views/*.view.yaml` (with template fallback for fixture workspaces). See `instructions/document-project.md`.
|
|
19
|
+
- `generate-document` — single: generate one document by `documentType` and render through parser -> validator -> normalizer -> renderer. See `instructions/generate-document.md`.
|
|
20
|
+
|
|
21
|
+
## File layout
|
|
22
|
+
|
|
23
|
+
- `parser.ts` - keyed record parsing from AI docs
|
|
24
|
+
- `validator.ts` - schema/rule validation and auto-resolution
|
|
25
|
+
- `normalizer.ts` - typed normalized model + record indexes
|
|
26
|
+
- `renderer.ts` - deterministic named markdown renderers
|
|
27
|
+
- `view-models.ts` - view model loader and listing
|
|
28
|
+
- `views/*.view.yaml` - rendering section contracts per document target
|
|
29
|
+
- `runtime.ts` - orchestration and IO only
|
|
30
|
+
|
|
31
|
+
Adding a new document target: add/adjust `.ai/<doc>.md` source, create/update matching `views/*.view.yaml`, and ensure a matching template exists if section-coverage checks require it.
|
|
@@ -12,7 +12,7 @@ When guidance conflicts, apply this order:
|
|
|
12
12
|
4. `src/modules/documentation/instructions/document-project.md` (document generation workflow)
|
|
13
13
|
5. `src/modules/documentation/instructions/documentation-maintainer.md` (AI-doc generation policy)
|
|
14
14
|
6. `src/modules/documentation/schemas/documentation-schema.md` (record schema contract)
|
|
15
|
-
7. `src/modules/documentation/
|
|
15
|
+
7. `src/modules/documentation/views/*.view.yaml` (document-type rendering contracts)
|
|
16
16
|
8. `docs/maintainers/module-build-guide.md` (human-readable companion guidance)
|
|
17
17
|
|
|
18
18
|
## Usage Model
|
|
@@ -20,15 +20,15 @@ When guidance conflicts, apply this order:
|
|
|
20
20
|
- Choose an instruction entry from `instructions/` for the operation you want.
|
|
21
21
|
- Discover available callable module operations through `src/core/module-command-router.ts` command listing.
|
|
22
22
|
- Load module config first and restrict writes to configured document paths.
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
23
|
+
- Resolve view model definitions first and treat them as the section/renderer contract.
|
|
24
|
+
- Generate AI-surface content first, then parse/validate/normalize records before human rendering.
|
|
25
|
+
- Human rendering must use named deterministic renderers only.
|
|
26
26
|
|
|
27
27
|
## Command Contracts
|
|
28
28
|
|
|
29
29
|
### `document-project(options)` — batch
|
|
30
30
|
|
|
31
|
-
Generates all project docs by iterating every `.
|
|
31
|
+
Generates all project docs by iterating every `.view.yaml` in `src/modules/documentation/views` (falls back to template discovery in fixture workspaces without views).
|
|
32
32
|
|
|
33
33
|
- Default behavior: **preserve AI docs** (`overwriteAi: false`), **overwrite human docs** (`overwriteHuman: true`), continue on individual failure.
|
|
34
34
|
- Returns batch summary with total/succeeded/failed/skipped counts plus per-document results.
|
|
@@ -37,7 +37,7 @@ Generates all project docs by iterating every `.md` template in `sources.templat
|
|
|
37
37
|
|
|
38
38
|
Generates one document pair (AI + human) for the given `documentType`.
|
|
39
39
|
|
|
40
|
-
- `documentType`: required string basename resolving to
|
|
40
|
+
- `documentType`: required string basename resolving to both AI and human output targets.
|
|
41
41
|
- `options`:
|
|
42
42
|
- `dryRun?: boolean` (default `false`) - compute outputs/validations without writing files
|
|
43
43
|
- `overwrite?: boolean` (default `true`) - allow replacing existing files (both surfaces)
|
|
@@ -46,19 +46,19 @@ Generates one document pair (AI + human) for the given `documentType`.
|
|
|
46
46
|
- `strict?: boolean` (default `true`) - fail on unresolved warnings (validation/conflict/coverage)
|
|
47
47
|
- `maxValidationAttempts?: number` (default from config) - override retry limit
|
|
48
48
|
- `allowWithoutTemplate?: boolean` (default `false`) - continue without template only when explicitly confirmed
|
|
49
|
-
- Shipped
|
|
49
|
+
- Shipped view model files are listed by `listViewModels()` in `view-models.ts`.
|
|
50
50
|
|
|
51
51
|
### Shared semantics
|
|
52
52
|
|
|
53
53
|
- Both commands read paths from module config (`sources.aiRoot`, `sources.humanRoot`, `sources.templatesRoot`, `sources.instructionsRoot`, `sources.schemasRoot`).
|
|
54
54
|
- Both enforce write boundaries to configured output roots only.
|
|
55
|
-
- Both execute AI generation first, then human generation from AI output plus
|
|
55
|
+
- Both execute AI generation first, then human generation from parsed+normalized AI output plus view-model renderers.
|
|
56
56
|
- Both return evidence objects containing files read/written, validations, retries, warnings/conflicts, and timestamp.
|
|
57
57
|
|
|
58
58
|
## Required Validation
|
|
59
59
|
|
|
60
60
|
- Validate AI output against `schemas/documentation-schema.md`.
|
|
61
|
-
- Verify section coverage for
|
|
61
|
+
- Verify section coverage for template-backed content and ensure no unresolved `{{{` blocks remain.
|
|
62
62
|
- Detect conflicts against higher-precedence sources and stop/prompt when required.
|
|
63
63
|
- Emit run evidence (inputs, outputs, validation results, timestamp).
|
|
64
64
|
|