@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.
Files changed (144) hide show
  1. package/README.md +23 -9
  2. package/dist/cli/doctor-planning-issues.js +3 -22
  3. package/dist/cli/run-command.js +22 -38
  4. package/dist/cli.js +95 -4
  5. package/dist/contracts/command-manifest.d.ts +17 -0
  6. package/dist/contracts/command-manifest.js +1 -0
  7. package/dist/contracts/index.d.ts +1 -1
  8. package/dist/contracts/module-contract.d.ts +12 -11
  9. package/dist/core/agent-instruction-surface.d.ts +33 -0
  10. package/dist/core/agent-instruction-surface.js +46 -0
  11. package/dist/core/config-cli.js +13 -17
  12. package/dist/core/config-metadata.js +101 -2
  13. package/dist/core/index.d.ts +4 -1
  14. package/dist/core/index.js +3 -0
  15. package/dist/core/module-command-router.js +19 -1
  16. package/dist/core/module-registry-resolve.d.ts +27 -0
  17. package/dist/core/module-registry-resolve.js +91 -0
  18. package/dist/core/module-registry.d.ts +14 -0
  19. package/dist/core/module-registry.js +57 -0
  20. package/dist/core/planning/build-plan-session-file.d.ts +29 -0
  21. package/dist/core/planning/build-plan-session-file.js +58 -0
  22. package/dist/core/planning/index.d.ts +17 -0
  23. package/dist/core/planning/index.js +15 -0
  24. package/dist/core/policy.js +18 -8
  25. package/dist/core/state/unified-state-db.d.ts +21 -0
  26. package/dist/core/state/unified-state-db.js +80 -0
  27. package/dist/core/workspace-kit-config.js +13 -1
  28. package/dist/modules/agent-behavior/builtins.d.ts +3 -0
  29. package/dist/modules/agent-behavior/builtins.js +71 -0
  30. package/dist/modules/agent-behavior/explain.d.ts +6 -0
  31. package/dist/modules/agent-behavior/explain.js +46 -0
  32. package/dist/modules/agent-behavior/index.d.ts +4 -0
  33. package/dist/modules/agent-behavior/index.js +461 -0
  34. package/dist/modules/agent-behavior/interview-session-file.d.ts +9 -0
  35. package/dist/modules/agent-behavior/interview-session-file.js +43 -0
  36. package/dist/modules/agent-behavior/interview.d.ts +13 -0
  37. package/dist/modules/agent-behavior/interview.js +88 -0
  38. package/dist/modules/agent-behavior/persistence.d.ts +6 -0
  39. package/dist/modules/agent-behavior/persistence.js +89 -0
  40. package/dist/modules/agent-behavior/store.d.ts +34 -0
  41. package/dist/modules/agent-behavior/store.js +119 -0
  42. package/dist/modules/agent-behavior/types.d.ts +28 -0
  43. package/dist/modules/agent-behavior/types.js +1 -0
  44. package/dist/modules/agent-behavior/validate.d.ts +11 -0
  45. package/dist/modules/agent-behavior/validate.js +123 -0
  46. package/dist/modules/approvals/index.js +54 -51
  47. package/dist/modules/approvals/policy-sensitive-commands.d.ts +4 -0
  48. package/dist/modules/approvals/policy-sensitive-commands.js +4 -0
  49. package/dist/modules/approvals/review-runtime.js +1 -2
  50. package/dist/modules/documentation/index.js +47 -45
  51. package/dist/modules/documentation/normalizer.d.ts +3 -0
  52. package/dist/modules/documentation/normalizer.js +171 -0
  53. package/dist/modules/documentation/parser.d.ts +7 -0
  54. package/dist/modules/documentation/parser.js +39 -0
  55. package/dist/modules/documentation/policy-sensitive-commands.d.ts +5 -0
  56. package/dist/modules/documentation/policy-sensitive-commands.js +8 -0
  57. package/dist/modules/documentation/renderer.d.ts +23 -0
  58. package/dist/modules/documentation/renderer.js +105 -0
  59. package/dist/modules/documentation/runtime-batch.d.ts +10 -0
  60. package/dist/modules/documentation/runtime-batch.js +67 -0
  61. package/dist/modules/documentation/runtime-config.d.ts +11 -0
  62. package/dist/modules/documentation/runtime-config.js +54 -0
  63. package/dist/modules/documentation/runtime-render-support.d.ts +8 -0
  64. package/dist/modules/documentation/runtime-render-support.js +36 -0
  65. package/dist/modules/documentation/runtime.js +22 -510
  66. package/dist/modules/documentation/types.d.ts +182 -0
  67. package/dist/modules/documentation/validator.d.ts +8 -0
  68. package/dist/modules/documentation/validator.js +234 -0
  69. package/dist/modules/documentation/view-models.d.ts +3 -0
  70. package/dist/modules/documentation/view-models.js +124 -0
  71. package/dist/modules/improvement/generate-recommendations-runtime.js +3 -3
  72. package/dist/modules/improvement/improvement-state.d.ts +2 -2
  73. package/dist/modules/improvement/improvement-state.js +52 -23
  74. package/dist/modules/improvement/index.js +140 -138
  75. package/dist/modules/improvement/ingest.d.ts +1 -1
  76. package/dist/modules/improvement/policy-sensitive-commands.d.ts +4 -0
  77. package/dist/modules/improvement/policy-sensitive-commands.js +7 -0
  78. package/dist/modules/index.d.ts +6 -0
  79. package/dist/modules/index.js +17 -0
  80. package/dist/modules/planning/artifact.d.ts +19 -0
  81. package/dist/modules/planning/artifact.js +72 -0
  82. package/dist/modules/planning/index.js +605 -6
  83. package/dist/modules/planning/question-engine.d.ts +25 -0
  84. package/dist/modules/planning/question-engine.js +284 -0
  85. package/dist/modules/planning/types.d.ts +9 -0
  86. package/dist/modules/planning/types.js +39 -0
  87. package/dist/modules/task-engine/doctor-planning-persistence.js +21 -13
  88. package/dist/modules/task-engine/index.d.ts +1 -2
  89. package/dist/modules/task-engine/index.js +1 -1143
  90. package/dist/modules/task-engine/migrate-task-persistence-runtime.js +31 -4
  91. package/dist/modules/task-engine/migrate-wishlist-intake-runtime.d.ts +2 -0
  92. package/dist/modules/task-engine/migrate-wishlist-intake-runtime.js +146 -0
  93. package/dist/modules/task-engine/planning-open.d.ts +2 -9
  94. package/dist/modules/task-engine/planning-open.js +4 -15
  95. package/dist/modules/task-engine/policy-sensitive-commands.d.ts +5 -0
  96. package/dist/modules/task-engine/policy-sensitive-commands.js +5 -0
  97. package/dist/modules/task-engine/sqlite-dual-planning.d.ts +11 -2
  98. package/dist/modules/task-engine/sqlite-dual-planning.js +134 -28
  99. package/dist/modules/task-engine/strict-task-validation.js +3 -0
  100. package/dist/modules/task-engine/suggestions.js +2 -1
  101. package/dist/modules/task-engine/task-engine-internal.d.ts +2 -0
  102. package/dist/modules/task-engine/task-engine-internal.js +1304 -0
  103. package/dist/modules/task-engine/task-type-validation.js +40 -0
  104. package/dist/modules/task-engine/wishlist-intake.d.ts +22 -0
  105. package/dist/modules/task-engine/wishlist-intake.js +180 -0
  106. package/dist/modules/task-engine/wishlist-validation.d.ts +4 -0
  107. package/dist/modules/task-engine/wishlist-validation.js +19 -0
  108. package/dist/modules/workspace-config/index.js +9 -11
  109. package/package.json +2 -2
  110. package/schemas/agent-behavior-profile.schema.json +52 -0
  111. package/schemas/task-engine-run-contracts.schema.json +80 -5
  112. package/src/modules/documentation/README.md +16 -25
  113. package/src/modules/documentation/RULES.md +9 -9
  114. package/src/modules/documentation/index.ts +54 -49
  115. package/src/modules/documentation/instructions/document-project.md +6 -6
  116. package/src/modules/documentation/instructions/generate-document.md +4 -4
  117. package/src/modules/documentation/normalizer.ts +187 -0
  118. package/src/modules/documentation/parser.ts +41 -0
  119. package/src/modules/documentation/policy-sensitive-commands.ts +8 -0
  120. package/src/modules/documentation/renderer.ts +121 -0
  121. package/src/modules/documentation/runtime-batch.ts +74 -0
  122. package/src/modules/documentation/runtime-config.ts +68 -0
  123. package/src/modules/documentation/runtime-render-support.ts +39 -0
  124. package/src/modules/documentation/runtime.ts +28 -600
  125. package/src/modules/documentation/schemas/documentation-schema.md +37 -54
  126. package/src/modules/documentation/types.ts +228 -0
  127. package/src/modules/documentation/validator.ts +247 -0
  128. package/src/modules/documentation/view-models.ts +132 -0
  129. package/src/modules/documentation/views/agents.view.yaml +18 -0
  130. package/src/modules/documentation/views/architecture.view.yaml +18 -0
  131. package/src/modules/documentation/views/principles.view.yaml +18 -0
  132. package/src/modules/documentation/views/readme.view.yaml +18 -0
  133. package/src/modules/documentation/views/releasing.view.yaml +18 -0
  134. package/src/modules/documentation/views/roadmap.view.yaml +18 -0
  135. package/src/modules/documentation/views/runbooks-consumer-cadence.view.yaml +18 -0
  136. package/src/modules/documentation/views/runbooks-parity-validation-flow.view.yaml +18 -0
  137. package/src/modules/documentation/views/runbooks-release-channels.view.yaml +18 -0
  138. package/src/modules/documentation/views/security.view.yaml +18 -0
  139. package/src/modules/documentation/views/support.view.yaml +18 -0
  140. package/src/modules/documentation/views/terms.view.yaml +18 -0
  141. package/src/modules/documentation/views/workbooks-phase2-config-policy-workbook.view.yaml +18 -0
  142. package/src/modules/documentation/views/workbooks-task-engine-workbook.view.yaml +18 -0
  143. package/src/modules/documentation/views/workbooks-transcript-automation-baseline.view.yaml +18 -0
  144. 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
- if (command.name === "explain-config") {
89
- return handleExplainConfig(command.args ?? {}, baseCtx);
90
- }
91
- if (command.name === "resolve-config") {
92
- return handleResolveConfig(command.args ?? {}, baseCtx);
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.17.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.17.0",
9
+ "packageVersion": "0.24.0",
10
10
  "properties": {
11
11
  "schemaVersion": {
12
12
  "const": 1
13
13
  },
14
14
  "packageVersion": {
15
- "const": "0.17.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
- "dashboard-summary"
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
- "dashboard-summary": { "$ref": "#/$defs/contractDashboardSummary" }
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": ["wishlistId", "decomposition"],
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 **all** project docs from the template library. Outputs AI docs to `.ai/` (preserving existing) and human docs to `docs/maintainers/` (overwriting). Continues through failures; reports batch summary. See `instructions/document-project.md`.
18
- - `generate-document` — single: generate **one** document by `documentType`. See `instructions/generate-document.md`.
19
-
20
- ## Shipped templates
21
-
22
- Files under `templates/`; `documentType` is the filename (basename). Keep this list aligned with `instructions/document-project.md` **Inputs**:
23
-
24
- - `AGENTS.md`
25
- - `ARCHITECTURE.md`
26
- - `PRINCIPLES.md`
27
- - `README.md`
28
- - `RELEASING.md`
29
- - `ROADMAP.md`
30
- - `SECURITY.md`
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/templates/*.md` (document-type generation templates)
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
- - If a matching template exists, use it as the structure contract.
24
- - For templates with `{{{ ... }}}` blocks, treat block content as generation instructions, not output text.
25
- - Generate AI-surface content first, then generate human-surface content from that result plus project context.
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 `.md` template in `sources.templatesRoot`.
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 `<templatesRoot>/<documentType>`.
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 template basenames are listed in `instructions/generate-document.md` and `instructions/document-project.md`.
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 project context.
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 templated documents and ensure no unresolved `{{{` blocks remain.
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