@workflow-cannon/workspace-kit 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/dist/cli/run-command.d.ts +11 -0
- package/dist/cli/run-command.js +138 -0
- package/dist/cli.js +18 -135
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/module-contract.d.ts +13 -0
- package/dist/core/config-cli.js +4 -4
- package/dist/core/config-metadata.js +199 -5
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.js +6 -0
- package/dist/core/instruction-template-mapper.d.ts +9 -0
- package/dist/core/instruction-template-mapper.js +35 -0
- package/dist/core/lineage-contract.d.ts +1 -1
- package/dist/core/lineage-contract.js +1 -1
- package/dist/core/policy.d.ts +13 -2
- package/dist/core/policy.js +42 -25
- package/dist/core/response-template-contract.d.ts +15 -0
- package/dist/core/response-template-contract.js +10 -0
- package/dist/core/response-template-registry.d.ts +4 -0
- package/dist/core/response-template-registry.js +44 -0
- package/dist/core/response-template-shaping.d.ts +6 -0
- package/dist/core/response-template-shaping.js +128 -0
- package/dist/core/session-policy.d.ts +18 -0
- package/dist/core/session-policy.js +57 -0
- package/dist/core/transcript-completion-hook.d.ts +7 -0
- package/dist/core/transcript-completion-hook.js +128 -0
- package/dist/core/workspace-kit-config.d.ts +2 -1
- package/dist/core/workspace-kit-config.js +19 -23
- package/dist/modules/approvals/index.js +2 -2
- package/dist/modules/documentation/runtime.js +413 -20
- package/dist/modules/improvement/generate-recommendations-runtime.d.ts +7 -0
- package/dist/modules/improvement/generate-recommendations-runtime.js +37 -4
- package/dist/modules/improvement/improvement-state.d.ts +10 -1
- package/dist/modules/improvement/improvement-state.js +36 -7
- package/dist/modules/improvement/index.js +70 -23
- package/dist/modules/improvement/ingest.js +2 -1
- package/dist/modules/improvement/transcript-redaction.d.ts +4 -0
- package/dist/modules/improvement/transcript-redaction.js +10 -0
- package/dist/modules/improvement/transcript-sync-runtime.d.ts +42 -1
- package/dist/modules/improvement/transcript-sync-runtime.js +215 -9
- package/dist/modules/index.d.ts +1 -1
- package/dist/modules/index.js +1 -1
- package/dist/modules/task-engine/index.d.ts +0 -2
- package/dist/modules/task-engine/index.js +4 -78
- package/package.json +6 -2
- package/src/modules/documentation/README.md +39 -0
- package/src/modules/documentation/RULES.md +70 -0
- package/src/modules/documentation/config.md +14 -0
- package/src/modules/documentation/index.ts +120 -0
- package/src/modules/documentation/instructions/document-project.md +44 -0
- package/src/modules/documentation/instructions/documentation-maintainer.md +81 -0
- package/src/modules/documentation/instructions/generate-document.md +44 -0
- package/src/modules/documentation/runtime.ts +870 -0
- package/src/modules/documentation/schemas/documentation-schema.md +54 -0
- package/src/modules/documentation/state.md +8 -0
- package/src/modules/documentation/templates/AGENTS.md +84 -0
- package/src/modules/documentation/templates/ARCHITECTURE.md +71 -0
- package/src/modules/documentation/templates/PRINCIPLES.md +122 -0
- package/src/modules/documentation/templates/RELEASING.md +96 -0
- package/src/modules/documentation/templates/ROADMAP.md +131 -0
- package/src/modules/documentation/templates/SECURITY.md +53 -0
- package/src/modules/documentation/templates/SUPPORT.md +40 -0
- package/src/modules/documentation/templates/TERMS.md +61 -0
- package/src/modules/documentation/templates/runbooks/consumer-cadence.md +55 -0
- package/src/modules/documentation/templates/runbooks/parity-validation-flow.md +68 -0
- package/src/modules/documentation/templates/runbooks/release-channels.md +30 -0
- package/src/modules/documentation/templates/workbooks/phase2-config-policy-workbook.md +42 -0
- package/src/modules/documentation/templates/workbooks/task-engine-workbook.md +42 -0
- package/src/modules/documentation/templates/workbooks/transcript-automation-baseline.md +68 -0
- package/src/modules/documentation/types.ts +51 -0
- package/dist/modules/task-engine/generator.d.ts +0 -3
- package/dist/modules/task-engine/generator.js +0 -118
- package/dist/modules/task-engine/importer.d.ts +0 -8
- package/dist/modules/task-engine/importer.js +0 -163
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import fs from "node:fs/promises";
|
|
1
|
+
import { maybeSpawnTranscriptHookAfterCompletion } from "../../core/transcript-completion-hook.js";
|
|
3
2
|
import { TaskStore } from "./store.js";
|
|
4
3
|
import { TransitionService } from "./service.js";
|
|
5
4
|
import { TaskEngineError } from "./transitions.js";
|
|
6
|
-
import { generateTasksMd, syncTaskHeadingsInMarkdown } from "./generator.js";
|
|
7
|
-
import { importTasksFromMarkdown } from "./importer.js";
|
|
8
5
|
import { getNextActions } from "./suggestions.js";
|
|
9
6
|
export { TaskStore } from "./store.js";
|
|
10
7
|
export { TransitionService } from "./service.js";
|
|
11
8
|
export { TaskEngineError, TransitionValidator, isTransitionAllowed, getTransitionAction, resolveTargetState, getAllowedTransitionsFrom, stateValidityGuard, dependencyCheckGuard } from "./transitions.js";
|
|
12
|
-
export { generateTasksMd, syncTaskHeadingsInMarkdown } from "./generator.js";
|
|
13
|
-
export { importTasksFromMarkdown } from "./importer.js";
|
|
14
9
|
export { getNextActions } from "./suggestions.js";
|
|
15
10
|
function taskStorePath(ctx) {
|
|
16
11
|
const tasks = ctx.effectiveConfig?.tasks;
|
|
@@ -61,16 +56,6 @@ export const taskEngineModule = {
|
|
|
61
56
|
file: "get-ready-queue.md",
|
|
62
57
|
description: "Get ready tasks sorted by priority."
|
|
63
58
|
},
|
|
64
|
-
{
|
|
65
|
-
name: "import-tasks",
|
|
66
|
-
file: "import-tasks.md",
|
|
67
|
-
description: "One-time import from TASKS.md into engine state."
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
name: "generate-tasks-md",
|
|
71
|
-
file: "generate-tasks-md.md",
|
|
72
|
-
description: "Generate read-only TASKS.md from engine state."
|
|
73
|
-
},
|
|
74
59
|
{
|
|
75
60
|
name: "get-next-actions",
|
|
76
61
|
file: "get-next-actions.md",
|
|
@@ -113,6 +98,9 @@ export const taskEngineModule = {
|
|
|
113
98
|
try {
|
|
114
99
|
const service = new TransitionService(store);
|
|
115
100
|
const result = await service.runTransition({ taskId, action, actor });
|
|
101
|
+
if (result.evidence.toState === "completed") {
|
|
102
|
+
maybeSpawnTranscriptHookAfterCompletion(ctx.workspacePath, (ctx.effectiveConfig ?? {}));
|
|
103
|
+
}
|
|
116
104
|
return {
|
|
117
105
|
ok: true,
|
|
118
106
|
code: "transition-applied",
|
|
@@ -190,68 +178,6 @@ export const taskEngineModule = {
|
|
|
190
178
|
data: { tasks: ready, count: ready.length }
|
|
191
179
|
};
|
|
192
180
|
}
|
|
193
|
-
if (command.name === "import-tasks") {
|
|
194
|
-
const sourcePath = typeof args.sourcePath === "string"
|
|
195
|
-
? path.resolve(ctx.workspacePath, args.sourcePath)
|
|
196
|
-
: path.resolve(ctx.workspacePath, "docs/maintainers/TASKS.md");
|
|
197
|
-
try {
|
|
198
|
-
const result = await importTasksFromMarkdown(sourcePath);
|
|
199
|
-
store.replaceAllTasks(result.tasks);
|
|
200
|
-
await store.save();
|
|
201
|
-
return {
|
|
202
|
-
ok: true,
|
|
203
|
-
code: "tasks-imported",
|
|
204
|
-
message: `Imported ${result.imported} tasks (${result.skipped} skipped)`,
|
|
205
|
-
data: {
|
|
206
|
-
imported: result.imported,
|
|
207
|
-
skipped: result.skipped,
|
|
208
|
-
errors: result.errors
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
catch (err) {
|
|
213
|
-
if (err instanceof TaskEngineError) {
|
|
214
|
-
return { ok: false, code: err.code, message: err.message };
|
|
215
|
-
}
|
|
216
|
-
return {
|
|
217
|
-
ok: false,
|
|
218
|
-
code: "import-parse-error",
|
|
219
|
-
message: err.message
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
if (command.name === "generate-tasks-md") {
|
|
224
|
-
const outputPath = typeof args.outputPath === "string"
|
|
225
|
-
? path.resolve(ctx.workspacePath, args.outputPath)
|
|
226
|
-
: path.resolve(ctx.workspacePath, "docs/maintainers/TASKS.md");
|
|
227
|
-
const tasks = store.getAllTasks();
|
|
228
|
-
const fallbackMarkdown = generateTasksMd(tasks);
|
|
229
|
-
let markdown = fallbackMarkdown;
|
|
230
|
-
const preserveStructure = args.preserveStructure !== false;
|
|
231
|
-
try {
|
|
232
|
-
if (preserveStructure) {
|
|
233
|
-
const existing = await fs.readFile(outputPath, "utf8").catch(() => undefined);
|
|
234
|
-
if (typeof existing === "string" && existing.length > 0) {
|
|
235
|
-
markdown = syncTaskHeadingsInMarkdown(existing, tasks);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
await fs.mkdir(path.dirname(outputPath), { recursive: true });
|
|
239
|
-
await fs.writeFile(outputPath, markdown, "utf8");
|
|
240
|
-
}
|
|
241
|
-
catch (err) {
|
|
242
|
-
return {
|
|
243
|
-
ok: false,
|
|
244
|
-
code: "storage-write-error",
|
|
245
|
-
message: `Failed to write TASKS.md: ${err.message}`
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
return {
|
|
249
|
-
ok: true,
|
|
250
|
-
code: "tasks-md-generated",
|
|
251
|
-
message: `Generated TASKS.md with ${tasks.length} tasks`,
|
|
252
|
-
data: { outputPath, taskCount: tasks.length }
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
181
|
if (command.name === "get-next-actions") {
|
|
256
182
|
const tasks = store.getAllTasks();
|
|
257
183
|
const suggestion = getNextActions(tasks);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workflow-cannon/workspace-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"packageManager": "pnpm@10.0.0",
|
|
6
6
|
"license": "MIT",
|
|
@@ -31,7 +31,10 @@
|
|
|
31
31
|
"generate-runtime-diagnostics": "node scripts/generate-runtime-diagnostics.mjs",
|
|
32
32
|
"prune-evidence": "node scripts/prune-evidence.mjs",
|
|
33
33
|
"phase4-gates": "pnpm run check-compatibility && pnpm run check-planning-consistency && pnpm run check-release-channel",
|
|
34
|
-
"phase5-gates": "pnpm run phase4-gates && pnpm run test"
|
|
34
|
+
"phase5-gates": "pnpm run phase4-gates && pnpm run test",
|
|
35
|
+
"pre-release-transcript-hook": "pnpm run build && node scripts/pre-release-transcript-hook.mjs",
|
|
36
|
+
"transcript:sync": "node scripts/run-transcript-cli.mjs sync-transcripts",
|
|
37
|
+
"transcript:ingest": "node scripts/run-transcript-cli.mjs ingest-transcripts"
|
|
35
38
|
},
|
|
36
39
|
"devDependencies": {
|
|
37
40
|
"@types/node": "^25.5.0",
|
|
@@ -39,6 +42,7 @@
|
|
|
39
42
|
},
|
|
40
43
|
"files": [
|
|
41
44
|
"dist",
|
|
45
|
+
"src/modules/documentation",
|
|
42
46
|
"package.json"
|
|
43
47
|
]
|
|
44
48
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Documentation Module
|
|
2
|
+
|
|
3
|
+
Translates between canonical AI-optimized documentation and human-readable maintainership docs.
|
|
4
|
+
|
|
5
|
+
Primary responsibilities:
|
|
6
|
+
|
|
7
|
+
- maintain parity between `/.ai` and configured human docs roots (default: `docs/maintainers`)
|
|
8
|
+
- execute instruction-file driven documentation generation
|
|
9
|
+
- record deterministic documentation generation state and evidence
|
|
10
|
+
|
|
11
|
+
See `src/modules/documentation/RULES.md` for the canonical usage order and validation rules.
|
|
12
|
+
|
|
13
|
+
## Callable commands
|
|
14
|
+
|
|
15
|
+
Registered on the documentation module and dispatched through `src/core/module-command-router.ts`:
|
|
16
|
+
|
|
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
|
+
- `RELEASING.md`
|
|
28
|
+
- `ROADMAP.md`
|
|
29
|
+
- `SECURITY.md`
|
|
30
|
+
- `SUPPORT.md`
|
|
31
|
+
- `TERMS.md`
|
|
32
|
+
- `runbooks/parity-validation-flow.md`
|
|
33
|
+
- `runbooks/consumer-cadence.md`
|
|
34
|
+
- `runbooks/release-channels.md`
|
|
35
|
+
- `workbooks/transcript-automation-baseline.md`
|
|
36
|
+
- `workbooks/phase2-config-policy-workbook.md`
|
|
37
|
+
- `workbooks/task-engine-workbook.md`
|
|
38
|
+
|
|
39
|
+
Adding a new template: add `templates/<Name>.md`, extend the **Inputs** list in `instructions/document-project.md`, and add the same line here.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Documentation Module Rules
|
|
2
|
+
|
|
3
|
+
Single entrypoint for how to use the documentation module.
|
|
4
|
+
|
|
5
|
+
## Precedence Order
|
|
6
|
+
|
|
7
|
+
When guidance conflicts, apply this order:
|
|
8
|
+
|
|
9
|
+
1. `/.ai/PRINCIPLES.md` (global governance and approval gates)
|
|
10
|
+
2. `/.ai/module-build.md` (module development and validation rules)
|
|
11
|
+
3. `src/modules/documentation/config.md` (module path policy and generation behavior)
|
|
12
|
+
4. `src/modules/documentation/instructions/document-project.md` (document generation workflow)
|
|
13
|
+
5. `src/modules/documentation/instructions/documentation-maintainer.md` (AI-doc generation policy)
|
|
14
|
+
6. `src/modules/documentation/schemas/documentation-schema.md` (record schema contract)
|
|
15
|
+
7. `src/modules/documentation/templates/*.md` (document-type generation templates)
|
|
16
|
+
8. `docs/maintainers/module-build-guide.md` (human-readable companion guidance)
|
|
17
|
+
|
|
18
|
+
## Usage Model
|
|
19
|
+
|
|
20
|
+
- Choose an instruction entry from `instructions/` for the operation you want.
|
|
21
|
+
- Discover available callable module operations through `src/core/module-command-router.ts` command listing.
|
|
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.
|
|
26
|
+
|
|
27
|
+
## Command Contracts
|
|
28
|
+
|
|
29
|
+
### `document-project(options)` — batch
|
|
30
|
+
|
|
31
|
+
Generates all project docs by iterating every `.md` template in `sources.templatesRoot`.
|
|
32
|
+
|
|
33
|
+
- Default behavior: **preserve AI docs** (`overwriteAi: false`), **overwrite human docs** (`overwriteHuman: true`), continue on individual failure.
|
|
34
|
+
- Returns batch summary with total/succeeded/failed/skipped counts plus per-document results.
|
|
35
|
+
|
|
36
|
+
### `generate-document(documentType, options)` — single
|
|
37
|
+
|
|
38
|
+
Generates one document pair (AI + human) for the given `documentType`.
|
|
39
|
+
|
|
40
|
+
- `documentType`: required string basename resolving to `<templatesRoot>/<documentType>`.
|
|
41
|
+
- `options`:
|
|
42
|
+
- `dryRun?: boolean` (default `false`) - compute outputs/validations without writing files
|
|
43
|
+
- `overwrite?: boolean` (default `true`) - allow replacing existing files (both surfaces)
|
|
44
|
+
- `overwriteAi?: boolean` - override `overwrite` for AI surface only
|
|
45
|
+
- `overwriteHuman?: boolean` - override `overwrite` for human surface only
|
|
46
|
+
- `strict?: boolean` (default `true`) - fail on unresolved warnings (validation/conflict/coverage)
|
|
47
|
+
- `maxValidationAttempts?: number` (default from config) - override retry limit
|
|
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`.
|
|
50
|
+
|
|
51
|
+
### Shared semantics
|
|
52
|
+
|
|
53
|
+
- Both commands read paths from module config (`sources.aiRoot`, `sources.humanRoot`, `sources.templatesRoot`, `sources.instructionsRoot`, `sources.schemasRoot`).
|
|
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.
|
|
56
|
+
- Both return evidence objects containing files read/written, validations, retries, warnings/conflicts, and timestamp.
|
|
57
|
+
|
|
58
|
+
## Required Validation
|
|
59
|
+
|
|
60
|
+
- Validate AI output against `schemas/documentation-schema.md`.
|
|
61
|
+
- Verify section coverage for templated documents and ensure no unresolved `{{{` blocks remain.
|
|
62
|
+
- Detect conflicts against higher-precedence sources and stop/prompt when required.
|
|
63
|
+
- Emit run evidence (inputs, outputs, validation results, timestamp).
|
|
64
|
+
|
|
65
|
+
## Missing Template Behavior
|
|
66
|
+
|
|
67
|
+
- If a template for the requested document type is missing:
|
|
68
|
+
- warn the user
|
|
69
|
+
- ask whether to continue without a template
|
|
70
|
+
- continue only with explicit confirmation
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Documentation Module Config
|
|
2
|
+
|
|
3
|
+
Defines module-level configuration keys used by the documentation module.
|
|
4
|
+
|
|
5
|
+
- `sources.aiRoot`: canonical AI docs root (default: `/.ai`)
|
|
6
|
+
- `sources.humanRoot`: human docs root (default: `docs/maintainers`)
|
|
7
|
+
- `sources.templatesRoot`: document template root (default: `src/modules/documentation/templates`)
|
|
8
|
+
- `sources.instructionsRoot`: instruction root (default: `src/modules/documentation/instructions`)
|
|
9
|
+
- `sources.schemasRoot`: schema root (default: `src/modules/documentation/schemas`)
|
|
10
|
+
- `generation.enforceParity`: fail generation when AI and human surfaces diverge
|
|
11
|
+
- `generation.enforceSectionCoverage`: fail when expected template sections are missing in output
|
|
12
|
+
- `generation.resolveOrRetryOnValidationError`: auto-resolve issues or retry generation before returning failure
|
|
13
|
+
- `generation.maxValidationAttempts`: maximum validate/retry attempts (default: `3`)
|
|
14
|
+
- `generation.allowTemplatelessFallback`: when template is missing, require user confirmation before continuing
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { WorkflowModule } from "../../contracts/module-contract.js";
|
|
2
|
+
import { generateDocument, generateAllDocuments } from "./runtime.js";
|
|
3
|
+
export type {
|
|
4
|
+
DocumentationBatchResult,
|
|
5
|
+
DocumentationConflict,
|
|
6
|
+
DocumentationGenerateOptions,
|
|
7
|
+
DocumentationGenerateResult,
|
|
8
|
+
DocumentationGenerationEvidence,
|
|
9
|
+
DocumentationValidationIssue
|
|
10
|
+
} from "./types.js";
|
|
11
|
+
import type { DocumentationGenerateOptions } from "./types.js";
|
|
12
|
+
|
|
13
|
+
function parseOptions(raw: Record<string, unknown>): DocumentationGenerateOptions {
|
|
14
|
+
return {
|
|
15
|
+
dryRun: typeof raw.dryRun === "boolean" ? raw.dryRun : undefined,
|
|
16
|
+
overwrite: typeof raw.overwrite === "boolean" ? raw.overwrite : undefined,
|
|
17
|
+
overwriteAi: typeof raw.overwriteAi === "boolean" ? raw.overwriteAi : undefined,
|
|
18
|
+
overwriteHuman: typeof raw.overwriteHuman === "boolean" ? raw.overwriteHuman : undefined,
|
|
19
|
+
strict: typeof raw.strict === "boolean" ? raw.strict : undefined,
|
|
20
|
+
maxValidationAttempts:
|
|
21
|
+
typeof raw.maxValidationAttempts === "number" ? raw.maxValidationAttempts : undefined,
|
|
22
|
+
allowWithoutTemplate:
|
|
23
|
+
typeof raw.allowWithoutTemplate === "boolean" ? raw.allowWithoutTemplate : undefined,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const documentationModule: WorkflowModule = {
|
|
28
|
+
registration: {
|
|
29
|
+
id: "documentation",
|
|
30
|
+
version: "0.2.0",
|
|
31
|
+
contractVersion: "1",
|
|
32
|
+
capabilities: ["documentation"],
|
|
33
|
+
dependsOn: [],
|
|
34
|
+
enabledByDefault: true,
|
|
35
|
+
config: {
|
|
36
|
+
path: "src/modules/documentation/config.md",
|
|
37
|
+
format: "md",
|
|
38
|
+
description: "Documentation module configuration contract."
|
|
39
|
+
},
|
|
40
|
+
state: {
|
|
41
|
+
path: "src/modules/documentation/state.md",
|
|
42
|
+
format: "md",
|
|
43
|
+
description: "Documentation module generation/runtime state contract."
|
|
44
|
+
},
|
|
45
|
+
instructions: {
|
|
46
|
+
directory: "src/modules/documentation/instructions",
|
|
47
|
+
entries: [
|
|
48
|
+
{
|
|
49
|
+
name: "document-project",
|
|
50
|
+
file: "document-project.md",
|
|
51
|
+
description: "Generate all project docs from templates to .ai and docs/maintainers surfaces."
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "generate-document",
|
|
55
|
+
file: "generate-document.md",
|
|
56
|
+
description: "Generate a single document by type for .ai and docs/maintainers surfaces."
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
async onCommand(command, ctx) {
|
|
62
|
+
const args = command.args ?? {};
|
|
63
|
+
const rawOptions: Record<string, unknown> =
|
|
64
|
+
typeof args.options === "object" && args.options !== null
|
|
65
|
+
? (args.options as Record<string, unknown>)
|
|
66
|
+
: {};
|
|
67
|
+
const options = parseOptions(rawOptions);
|
|
68
|
+
|
|
69
|
+
if (command.name === "document-project") {
|
|
70
|
+
const batchResult = await generateAllDocuments({ options }, ctx);
|
|
71
|
+
return {
|
|
72
|
+
ok: batchResult.ok,
|
|
73
|
+
code: batchResult.ok ? "documented-project" : "documentation-batch-failed",
|
|
74
|
+
message: batchResult.ok
|
|
75
|
+
? `Generated ${batchResult.summary.succeeded} documents (${batchResult.summary.skipped} skipped)`
|
|
76
|
+
: `Batch failed: ${batchResult.summary.failed} of ${batchResult.summary.total} documents failed`,
|
|
77
|
+
data: {
|
|
78
|
+
summary: batchResult.summary,
|
|
79
|
+
results: batchResult.results.map((r) => ({
|
|
80
|
+
documentType: r.evidence.documentType,
|
|
81
|
+
ok: r.ok,
|
|
82
|
+
aiOutputPath: r.aiOutputPath,
|
|
83
|
+
humanOutputPath: r.humanOutputPath,
|
|
84
|
+
filesWritten: r.evidence.filesWritten,
|
|
85
|
+
filesSkipped: r.evidence.filesSkipped,
|
|
86
|
+
}))
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (command.name === "generate-document") {
|
|
92
|
+
const result = await generateDocument(
|
|
93
|
+
{
|
|
94
|
+
documentType: typeof args.documentType === "string" ? args.documentType : undefined,
|
|
95
|
+
options
|
|
96
|
+
},
|
|
97
|
+
ctx
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
ok: result.ok,
|
|
102
|
+
code: result.ok ? "generated-document" : "generation-failed",
|
|
103
|
+
message: result.ok
|
|
104
|
+
? `Generated document '${args.documentType ?? "unknown"}'`
|
|
105
|
+
: `Failed to generate document '${args.documentType ?? "unknown"}'`,
|
|
106
|
+
data: {
|
|
107
|
+
aiOutputPath: result.aiOutputPath,
|
|
108
|
+
humanOutputPath: result.humanOutputPath,
|
|
109
|
+
evidence: result.evidence
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
ok: false,
|
|
116
|
+
code: "unsupported-command",
|
|
117
|
+
message: `Documentation module does not support command '${command.name}'`
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# document-project
|
|
2
|
+
|
|
3
|
+
Generate all project documentation by running `generate-document` for every template in the template library. Outputs AI-optimized docs to `.ai/` and human-readable docs to `docs/maintainers/`.
|
|
4
|
+
|
|
5
|
+
## Inputs
|
|
6
|
+
|
|
7
|
+
- `options` (all optional):
|
|
8
|
+
- `dryRun?: boolean` — compute outputs/validations without writing files
|
|
9
|
+
- `overwriteAi?: boolean` — overwrite existing AI docs (default `false`)
|
|
10
|
+
- `overwriteHuman?: boolean` — overwrite existing human docs (default `true`)
|
|
11
|
+
- `strict?: boolean` — fail on unresolved warnings (default `false` in batch mode)
|
|
12
|
+
- `maxValidationAttempts?: number` — override retry limit per document
|
|
13
|
+
|
|
14
|
+
## Shipped templates
|
|
15
|
+
|
|
16
|
+
All `.md` files under `sources.templatesRoot` (default `src/modules/documentation/templates`) are processed:
|
|
17
|
+
|
|
18
|
+
- `AGENTS.md`
|
|
19
|
+
- `ARCHITECTURE.md`
|
|
20
|
+
- `PRINCIPLES.md`
|
|
21
|
+
- `RELEASING.md`
|
|
22
|
+
- `ROADMAP.md`
|
|
23
|
+
- `SECURITY.md`
|
|
24
|
+
- `SUPPORT.md`
|
|
25
|
+
- `TERMS.md`
|
|
26
|
+
- `runbooks/parity-validation-flow.md`
|
|
27
|
+
- `runbooks/consumer-cadence.md`
|
|
28
|
+
- `runbooks/release-channels.md`
|
|
29
|
+
- `workbooks/transcript-automation-baseline.md`
|
|
30
|
+
- `workbooks/phase2-config-policy-workbook.md`
|
|
31
|
+
- `workbooks/task-engine-workbook.md`
|
|
32
|
+
|
|
33
|
+
## Required behavior
|
|
34
|
+
|
|
35
|
+
1. Discover all `.md` templates in `sources.templatesRoot`.
|
|
36
|
+
2. For each template, invoke `generate-document` with the template basename as `documentType`.
|
|
37
|
+
3. Default overwrite behavior: **preserve AI docs** (`overwriteAi: false`), **overwrite human docs** (`overwriteHuman: true`).
|
|
38
|
+
4. Continue through all templates on individual failure; do not stop the batch.
|
|
39
|
+
5. Collect per-document results and emit a batch summary with total/succeeded/failed/skipped counts.
|
|
40
|
+
6. Return `ok: true` only when zero documents failed.
|
|
41
|
+
|
|
42
|
+
## Skipped AI doc handling
|
|
43
|
+
|
|
44
|
+
When AI docs are skipped because they already exist (`filesSkipped` is non-empty in a document result), the calling agent **must** prompt the user before overwriting. Present the list of skipped AI doc paths and ask for explicit confirmation. If confirmed, re-run with `overwriteAi: true` for those documents.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
meta|v=1|doc=generator|truth=canonical|st=active
|
|
2
|
+
|
|
3
|
+
goal|produce=canonical_project_docs|opt=max_obedience_per_token|minimize=ambiguity,drift,token_waste
|
|
4
|
+
io|in=repo_files,code_config,existing_docs,core_schema|out=manifest,rules,map,workflows,commands,decisions,glossary,observed,planned,checks
|
|
5
|
+
authority|order=canonical_ai_docs>code_and_config_reality>generated_human_docs>narrative_docs
|
|
6
|
+
|
|
7
|
+
use|schema=src/modules/documentation/schemas/documentation-schema.md
|
|
8
|
+
create|files=.ai/00-manifest.md,.ai/01-rules.md,.ai/02-map.md,.ai/03-workflows.md,.ai/04-commands.md,.ai/05-decisions.md,.ai/06-glossary.md,.ai/07-observed.md,.ai/08-planned.md,.ai/09-checks.md
|
|
9
|
+
min_set|files=manifest,rules,map,workflows
|
|
10
|
+
|
|
11
|
+
author|one_record_per_line=true|meta_first_once=true|stable_order=true|omit_empty_optional=true|one_fact_per_record=true|exceptions_inline=true
|
|
12
|
+
author|explicit=level,scope,directive,trigger,done,approval,stop_prompt_behavior
|
|
13
|
+
author|forbid=vague_directives,undefined_shorthand,hidden_exceptions,softened_requirements,duplicate_meaning,manual_reordering_without_reason
|
|
14
|
+
|
|
15
|
+
classify|rule=intended_policy_for_future_action
|
|
16
|
+
classify|observed=current_reality_or_drift_not_policy
|
|
17
|
+
classify|planned=target_state_not_yet_true
|
|
18
|
+
classify|decision=compact_choice_plus_consequence
|
|
19
|
+
classify|check=validation_assertion
|
|
20
|
+
classify|term=project_specific_term_only
|
|
21
|
+
|
|
22
|
+
infer|allowed=project_identity,stack,repo_scope,path_roles,module_roles,commands,high_confidence_workflows,observed_facts
|
|
23
|
+
infer|forbid=unstated_policy,hidden_exceptions,preferred_style_without_evidence,intent_from_accidental_code_smells
|
|
24
|
+
infer|policy_from=explicit_docs,repeated_patterns_with_high_confidence,user_stated_preferences,active_decisions
|
|
25
|
+
infer|when_unclear=write_observed_or_draft_not_rule
|
|
26
|
+
|
|
27
|
+
rule|write=rule|RID|lvl|scope|directive|optional_fields
|
|
28
|
+
rule|good=add_migration,preserve_backward_compatibility,contain_business_logic,commit_secrets,manual_edit,add_or_update_tests
|
|
29
|
+
rule|bad=best_practices,clean_code,good_design,keep_it_simple,do_the_right_thing
|
|
30
|
+
rule|levels=must,must_not,should,may
|
|
31
|
+
rule|scope=concrete_and_stable
|
|
32
|
+
rule|exception=inline_unless
|
|
33
|
+
rule|interaction=ov=auto,warn,prompt,stop_when_needed
|
|
34
|
+
rule|new_id_if=meaning_changes
|
|
35
|
+
rule|keep_id_if=meaning_same_and_fields_refined
|
|
36
|
+
|
|
37
|
+
map|write=path_and_module_records_only
|
|
38
|
+
map|path_fields=role,has,xhas,deps,xdeps,check,st,refs
|
|
39
|
+
map|module_fields=role,owns,deps,xdeps,entry,tests,st,refs
|
|
40
|
+
map|require=ownership_boundaries_for_major_paths
|
|
41
|
+
map|forbid=generic_roles,misc_buckets
|
|
42
|
+
|
|
43
|
+
wf|write=wf|WID|name|when|do|done|optional_fields
|
|
44
|
+
wf|require=trigger_and_done_when_tasklike
|
|
45
|
+
wf|use=forbid,ask_if,halt_if,ap,risk_when_relevant
|
|
46
|
+
wf|common_first=true|risky_early=true|clarify_last=true
|
|
47
|
+
wf|stop_if=destructive_unapproved,policy_conflict_unresolved,unsafe_missing_info
|
|
48
|
+
wf|ask_if=multiple_valid_interpretations,required_choice_missing
|
|
49
|
+
|
|
50
|
+
cmd|write=canonical_commands_only
|
|
51
|
+
cmd|include=install,dev,test,lint,build_when_present
|
|
52
|
+
cmd|forbid=speculative_commands
|
|
53
|
+
|
|
54
|
+
decision|write=only_active_high_value_choices
|
|
55
|
+
decision|require=topic,choice
|
|
56
|
+
decision|prefer=why,then
|
|
57
|
+
decision|forbid=long_narrative
|
|
58
|
+
|
|
59
|
+
term|write=only_if_reduces_ambiguity
|
|
60
|
+
term|forbid=common_engineering_terms,indirection_debt
|
|
61
|
+
|
|
62
|
+
observed|write=for_drift_violations_legacy_patterns_notable_current_facts
|
|
63
|
+
planned|write=for_target_state_not_yet_implemented
|
|
64
|
+
check|write=for_required_validation_gates_and_done_assertions
|
|
65
|
+
|
|
66
|
+
order|manifest=meta,project,stack,prio,truth,ref
|
|
67
|
+
order|rules=global,risky,scoped,workflow,style
|
|
68
|
+
order|map=roots,major,special,legacy
|
|
69
|
+
order|workflows=common,risky,edge,clarify
|
|
70
|
+
|
|
71
|
+
validate|struct=allowed_record_types,required_fields,valid_enums,valid_ids,meta_first_once
|
|
72
|
+
validate|semantic=no_duplicate_active_ids,no_conflicting_active_rules_without_exception,no_vague_directives,no_observed_as_rule,no_planned_as_rule,no_unknown_paths_without_reason
|
|
73
|
+
validate|interaction=critical_secret_risk_stop,destructive_unapproved_stop_or_required,ambiguity_prompt_or_observed
|
|
74
|
+
|
|
75
|
+
stop|if=critical_secret_risk,destructive_change_without_approval,unresolved_policy_conflict,unsafe_missing_info
|
|
76
|
+
prompt|if=multiple_valid_interpretations,required_approval_missing,repo_intent_unclear_but_safe_to_ask
|
|
77
|
+
warn|if=should_violation,low_risk_uncertainty,minor_doc_drift
|
|
78
|
+
auto|if=low_risk_clear_routine_work
|
|
79
|
+
|
|
80
|
+
output|deterministic=true|preserve_existing_order_when_semantics_same=true|preserve_ids=true
|
|
81
|
+
output|never=soften_must_to_should,drop_unless,merge_distinct_rules_into_fuzzy_prose,invent_rationale
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# generate-document
|
|
2
|
+
|
|
3
|
+
Generate a single document for both canonical AI and human-readable surfaces using module config, schema, and templates.
|
|
4
|
+
|
|
5
|
+
## Inputs
|
|
6
|
+
|
|
7
|
+
- `documentType` (required): basename of the doc to generate; must match a file under `sources.templatesRoot` (default `src/modules/documentation/templates`). Known templates:
|
|
8
|
+
- `AGENTS.md`
|
|
9
|
+
- `ARCHITECTURE.md`
|
|
10
|
+
- `PRINCIPLES.md`
|
|
11
|
+
- `RELEASING.md`
|
|
12
|
+
- `ROADMAP.md`
|
|
13
|
+
- `SECURITY.md`
|
|
14
|
+
- `SUPPORT.md`
|
|
15
|
+
- `TERMS.md`
|
|
16
|
+
- `runbooks/parity-validation-flow.md`
|
|
17
|
+
- `runbooks/consumer-cadence.md`
|
|
18
|
+
- `runbooks/release-channels.md`
|
|
19
|
+
- `workbooks/transcript-automation-baseline.md`
|
|
20
|
+
- `workbooks/phase2-config-policy-workbook.md`
|
|
21
|
+
- `workbooks/task-engine-workbook.md`
|
|
22
|
+
- `options`:
|
|
23
|
+
- `dryRun?: boolean` — compute outputs/validations without writing files
|
|
24
|
+
- `overwrite?: boolean` — allow replacing existing files (default `true`)
|
|
25
|
+
- `overwriteAi?: boolean` — override `overwrite` for AI surface only
|
|
26
|
+
- `overwriteHuman?: boolean` — override `overwrite` for human surface only
|
|
27
|
+
- `strict?: boolean` — fail on unresolved warnings (default `true`)
|
|
28
|
+
- `maxValidationAttempts?: number` — override retry limit
|
|
29
|
+
- `allowWithoutTemplate?: boolean` — continue without template only when explicitly confirmed
|
|
30
|
+
|
|
31
|
+
## Required behavior
|
|
32
|
+
|
|
33
|
+
1. Read `src/modules/documentation/RULES.md` and apply precedence order before generation.
|
|
34
|
+
2. Load module config and resolve output roots from configured paths (`sources.aiRoot`, `sources.humanRoot`).
|
|
35
|
+
3. Restrict writes strictly to configured output roots; reject writes outside those roots.
|
|
36
|
+
4. Resolve template for `documentType` from `sources.templatesRoot`.
|
|
37
|
+
5. If template is missing, warn user and ask whether to continue without a template; continue only on explicit confirmation.
|
|
38
|
+
6. Generate AI output first at `<aiRoot>/<documentType>` using `documentation-maintainer.md` + `documentation-schema.md`.
|
|
39
|
+
7. Validate AI output against schema; on validation failure, auto-resolve/retry up to `generation.maxValidationAttempts` before failing.
|
|
40
|
+
8. Re-read generated AI output with project context, then generate human output at `<humanRoot>/<documentType>`.
|
|
41
|
+
9. For templates containing `{{{ ... }}}`, execute block contents as generation instructions and ensure no unresolved blocks remain in output.
|
|
42
|
+
10. Run section coverage validation (all required sections present, correct headings/order where required); retry/resolve on failure.
|
|
43
|
+
11. Detect conflicts with higher-precedence docs and stop/prompt when policy-sensitive or unresolved.
|
|
44
|
+
12. Emit run evidence: inputs, files read/written, validation results, retries used, conflict outcomes, timestamp.
|