@vibecompass/vibecompass 0.4.0 → 0.6.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/CHANGELOG.md +13 -0
- package/README.md +54 -9
- package/package.json +4 -2
- package/src/docs-review.js +102 -10
- package/src/generators/agent-files/index.js +2 -11
- package/src/generators/agent-files/template.js +33 -34
- package/src/project-memory.js +3 -1
- package/src/refresh-workflow.js +3 -0
- package/src/scaffold.js +45 -86
- package/src/setup.js +2 -11
- package/src/workflows/registry.js +138 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.6.0 - 2026-05-25
|
|
4
|
+
|
|
5
|
+
- Bump docs-review to `VibeCompass Docs Review Prompt v2`.
|
|
6
|
+
- Add a staged docs-review workflow: evidence inventory, coverage plan, bounded doc generation, and apply/verify.
|
|
7
|
+
- Add retrieval-oriented metadata expectations so generated architecture docs are useful future context without requiring broad token-heavy loads.
|
|
8
|
+
- Add soft `oversized_architecture_doc` warnings for accepted architecture docs over the 12000-byte budget.
|
|
9
|
+
- Include package-owned workflow registry files in the npm tarball.
|
|
10
|
+
|
|
11
|
+
## 0.5.0
|
|
12
|
+
|
|
13
|
+
- Previous published release.
|
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ Shipped today:
|
|
|
20
20
|
- interactive guided init for placement, workflow bootstrap, and first-session setup
|
|
21
21
|
- lightweight starter architecture/session memory plus example-only decision guidance
|
|
22
22
|
- generated `context.md` plus opt-in workflow guide files
|
|
23
|
-
- opt-in starter `CLAUDE.md` / `AGENTS.md` templates that are created
|
|
23
|
+
- opt-in starter `CLAUDE.md` / `AGENTS.md` templates that are created only when missing, with VibeCompass-managed regions for future refreshes
|
|
24
24
|
- `vibecompass start-session` / `vibecompass close-session` for lane-aware local builder workflow
|
|
25
25
|
- `vibecompass list-sessions` / `vibecompass switch-session` for multiple active session lanes
|
|
26
26
|
- `vibecompass end-session` as a discoverable alias for `close-session`
|
|
@@ -31,6 +31,8 @@ Shipped today:
|
|
|
31
31
|
- `vibecompass docs-review --submit-hosted` — submit the review request to the hosted app and poll for proposal/artifact output
|
|
32
32
|
- `vibecompass docs-review --run-local --provider anthropic` — local provider adapter that saves review output locally
|
|
33
33
|
- `vibecompass docs-review --apply-output` — apply accepted architecture-doc blocks into canonical `architecture/` docs
|
|
34
|
+
- docs-review prompt v2 with staged evidence inventory, coverage planning, bounded doc generation, retrieval metadata, and soft oversized-doc warnings
|
|
35
|
+
- strict docs-review output validation for architecture-doc fences, duplicate paths, and required frontmatter
|
|
34
36
|
- `vibecompass docs-review --complete` — mark the review accepted after the docs land
|
|
35
37
|
- hosted sync commands: `push`, `pull-preview`, `pull-export`, and `apply-export`
|
|
36
38
|
- canonical file scanning and validation
|
|
@@ -68,6 +70,15 @@ command is intentionally unscoped: `vibecompass`.
|
|
|
68
70
|
npm install @vibecompass/vibecompass
|
|
69
71
|
```
|
|
70
72
|
|
|
73
|
+
## Latest release
|
|
74
|
+
|
|
75
|
+
`0.6.0` upgrades docs-review to `VibeCompass Docs Review Prompt v2`.
|
|
76
|
+
The generated review prompt now guides the LLM through evidence inventory,
|
|
77
|
+
coverage planning, bounded architecture-doc generation, and apply/verify.
|
|
78
|
+
Accepted architecture docs over the 12000-byte soft budget are still applied,
|
|
79
|
+
but surface an `oversized_architecture_doc` warning so users can compact them
|
|
80
|
+
before future LLM sessions load that context.
|
|
81
|
+
|
|
71
82
|
## Quickstart
|
|
72
83
|
|
|
73
84
|
Most users should start with the guided bootstrap:
|
|
@@ -144,6 +155,11 @@ AGENTS.md # at the tooling root, only if missing and --with-agents is
|
|
|
144
155
|
|
|
145
156
|
`context.md` is a derived package-owned file. Re-running `init --force --with-workflow`
|
|
146
157
|
regenerates it; do not treat it as a hand-edited source document.
|
|
158
|
+
Starter `CLAUDE.md` / `AGENTS.md` files include VibeCompass managed markers
|
|
159
|
+
when the package creates them, so later `sync-agents` and session lifecycle
|
|
160
|
+
commands can refresh the generated region without warning. If those files
|
|
161
|
+
already exist without markers, init leaves them untouched unless you explicitly
|
|
162
|
+
adopt them.
|
|
147
163
|
|
|
148
164
|
Check an initialized root without writing files:
|
|
149
165
|
|
|
@@ -188,9 +204,9 @@ remind you with a non-blocking warning if no completed review exists.
|
|
|
188
204
|
|
|
189
205
|
What happens:
|
|
190
206
|
|
|
191
|
-
1. The CLI asks which LLM you'll use, then prints a versioned prompt
|
|
207
|
+
1. The CLI asks which LLM you'll use, then prints a versioned staged review prompt with fixed review criteria.
|
|
192
208
|
2. You paste that prompt into your AI tool (Claude Code, Codex, Cursor, etc.).
|
|
193
|
-
3. The AI
|
|
209
|
+
3. The AI inventories project memory and source evidence, proposes a coverage plan, then writes only accepted architecture docs under
|
|
194
210
|
`architecture/<domain>/<feature>/<component>.md`.
|
|
195
211
|
4. Run `vibecompass docs-review --apply-output` after accepting fenced
|
|
196
212
|
architecture-doc blocks, or `--complete` if accepted docs were written
|
|
@@ -199,8 +215,11 @@ What happens:
|
|
|
199
215
|
The guided prompt is deterministic apart from project-specific fields
|
|
200
216
|
(`project`, `mode`, `root`, provider, and model). It uses the same structure
|
|
201
217
|
VibeCompass dogfoods: read project memory first, inspect source evidence,
|
|
202
|
-
write component docs with review
|
|
203
|
-
emit accepted docs as
|
|
218
|
+
build a coverage plan, write retrieval-oriented component docs with review
|
|
219
|
+
metadata, preserve the starter overview, and emit accepted docs as
|
|
220
|
+
`vibecompass-architecture-doc` blocks. The prompt includes a soft 12000-byte
|
|
221
|
+
budget per generated architecture doc so future LLM sessions can load targeted
|
|
222
|
+
context without pulling oversized narrative files by default.
|
|
204
223
|
|
|
205
224
|
Plain `--guided` never calls an AI itself. You stay in control of which
|
|
206
225
|
provider runs the review and what gets saved. Use `--run-local --provider
|
|
@@ -283,7 +302,7 @@ Generate agent-instruction files from project memory:
|
|
|
283
302
|
npx -y @vibecompass/vibecompass sync-agents --root .compass
|
|
284
303
|
```
|
|
285
304
|
|
|
286
|
-
`sync-agents` writes
|
|
305
|
+
`sync-agents` writes compact VibeCompass bootloader regions:
|
|
287
306
|
|
|
288
307
|
```md
|
|
289
308
|
<!-- vibecompass:start - managed by VibeCompass, do not edit -->
|
|
@@ -291,13 +310,23 @@ npx -y @vibecompass/vibecompass sync-agents --root .compass
|
|
|
291
310
|
<!-- vibecompass:end -->
|
|
292
311
|
```
|
|
293
312
|
|
|
294
|
-
Content outside those markers is preserved.
|
|
295
|
-
|
|
313
|
+
Content outside those markers is preserved. Package-created starter files
|
|
314
|
+
include managed markers from the beginning. Existing user files without markers
|
|
315
|
+
are reported as warnings and left untouched unless you explicitly adopt them:
|
|
296
316
|
|
|
297
317
|
```bash
|
|
298
318
|
npx -y @vibecompass/vibecompass sync-agents --root .compass --adopt-existing
|
|
299
319
|
```
|
|
300
320
|
|
|
321
|
+
The managed block intentionally stays short: project-memory root, read order,
|
|
322
|
+
prompt-command routing, and hard safety rules. Detailed workflow lives in
|
|
323
|
+
`context.md` and generated files under `workflows/`, so `CLAUDE.md`, `AGENTS.md`,
|
|
324
|
+
`.cursorrules`, and Copilot instructions do not duplicate long protocol text.
|
|
325
|
+
`CLAUDE.md` starters also keep the mutable `Current session` block above the
|
|
326
|
+
managed region because session lifecycle commands update it. `AGENTS.md`
|
|
327
|
+
starters are intentionally just the managed bootloader; add Codex/team notes
|
|
328
|
+
before or after the marker block if needed, and `sync-agents` will preserve them.
|
|
329
|
+
|
|
301
330
|
Adoption appends a managed VibeCompass block to the end of existing unmarked
|
|
302
331
|
agent files, preserves everything outside the markers, and reports possible
|
|
303
332
|
workflow-overlap lines before you rely on the result. Guided init may offer the
|
|
@@ -665,7 +694,23 @@ Accepted review content.
|
|
|
665
694
|
```
|
|
666
695
|
````
|
|
667
696
|
|
|
668
|
-
|
|
697
|
+
The fence opening is strict: it must be exactly
|
|
698
|
+
`vibecompass-architecture-doc path=<architecture/*.md>` with one `path`
|
|
699
|
+
attribute and no extra attributes. Malformed architecture-doc fences report a
|
|
700
|
+
targeted error instead of being treated as "no output found".
|
|
701
|
+
|
|
702
|
+
Only `architecture/*.md` paths are writable through this apply step. Component
|
|
703
|
+
docs require non-empty `domain`, `feature`, `component`, and `status`
|
|
704
|
+
frontmatter. The project overview file,
|
|
705
|
+
`architecture/overview/project-shape.md`, may use status-only frontmatter so it
|
|
706
|
+
matches hosted docs-review proposal behavior. If one accepted output contains
|
|
707
|
+
multiple blocks for the same architecture path, local apply fails rather than
|
|
708
|
+
silently overwriting earlier accepted content.
|
|
709
|
+
|
|
710
|
+
Accepted architecture docs over the soft 12000-byte size budget are applied
|
|
711
|
+
with an `oversized_architecture_doc` warning instead of being rejected. Treat
|
|
712
|
+
that warning as a prompt to compact the doc unless the extra detail is needed
|
|
713
|
+
for future retrieval.
|
|
669
714
|
|
|
670
715
|
`vibecompass docs-review --complete` updates the marker in
|
|
671
716
|
`state/docs-review.json` to `status: "completed"` once the docs have
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibecompass/vibecompass",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Local-first project-memory core for VibeCompass",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -11,8 +11,10 @@
|
|
|
11
11
|
".": "./src/index.js"
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
|
+
"CHANGELOG.md",
|
|
14
15
|
"src/*.js",
|
|
15
|
-
"src/generators/**/*.js"
|
|
16
|
+
"src/generators/**/*.js",
|
|
17
|
+
"src/workflows/**/*.js"
|
|
16
18
|
],
|
|
17
19
|
"scripts": {
|
|
18
20
|
"test": "node --test src/tests/*.test.js",
|
package/src/docs-review.js
CHANGED
|
@@ -5,6 +5,9 @@ import { parseFrontmatter } from './frontmatter.js';
|
|
|
5
5
|
import { writeStateManifest } from './manifest.js';
|
|
6
6
|
import { parseSimpleYaml } from './simple-yaml.js';
|
|
7
7
|
|
|
8
|
+
const DOCS_REVIEW_PROMPT_VERSION = 'VibeCompass Docs Review Prompt v2';
|
|
9
|
+
const ARCHITECTURE_DOC_SOFT_SIZE_LIMIT_BYTES = 12000;
|
|
10
|
+
|
|
8
11
|
export async function preflightDocsReview(options = {}, environment = {}) {
|
|
9
12
|
validateDocsReviewMode(options);
|
|
10
13
|
const cwd = options.cwd ? path.resolve(options.cwd) : process.cwd();
|
|
@@ -59,8 +62,10 @@ export async function preflightDocsReview(options = {}, environment = {}) {
|
|
|
59
62
|
const localProvider = resolveLocalProvider(options);
|
|
60
63
|
const runtime = resolveDocsReviewRuntime(project, {
|
|
61
64
|
env,
|
|
65
|
+
guided: Boolean(options.guided),
|
|
62
66
|
localProvider,
|
|
63
67
|
runLocal: shouldRunLocal(options),
|
|
68
|
+
anthropicEnvVar: options.anthropicEnvVar ?? 'ANTHROPIC_API_KEY',
|
|
64
69
|
});
|
|
65
70
|
const reviewPrompt = renderReviewPrompt({
|
|
66
71
|
project,
|
|
@@ -180,14 +185,20 @@ async function applyDocsReviewOutput(options) {
|
|
|
180
185
|
const blocks = parseArchitectureDocBlocks(source);
|
|
181
186
|
|
|
182
187
|
if (blocks.length === 0) {
|
|
188
|
+
const malformedFenceCount = countMalformedArchitectureDocFences(source);
|
|
189
|
+
if (malformedFenceCount > 0) {
|
|
190
|
+
throw new Error(
|
|
191
|
+
`Malformed architecture doc fence found in ${outputPath}. Expected fence openings like \`\`\`vibecompass-architecture-doc path=architecture/domain/feature/component.md\` with exactly one path attribute and no extra attributes.`,
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
183
195
|
throw new Error(
|
|
184
196
|
`No accepted architecture doc blocks found in ${outputPath}. Expected fenced blocks like \`\`\`vibecompass-architecture-doc path=architecture/domain/feature/component.md\`.`,
|
|
185
197
|
);
|
|
186
198
|
}
|
|
187
199
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
200
|
+
validateArchitectureDocBlocks(blocks);
|
|
201
|
+
const warnings = createArchitectureDocSizeWarnings(blocks);
|
|
191
202
|
|
|
192
203
|
const applied = [];
|
|
193
204
|
for (const block of blocks) {
|
|
@@ -208,6 +219,7 @@ async function applyDocsReviewOutput(options) {
|
|
|
208
219
|
applied: {
|
|
209
220
|
output_path: outputPath,
|
|
210
221
|
architecture_docs: applied,
|
|
222
|
+
...(warnings.length > 0 ? { warnings } : {}),
|
|
211
223
|
applied_at: new Date().toISOString(),
|
|
212
224
|
},
|
|
213
225
|
completed_at: new Date().toISOString(),
|
|
@@ -225,7 +237,7 @@ async function applyDocsReviewOutput(options) {
|
|
|
225
237
|
hosted: current.hosted ?? null,
|
|
226
238
|
applied: marker.applied,
|
|
227
239
|
reviewPrompt: null,
|
|
228
|
-
warnings
|
|
240
|
+
warnings,
|
|
229
241
|
message: `Applied ${applied.length} accepted architecture doc${applied.length === 1 ? '' : 's'} and completed the docs-review marker.`,
|
|
230
242
|
};
|
|
231
243
|
}
|
|
@@ -357,6 +369,13 @@ function validateDocsReviewMode(options) {
|
|
|
357
369
|
}
|
|
358
370
|
|
|
359
371
|
async function promptForReviewConfig(options, environment) {
|
|
372
|
+
if (options.llm && options.model) {
|
|
373
|
+
return normalizeReviewConfig({
|
|
374
|
+
llm: options.llm,
|
|
375
|
+
model: options.model,
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
|
|
360
379
|
const prompter = createPrompter(environment.io, environment.runtime);
|
|
361
380
|
try {
|
|
362
381
|
if (!options.llm) {
|
|
@@ -485,6 +504,10 @@ function resolveDocsReviewRuntime(project, options) {
|
|
|
485
504
|
};
|
|
486
505
|
}
|
|
487
506
|
|
|
507
|
+
if (options.guided) {
|
|
508
|
+
return { provider: 'external' };
|
|
509
|
+
}
|
|
510
|
+
|
|
488
511
|
throw new Error(
|
|
489
512
|
`docs-review for local-primary projects requires a hosted sync binding or ${options.anthropicEnvVar}.`,
|
|
490
513
|
);
|
|
@@ -601,6 +624,32 @@ function parseArchitectureDocBlocks(source) {
|
|
|
601
624
|
return blocks;
|
|
602
625
|
}
|
|
603
626
|
|
|
627
|
+
function countMalformedArchitectureDocFences(source) {
|
|
628
|
+
const fencePattern = /^```vibecompass-architecture-doc\b.*$/gm;
|
|
629
|
+
const acceptedOpeningPattern = /^```vibecompass-architecture-doc\s+path=[^\s`]+\s*$/;
|
|
630
|
+
let count = 0;
|
|
631
|
+
let match;
|
|
632
|
+
|
|
633
|
+
while ((match = fencePattern.exec(source)) !== null) {
|
|
634
|
+
if (!acceptedOpeningPattern.test(match[0])) {
|
|
635
|
+
count += 1;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
return count;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
function validateArchitectureDocBlocks(blocks) {
|
|
643
|
+
const seenPaths = new Set();
|
|
644
|
+
for (const block of blocks) {
|
|
645
|
+
if (seenPaths.has(block.path)) {
|
|
646
|
+
throw new Error(`Accepted docs-review output contains duplicate architecture doc path: ${block.path}`);
|
|
647
|
+
}
|
|
648
|
+
seenPaths.add(block.path);
|
|
649
|
+
validateArchitectureDocBlock(block);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
|
|
604
653
|
function normalizeBlockPath(value) {
|
|
605
654
|
return String(value ?? '').trim().replaceAll('\\', '/');
|
|
606
655
|
}
|
|
@@ -625,13 +674,29 @@ function validateArchitectureDocBlock(block) {
|
|
|
625
674
|
throw new Error(`Accepted architecture doc ${block.path} must include frontmatter.`);
|
|
626
675
|
}
|
|
627
676
|
|
|
628
|
-
|
|
677
|
+
const requiredFields = block.path === 'architecture/overview/project-shape.md'
|
|
678
|
+
? ['status']
|
|
679
|
+
: ['domain', 'feature', 'component', 'status'];
|
|
680
|
+
for (const field of requiredFields) {
|
|
629
681
|
if (typeof frontmatter.data[field] !== 'string' || frontmatter.data[field].trim() === '') {
|
|
630
682
|
throw new Error(`Accepted architecture doc ${block.path} requires non-empty frontmatter field "${field}".`);
|
|
631
683
|
}
|
|
632
684
|
}
|
|
633
685
|
}
|
|
634
686
|
|
|
687
|
+
function createArchitectureDocSizeWarnings(blocks) {
|
|
688
|
+
return blocks
|
|
689
|
+
.map((block) => {
|
|
690
|
+
const byteLength = Buffer.byteLength(ensureTrailingNewline(block.content), 'utf8');
|
|
691
|
+
if (byteLength <= ARCHITECTURE_DOC_SOFT_SIZE_LIMIT_BYTES) {
|
|
692
|
+
return null;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
return `oversized_architecture_doc: ${block.path} is ${byteLength} bytes; soft budget is ${ARCHITECTURE_DOC_SOFT_SIZE_LIMIT_BYTES} bytes. Consider compacting the doc to preserve future LLM context budget.`;
|
|
696
|
+
})
|
|
697
|
+
.filter(Boolean);
|
|
698
|
+
}
|
|
699
|
+
|
|
635
700
|
async function submitHostedDocsReview(options) {
|
|
636
701
|
if (options.runtime.provider !== 'hosted') {
|
|
637
702
|
throw new Error('docs-review --submit-hosted requires a hosted sync binding in project.yaml.');
|
|
@@ -1034,9 +1099,9 @@ function renderDocsReviewMessage(options) {
|
|
|
1034
1099
|
|
|
1035
1100
|
function renderReviewPrompt(options) {
|
|
1036
1101
|
return [
|
|
1037
|
-
|
|
1102
|
+
`# ${DOCS_REVIEW_PROMPT_VERSION}`,
|
|
1038
1103
|
'',
|
|
1039
|
-
'Run a
|
|
1104
|
+
'Run a staged VibeCompass architecture documentation review for the project-memory root below. Follow this prompt exactly; do not invent a different document structure.',
|
|
1040
1105
|
'',
|
|
1041
1106
|
'## Review Context',
|
|
1042
1107
|
`- Project memory root: ${options.rootDir}`,
|
|
@@ -1049,13 +1114,35 @@ function renderReviewPrompt(options) {
|
|
|
1049
1114
|
'1. Read `project.yaml`.',
|
|
1050
1115
|
'2. Read `context.md` if present.',
|
|
1051
1116
|
'3. Read all canonical files under `architecture/`, `decisions/`, and finalized `sessions/`.',
|
|
1052
|
-
'4. Inspect
|
|
1117
|
+
'4. Inspect declared repositories before making implementation claims.',
|
|
1118
|
+
'',
|
|
1119
|
+
'## Staged Review Protocol',
|
|
1120
|
+
'Stage 1 — Evidence inventory:',
|
|
1121
|
+
'- Build a compact repo inventory from file paths, manifests/config files, route/job/test directories, and existing architecture frontmatter before reading large file bodies.',
|
|
1122
|
+
'- Identify candidate domains, features, components, and ownership boundaries with concrete `repo:path` evidence.',
|
|
1123
|
+
'- Do not fetch or summarize broad source bodies until the coverage plan says a file is needed.',
|
|
1124
|
+
'',
|
|
1125
|
+
'Stage 2 — Coverage plan:',
|
|
1126
|
+
'- Propose the smallest useful architecture-doc set that will let future agents understand the project and retrieve targeted context.',
|
|
1127
|
+
'- Prioritize entry points, data ownership, external integrations, jobs/async boundaries, auth/security boundaries, and test surfaces.',
|
|
1128
|
+
'- Mark each proposed doc as `comprehensive`, `partial`, or `initial`, with the reason and blindspots.',
|
|
1129
|
+
'- Ask for user acceptance before emitting fenced architecture-doc blocks.',
|
|
1130
|
+
'',
|
|
1131
|
+
'Stage 3 — Bounded doc generation:',
|
|
1132
|
+
'- Generate only accepted docs, one complete fenced block per architecture path.',
|
|
1133
|
+
'- Keep docs concise and retrieval-oriented: explain contracts, flows, invariants, and ownership; do not rewrite source code or produce file-by-file walkthroughs.',
|
|
1134
|
+
`- Soft size budget: keep each generated architecture doc under ${ARCHITECTURE_DOC_SOFT_SIZE_LIMIT_BYTES} bytes unless the extra detail is necessary and called out in Blindspots or Retrieval guidance.`,
|
|
1135
|
+
'- Include only the most important involved files; prefer representative entry points and owned contracts over exhaustive file lists.',
|
|
1136
|
+
'',
|
|
1137
|
+
'Stage 4 — Apply and verify:',
|
|
1138
|
+
'- After accepted blocks are written to `state/docs-review-output.md`, run `vibecompass docs-review --apply-output`.',
|
|
1139
|
+
'- Surface any parser warnings, especially oversized docs, so the user can decide whether to compact or accept the output.',
|
|
1053
1140
|
'',
|
|
1054
1141
|
'## Architecture Doc Contract',
|
|
1055
1142
|
'When creating or updating architecture docs, use the existing VibeCompass structure:',
|
|
1056
1143
|
'- path: `architecture/<domain-slug>/<feature-slug>/<component-slug>.md` for component docs',
|
|
1057
1144
|
'- frontmatter fields: `domain`, `feature`, `component`, `status`, plus `repo` or `repos` when implementation-scoped',
|
|
1058
|
-
'- body sections: `## Description`, `## Review metadata`, `## Details`, `## Next steps`, `## Involved files`',
|
|
1145
|
+
'- body sections: `## Description`, `## Review metadata`, `## Details`, `## Retrieval guidance`, `## Next steps`, `## Involved files`',
|
|
1059
1146
|
'',
|
|
1060
1147
|
'Use this exact Review metadata sub-header in every generated architecture doc:',
|
|
1061
1148
|
'',
|
|
@@ -1066,6 +1153,8 @@ function renderReviewPrompt(options) {
|
|
|
1066
1153
|
'- Confidence: high | medium | low',
|
|
1067
1154
|
'- Coverage: comprehensive | partial | initial',
|
|
1068
1155
|
'- Evidence: repo:path references inspected before making implementation claims',
|
|
1156
|
+
'- Retrieval scope: when future agents should load this doc',
|
|
1157
|
+
`- Token posture: compact unless the doc intentionally exceeds ${ARCHITECTURE_DOC_SOFT_SIZE_LIMIT_BYTES} bytes`,
|
|
1069
1158
|
'- Blindspots: explicit list, or "None identified" only when evidence is comprehensive',
|
|
1070
1159
|
'',
|
|
1071
1160
|
'## Review Rules',
|
|
@@ -1077,12 +1166,15 @@ function renderReviewPrompt(options) {
|
|
|
1077
1166
|
'6. Put uncertainty in `Blindspots`; do not fill gaps with guesses.',
|
|
1078
1167
|
'7. Do not append real `D-NNN` decisions without explicit user acceptance. Propose candidate decisions separately.',
|
|
1079
1168
|
'8. Do not edit `decisions/INDEX.md` directly unless a canonical decision file was explicitly accepted and appended.',
|
|
1169
|
+
'9. Optimize for future retrieval: project-level docs stay compact; component docs carry focused context for a specific area.',
|
|
1080
1170
|
'',
|
|
1081
1171
|
'## Output Contract',
|
|
1082
1172
|
'First provide a concise findings summary with:',
|
|
1083
1173
|
'- mapped areas',
|
|
1084
1174
|
'- gaps/blindspots',
|
|
1085
|
-
'-
|
|
1175
|
+
'- evidence inventory summary',
|
|
1176
|
+
'- coverage plan and proposed architecture docs',
|
|
1177
|
+
'- token-budget risks or oversized-doc candidates',
|
|
1086
1178
|
'- proposed decisions, if any',
|
|
1087
1179
|
'',
|
|
1088
1180
|
'Then, for each architecture doc the user accepts, output one fenced block exactly like this:',
|
|
@@ -8,6 +8,7 @@ import { claudeMdFormat } from './claude-md.js';
|
|
|
8
8
|
import { agentsMdFormat } from './agents-md.js';
|
|
9
9
|
import { cursorRulesFormat } from './cursor-rules.js';
|
|
10
10
|
import { copilotInstructionsFormat } from './copilot-instructions.js';
|
|
11
|
+
import { getWorkflowConflictScanPatterns } from '../../workflows/registry.js';
|
|
11
12
|
|
|
12
13
|
const FORMATS = [
|
|
13
14
|
claudeMdFormat,
|
|
@@ -17,17 +18,7 @@ const FORMATS = [
|
|
|
17
18
|
];
|
|
18
19
|
|
|
19
20
|
const FORMAT_MAP = new Map(FORMATS.map((format) => [format.name, format]));
|
|
20
|
-
const CONFLICT_SCAN_PATTERNS =
|
|
21
|
-
'session',
|
|
22
|
-
'handoff',
|
|
23
|
-
'decisions',
|
|
24
|
-
'wip.md',
|
|
25
|
-
'review handoff',
|
|
26
|
-
'close-session',
|
|
27
|
-
'address review',
|
|
28
|
-
'builder',
|
|
29
|
-
'reviewer',
|
|
30
|
-
];
|
|
21
|
+
const CONFLICT_SCAN_PATTERNS = getWorkflowConflictScanPatterns();
|
|
31
22
|
|
|
32
23
|
export async function syncAgentInstructionFiles(options = {}) {
|
|
33
24
|
const cwd = options.cwd ? path.resolve(options.cwd) : process.cwd();
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { renderPromptCommandLines } from '../../workflows/registry.js';
|
|
2
|
+
|
|
1
3
|
export function buildAgentContext(readModel) {
|
|
2
4
|
return {
|
|
3
5
|
projectName: readModel.project.name ?? 'Unnamed project',
|
|
@@ -16,47 +18,40 @@ export function renderSharedInstructionBody(context, options = {}) {
|
|
|
16
18
|
const intro =
|
|
17
19
|
options.intro ??
|
|
18
20
|
'Use VibeCompass project memory as the source of truth before making code changes.';
|
|
21
|
+
const contextPath = `${context.rootDir}/context.md`;
|
|
19
22
|
|
|
20
23
|
return [
|
|
21
24
|
`# ${heading}`,
|
|
22
25
|
'',
|
|
23
26
|
intro,
|
|
24
27
|
'',
|
|
25
|
-
`Read \`${
|
|
28
|
+
`This managed block is a compact bootloader. Read \`${contextPath}\` for the full VibeCompass workflow protocol; workflow-specific details live under \`${context.rootDir}/workflows/\`.`,
|
|
26
29
|
'',
|
|
27
30
|
'Existing project-specific coding, style, framework, and safety instructions outside this managed block remain authoritative. This block owns only VibeCompass project-memory workflow: sessions, handoffs, decisions, docs-review, and close-out.',
|
|
28
31
|
'',
|
|
29
|
-
'##
|
|
32
|
+
'## Project Snapshot',
|
|
30
33
|
`- Project memory root: \`${context.rootDir}\``,
|
|
31
|
-
|
|
32
|
-
'- Read the latest finalized session note under `sessions/` before resuming work.',
|
|
33
|
-
'- Read `sessions/active/index.yaml` when it exists, then read the selected lane under `sessions/active/<lane-id>/`.',
|
|
34
|
-
'- Read the selected lane `wip.md` and `handoff.md` when they exist; they are the active builder/reviewer scratch files.',
|
|
35
|
-
'- Read relevant `architecture/` and `decisions/` files before changing implementation.',
|
|
34
|
+
...renderProjectSnapshot(context),
|
|
36
35
|
'',
|
|
37
|
-
'##
|
|
38
|
-
|
|
36
|
+
'## Read Order',
|
|
37
|
+
`1. Read \`${contextPath}\`.`,
|
|
38
|
+
`2. Read the latest finalized session note under \`${context.rootDir}/sessions/\`.`,
|
|
39
|
+
`3. If present, read \`${context.rootDir}/sessions/active/index.yaml\`, then the selected lane's \`wip.md\` and \`handoff.md\`.`,
|
|
40
|
+
`4. Read relevant \`${context.rootDir}/architecture/\` and \`${context.rootDir}/decisions/\` docs before editing implementation.`,
|
|
39
41
|
'',
|
|
40
|
-
'##
|
|
41
|
-
|
|
42
|
-
'-
|
|
43
|
-
'- Use `vibecompass start-session --id <lane-id>` to open a named lane for every active feature or workstream.',
|
|
44
|
-
'- Use `vibecompass list-sessions` and `vibecompass switch-session <lane-id>` to inspect or change the current lane.',
|
|
45
|
-
'- Treat `sessions/active/index.yaml` as the current lane source of truth; tool-specific Current session blocks are continuity summaries.',
|
|
46
|
-
'- Use optional planning mode for risky or ambiguous work: read the same context, propose scope, and record the agreed plan in the selected lane `wip.md` before implementation.',
|
|
47
|
-
'- Use `review handoff` to ask a reviewer to inspect the active handoff.',
|
|
48
|
-
'- Use `address review` to process reviewer feedback from the selected lane `wip.md` and `handoff.md`.',
|
|
49
|
-
'- End the active builder session with the `close session` prompt, which runs close-out and ends with `vibecompass close-session --session <lane-id>`; `end session` and `vibecompass end-session` are accepted aliases.',
|
|
50
|
-
'- If stale scratch files block `start-session`, read them first, then close, recover, move, or delete them intentionally before retrying.',
|
|
51
|
-
'- Keep decisions append-only in `decisions/`. Session notes may reference decisions, but decisions are the durable source of truth.',
|
|
52
|
-
'- Treat generated agent files as views. Update canonical VibeCompass project memory instead of editing managed regions.',
|
|
42
|
+
'## Prompt Commands',
|
|
43
|
+
...renderPromptCommandLines({ rootRelativePath: context.rootDir }),
|
|
44
|
+
'- The prompt commands above are agent behaviors. The `vibecompass` CLI commands remain the filesystem mechanics behind them.',
|
|
53
45
|
'',
|
|
54
|
-
'##
|
|
55
|
-
|
|
46
|
+
'## Hard Rules',
|
|
47
|
+
'- Treat `sessions/active/index.yaml` as the current lane source of truth; tool-specific Current session blocks are continuity summaries.',
|
|
48
|
+
'- Keep the selected lane `wip.md` and `handoff.md` current during active builder/reviewer work.',
|
|
49
|
+
'- Keep decisions append-only in `decisions/`; append accepted architectural decisions before implementing them.',
|
|
50
|
+
'- Do not edit this managed block directly. Update canonical VibeCompass memory, then rerun package commands such as `vibecompass sync-agents`.',
|
|
56
51
|
].join('\n');
|
|
57
52
|
}
|
|
58
53
|
|
|
59
|
-
function
|
|
54
|
+
function renderProjectSnapshot(context) {
|
|
60
55
|
const lines = [];
|
|
61
56
|
|
|
62
57
|
if (context.description) {
|
|
@@ -71,18 +66,22 @@ function renderProjectShape(context) {
|
|
|
71
66
|
lines.push(`- Repo \`${repo.id}\`: ${repo.remote}`);
|
|
72
67
|
}
|
|
73
68
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
lines.push(`-
|
|
69
|
+
const domainCount = context.domains.length;
|
|
70
|
+
if (domainCount > 0) {
|
|
71
|
+
lines.push(`- Architecture domains recorded: ${domainCount}`);
|
|
77
72
|
}
|
|
78
73
|
|
|
79
|
-
|
|
80
|
-
}
|
|
74
|
+
if (context.recentDecisions.length > 0) {
|
|
75
|
+
lines.push(`- Latest decision: ${renderDecisionLine(context.recentDecisions[0])}`);
|
|
76
|
+
}
|
|
81
77
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return ['- No decisions recorded yet.'];
|
|
78
|
+
if (context.recentSessions.length > 0) {
|
|
79
|
+
lines.push(`- Latest session: ${context.recentSessions[0].title ?? context.recentSessions[0].path}`);
|
|
85
80
|
}
|
|
86
81
|
|
|
87
|
-
return
|
|
82
|
+
return lines.length > 0 ? lines : ['- No project details recorded yet.'];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function renderDecisionLine(decision) {
|
|
86
|
+
return `D-${String(decision.decision_id).padStart(3, '0')} — ${decision.title}`;
|
|
88
87
|
}
|
package/src/project-memory.js
CHANGED
|
@@ -364,7 +364,9 @@ function parseArchitectureDocument(options) {
|
|
|
364
364
|
}
|
|
365
365
|
|
|
366
366
|
const data = frontmatter.data;
|
|
367
|
-
const requiredFields =
|
|
367
|
+
const requiredFields = options.relativePath === 'architecture/overview/project-shape.md'
|
|
368
|
+
? ['status']
|
|
369
|
+
: ['domain', 'feature', 'component', 'status'];
|
|
368
370
|
|
|
369
371
|
for (const field of requiredFields) {
|
|
370
372
|
if (typeof data[field] !== 'string' || data[field].trim() === '') {
|
package/src/refresh-workflow.js
CHANGED
|
@@ -161,6 +161,9 @@ function isGeneratedWorkflowGuide(kind, content) {
|
|
|
161
161
|
if (kind === 'sessions-guide') {
|
|
162
162
|
return content.includes('Those scratch files are session-scoped working artifacts, not finalized history.');
|
|
163
163
|
}
|
|
164
|
+
if (kind === 'workflow-docs-review') {
|
|
165
|
+
return content.includes('Generated by VibeCompass. This file is a package-owned workflow guide');
|
|
166
|
+
}
|
|
164
167
|
|
|
165
168
|
return false;
|
|
166
169
|
}
|
package/src/scaffold.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { access, mkdir, readdir, writeFile } from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { resolveWorkflowSettings } from './workflow.js';
|
|
4
|
+
import { getGeneratedWorkflowFiles, renderPromptCommandLines } from './workflows/registry.js';
|
|
5
|
+
import { renderManagedBlock } from './generators/agent-files/markers.js';
|
|
6
|
+
import { renderSharedInstructionBody } from './generators/agent-files/template.js';
|
|
4
7
|
|
|
5
8
|
export async function scaffoldInitFiles(options) {
|
|
6
9
|
const createdFiles = [];
|
|
@@ -59,7 +62,7 @@ export async function scaffoldInitFiles(options) {
|
|
|
59
62
|
await writeFile(contextFilePath, workflowScaffold.context.content, 'utf8');
|
|
60
63
|
createdFiles.push(contextFilePath);
|
|
61
64
|
|
|
62
|
-
for (const file of workflowScaffold.guides) {
|
|
65
|
+
for (const file of [...workflowScaffold.guides, ...workflowScaffold.workflowFiles]) {
|
|
63
66
|
const outcome = await writeIfMissing(file.path, file.content);
|
|
64
67
|
if (outcome.created) {
|
|
65
68
|
createdFiles.push(file.path);
|
|
@@ -124,12 +127,20 @@ export function buildWorkflowScaffoldFiles(options) {
|
|
|
124
127
|
content: generateSessionsGuide(options.projectConfig),
|
|
125
128
|
},
|
|
126
129
|
];
|
|
130
|
+
const workflowFiles = getGeneratedWorkflowFiles({
|
|
131
|
+
rootRelativePath: options.rootRelativePath,
|
|
132
|
+
}).map((file) => ({
|
|
133
|
+
kind: file.kind,
|
|
134
|
+
path: path.join(options.rootDir, file.relativePath),
|
|
135
|
+
content: file.content,
|
|
136
|
+
}));
|
|
127
137
|
|
|
128
138
|
return {
|
|
129
139
|
contextFilePath,
|
|
130
140
|
context,
|
|
131
141
|
guides,
|
|
132
|
-
|
|
142
|
+
workflowFiles,
|
|
143
|
+
files: [context, ...guides, ...workflowFiles],
|
|
133
144
|
};
|
|
134
145
|
}
|
|
135
146
|
|
|
@@ -193,6 +204,7 @@ function generateContextMarkdown(options) {
|
|
|
193
204
|
const projectName = options.projectConfig.name;
|
|
194
205
|
const rootRelativePath = options.rootRelativePath;
|
|
195
206
|
const workflow = resolveWorkflowSettings(options.projectConfig);
|
|
207
|
+
const promptCommands = renderPromptCommandLines({ rootRelativePath }).join('\n');
|
|
196
208
|
const repos = options.projectConfig.repos
|
|
197
209
|
.map((repo) => `- \`${repo.id}\` → ${repo.remote}`)
|
|
198
210
|
.join('\n');
|
|
@@ -233,12 +245,7 @@ ${repos}
|
|
|
233
245
|
| "join as reviewer" | Reviewer | No — reviews the builder's work, appends findings, and updates handoff guidance |
|
|
234
246
|
|
|
235
247
|
## Session prompt commands
|
|
236
|
-
|
|
237
|
-
- \`join as reviewer\` — reviewer role trigger
|
|
238
|
-
- \`planning mode\` — optional prompt-level mode for scoping work before implementation
|
|
239
|
-
- \`review handoff\` — reviewer reads the selected lane's \`wip.md\`, \`handoff.md\`, latest finalized note, and relevant diffs before appending findings
|
|
240
|
-
- \`address review\` — builder reads reviewer feedback in the selected lane's \`wip.md\` / \`handoff.md\`, responds inline, applies accepted changes, and refreshes the builder handoff
|
|
241
|
-
- \`close session\` — builder runs the close-out checklist and ends with \`vibecompass close-session --session <lane-id>\`; \`end session\` is accepted as a synonym
|
|
248
|
+
${promptCommands}
|
|
242
249
|
|
|
243
250
|
These are prompt commands for agent behavior, not \`vibecompass\` CLI subcommands.
|
|
244
251
|
Reviewer handback is explicit: the reviewer ends the pass by updating the selected lane's \`wip.md\` + \`handoff.md\` and then stopping. The \`close session\` prompt runs builder close-out and ends with \`vibecompass close-session --session <lane-id>\`, which follows the workflow defaults recorded in \`${rootRelativePath}/project.yaml\`.
|
|
@@ -250,7 +257,7 @@ ${renderWorkflowDefaults(workflow)}
|
|
|
250
257
|
## Documentation coverage
|
|
251
258
|
- The architecture, decision, and session files created by init are an initial scaffold, not a comprehensive codebase review.
|
|
252
259
|
- Before risky implementation work, inspect the relevant code and update the affected architecture docs.
|
|
253
|
-
-
|
|
260
|
+
- Use the \`docs review\` prompt command when you want the current AI session to run a comprehensive documentation review. It may run \`vibecompass docs-review --guided\` as package mechanics to record marker state and print the canonical review contract.
|
|
254
261
|
|
|
255
262
|
## Session startup
|
|
256
263
|
1. Read \`${rootRelativePath}/project.yaml\`.
|
|
@@ -387,7 +394,7 @@ Not yet documented:
|
|
|
387
394
|
Before changing any undocumented area, inspect the relevant code and update or add architecture docs.
|
|
388
395
|
|
|
389
396
|
## Next steps
|
|
390
|
-
-
|
|
397
|
+
- Use the \`docs review\` prompt command for a comprehensive documentation review.
|
|
391
398
|
- Replace this placeholder with domain/feature/component docs as the project map becomes evidence-backed.
|
|
392
399
|
- Keep architecture docs aligned with implementation changes during each builder session.
|
|
393
400
|
|
|
@@ -445,7 +452,7 @@ Initialized VibeCompass project memory for ${projectConfig.name}.
|
|
|
445
452
|
${repoLines}
|
|
446
453
|
|
|
447
454
|
## Next session should start with
|
|
448
|
-
1.
|
|
455
|
+
1. Use the \`docs review\` prompt command if you want a comprehensive documentation review.
|
|
449
456
|
2. Inspect relevant code before making implementation changes in areas not covered by architecture docs.
|
|
450
457
|
3. Replace starter placeholders with evidence-backed domain/feature/component docs.
|
|
451
458
|
`;
|
|
@@ -531,33 +538,21 @@ Those scratch files are session-scoped working artifacts, not finalized history.
|
|
|
531
538
|
}
|
|
532
539
|
|
|
533
540
|
function generateClaudeTemplate(options) {
|
|
534
|
-
|
|
541
|
+
return [
|
|
542
|
+
generateClaudeSessionHeader(options),
|
|
543
|
+
renderManagedBlock(renderSharedInstructionBody(buildScaffoldAgentContext(options), {
|
|
544
|
+
heading: `${options.projectConfig.name} Claude Instructions`,
|
|
545
|
+
intro:
|
|
546
|
+
'Claude should use VibeCompass project memory as the source of truth before planning, editing, or reviewing code.',
|
|
547
|
+
})),
|
|
548
|
+
].join('\n');
|
|
549
|
+
}
|
|
535
550
|
|
|
551
|
+
function generateClaudeSessionHeader(options) {
|
|
536
552
|
return `# ${options.projectConfig.name} Workspace
|
|
537
553
|
|
|
538
554
|
Read \`${options.contextRelativeToToolingRoot}\` before doing substantive work.
|
|
539
555
|
|
|
540
|
-
## Session roles
|
|
541
|
-
|
|
542
|
-
| Entry trigger | Role | Owns session lifecycle? |
|
|
543
|
-
|---|---|---|
|
|
544
|
-
| "start session" | Builder | Yes |
|
|
545
|
-
| "join as reviewer" | Reviewer | No |
|
|
546
|
-
| "planning mode" | Planner | No — scopes work inside the selected active lane before implementation |
|
|
547
|
-
|
|
548
|
-
## Prompt commands
|
|
549
|
-
|
|
550
|
-
- \`start session\` — builder role trigger
|
|
551
|
-
- \`join as reviewer\` — reviewer role trigger
|
|
552
|
-
- \`planning mode\` — optional prompt-level mode for scoping risky or ambiguous work before implementation
|
|
553
|
-
- \`review handoff\` — reviewer reads the selected lane's \`wip.md\`, \`handoff.md\`, latest finalized note, and relevant diffs before appending findings
|
|
554
|
-
- \`address review\` — builder reads reviewer feedback in the selected lane's \`wip.md\` / \`handoff.md\`, responds inline, applies accepted changes, and refreshes the builder handoff
|
|
555
|
-
- \`close session\` — builder runs the close-out checklist and ends with \`vibecompass close-session --session <lane-id>\`; \`end session\` is accepted as a synonym
|
|
556
|
-
|
|
557
|
-
These are prompt commands for agent behavior, not \`vibecompass\` CLI subcommands.
|
|
558
|
-
Reviewer handback is explicit: the reviewer ends the pass by updating the selected lane's \`wip.md\` + \`handoff.md\` and then stopping. The \`close session\` prompt runs builder close-out and ends with \`vibecompass close-session --session <lane-id>\`, which follows the workflow defaults recorded in \`${options.rootRelativePath}/project.yaml\`.
|
|
559
|
-
\`vibecompass end-session\` is accepted as an alias for \`vibecompass close-session\`; \`close-session\` remains the canonical command name.
|
|
560
|
-
|
|
561
556
|
## Current session
|
|
562
557
|
|
|
563
558
|
**Update this block at the start and end of every session.**
|
|
@@ -569,64 +564,28 @@ Last thing completed: Project memory bootstrap completed.
|
|
|
569
564
|
Blockers: None recorded.
|
|
570
565
|
Next session should: Read \`${options.contextRelativeToToolingRoot}\`, then open the first builder or reviewer session.
|
|
571
566
|
\`\`\`
|
|
572
|
-
|
|
573
|
-
## Startup
|
|
574
|
-
- Read \`${options.contextRelativeToToolingRoot}\`
|
|
575
|
-
- Follow the builder/reviewer protocol defined there
|
|
576
|
-
- Use \`vibecompass start-session --id <lane-id>\`, \`vibecompass list-sessions\`, \`vibecompass switch-session <lane-id>\`, and \`vibecompass close-session --session <lane-id>\` to manage active lanes when possible
|
|
577
|
-
- Treat \`${options.rootRelativePath}/sessions/active/index.yaml\` as the current lane source of truth; this Current session block is only a continuity summary
|
|
578
|
-
- Keep the selected lane's \`${options.rootRelativePath}/sessions/active/<lane-id>/wip.md\` and \`${options.rootRelativePath}/sessions/active/<lane-id>/handoff.md\` current during an active session
|
|
579
|
-
- Use planning mode when scope is unclear; record the agreed plan in the selected lane's \`wip.md\` before implementing
|
|
580
|
-
- If stale scratch files block \`start-session\`, read them first, then close, recover, move, or delete them intentionally before retrying
|
|
581
|
-
- Workflow defaults:
|
|
582
|
-
${renderWorkflowDefaults(workflow)}
|
|
583
567
|
`;
|
|
584
568
|
}
|
|
585
569
|
|
|
586
570
|
function generateAgentsTemplate(options) {
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
## Session roles
|
|
594
|
-
|
|
595
|
-
| Entry trigger | Role | Owns session lifecycle? |
|
|
596
|
-
|---|---|---|
|
|
597
|
-
| "start session" | Builder | Yes — opens and closes the session lifecycle |
|
|
598
|
-
| "join as reviewer" | Reviewer | No — reviews the builder's work and updates the handoff |
|
|
599
|
-
| "planning mode" | Planner | No — scopes work inside the selected active lane before implementation |
|
|
600
|
-
|
|
601
|
-
## Prompt commands
|
|
602
|
-
|
|
603
|
-
- \`start session\` — builder role trigger
|
|
604
|
-
- \`join as reviewer\` — reviewer role trigger
|
|
605
|
-
- \`planning mode\` — optional prompt-level mode for scoping risky or ambiguous work before implementation
|
|
606
|
-
- \`review handoff\` — reviewer reads the selected lane's \`wip.md\`, \`handoff.md\`, latest finalized note, and relevant diffs before appending findings
|
|
607
|
-
- \`address review\` — builder reads reviewer feedback in the selected lane's \`wip.md\` / \`handoff.md\`, responds inline, applies accepted changes, and refreshes the builder handoff
|
|
608
|
-
- \`close session\` — builder runs the close-out checklist and ends with \`vibecompass close-session --session <lane-id>\`; \`end session\` is accepted as a synonym
|
|
571
|
+
return renderManagedBlock(renderSharedInstructionBody(buildScaffoldAgentContext(options), {
|
|
572
|
+
heading: `${options.projectConfig.name} Agent Instructions`,
|
|
573
|
+
intro:
|
|
574
|
+
'Agents should use VibeCompass project memory as the source of truth before planning, editing, or reviewing code.',
|
|
575
|
+
}));
|
|
576
|
+
}
|
|
609
577
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
6. Read the relevant docs under \`${options.rootRelativePath}/architecture/\` and \`${options.rootRelativePath}/decisions/\`.
|
|
622
|
-
|
|
623
|
-
## Working rule
|
|
624
|
-
Treat \`${options.contextRelativeToToolingRoot}\` as the local workflow source of truth for the builder/reviewer protocol and session scratch-file structure. When the package provides \`start-session\` / \`close-session\`, prefer those commands over hand-editing boilerplate.
|
|
625
|
-
Use planning mode when scope is unclear; record the agreed plan in the selected lane's \`wip.md\` before implementing.
|
|
626
|
-
If stale scratch files block \`start-session\`, read them first, then close, recover, move, or delete them intentionally before retrying.
|
|
627
|
-
- Workflow defaults:
|
|
628
|
-
${renderWorkflowDefaults(workflow)}
|
|
629
|
-
`;
|
|
578
|
+
function buildScaffoldAgentContext(options) {
|
|
579
|
+
return {
|
|
580
|
+
projectName: options.projectConfig.name ?? 'Unnamed project',
|
|
581
|
+
description: options.projectConfig.description ?? null,
|
|
582
|
+
mode: options.projectConfig.mode ?? null,
|
|
583
|
+
rootDir: options.rootRelativePath,
|
|
584
|
+
repos: options.projectConfig.repos ?? [],
|
|
585
|
+
domains: [],
|
|
586
|
+
recentDecisions: [],
|
|
587
|
+
recentSessions: [],
|
|
588
|
+
};
|
|
630
589
|
}
|
|
631
590
|
|
|
632
591
|
function renderWorkflowDefaults(workflow) {
|
package/src/setup.js
CHANGED
|
@@ -7,6 +7,7 @@ import { promisify } from 'node:util';
|
|
|
7
7
|
import { getSupportedAgentFilePaths } from './generators/agent-files/index.js';
|
|
8
8
|
import { END_MARKER, START_MARKER } from './generators/agent-files/markers.js';
|
|
9
9
|
import { parseSimpleYaml } from './simple-yaml.js';
|
|
10
|
+
import { getWorkflowConflictScanPatterns } from './workflows/registry.js';
|
|
10
11
|
|
|
11
12
|
const execFileAsync = promisify(execFile);
|
|
12
13
|
|
|
@@ -859,17 +860,7 @@ function writeAgentAdoptionPreview(prompter, candidates) {
|
|
|
859
860
|
}
|
|
860
861
|
|
|
861
862
|
function scanPotentialAgentWorkflowConflicts(content) {
|
|
862
|
-
const patterns =
|
|
863
|
-
'session',
|
|
864
|
-
'handoff',
|
|
865
|
-
'decisions',
|
|
866
|
-
'wip.md',
|
|
867
|
-
'review handoff',
|
|
868
|
-
'close-session',
|
|
869
|
-
'address review',
|
|
870
|
-
'builder',
|
|
871
|
-
'reviewer',
|
|
872
|
-
];
|
|
863
|
+
const patterns = getWorkflowConflictScanPatterns();
|
|
873
864
|
|
|
874
865
|
return content
|
|
875
866
|
.split(/\r?\n/)
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
export const WORKFLOW_REGISTRY = [
|
|
2
|
+
{
|
|
3
|
+
id: 'session-lifecycle',
|
|
4
|
+
title: 'Session lifecycle',
|
|
5
|
+
detailPath: 'context.md',
|
|
6
|
+
summary: 'Builder/reviewer lane lifecycle, handoffs, planning mode, and close-out.',
|
|
7
|
+
promptCommands: [
|
|
8
|
+
{ trigger: 'start session', summary: 'builder role trigger' },
|
|
9
|
+
{ trigger: 'join as reviewer', summary: 'reviewer role trigger' },
|
|
10
|
+
{ trigger: 'planning mode', summary: 'optional prompt-level mode for scoping work before implementation' },
|
|
11
|
+
{ trigger: 'review handoff', summary: 'reviewer reads the selected lane handoff and appends findings' },
|
|
12
|
+
{ trigger: 'address review', summary: 'builder processes reviewer feedback from the selected lane scratch files' },
|
|
13
|
+
{ trigger: 'close session', summary: 'builder runs the close-out checklist and ends with `vibecompass close-session --session <lane-id>`; `end session` and `vibecompass end-session` are accepted aliases' },
|
|
14
|
+
],
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: 'docs-review',
|
|
18
|
+
title: 'Docs review',
|
|
19
|
+
detailPath: 'workflows/docs-review.md',
|
|
20
|
+
summary: 'Generate evidence-backed architecture docs from the user\'s preferred AI session.',
|
|
21
|
+
promptCommands: [
|
|
22
|
+
{ trigger: 'docs review', summary: 'agent-led architecture documentation review using the preferred LLM prompt box' },
|
|
23
|
+
],
|
|
24
|
+
generatedFileKind: 'workflow-docs-review',
|
|
25
|
+
renderFile: renderDocsReviewWorkflow,
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
export function getPromptCommands() {
|
|
30
|
+
return WORKFLOW_REGISTRY.flatMap((workflow) =>
|
|
31
|
+
workflow.promptCommands.map((command) => ({
|
|
32
|
+
...command,
|
|
33
|
+
workflowId: workflow.id,
|
|
34
|
+
workflowTitle: workflow.title,
|
|
35
|
+
detailPath: workflow.detailPath,
|
|
36
|
+
})),
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function getWorkflowConflictScanPatterns() {
|
|
41
|
+
const patterns = new Set([
|
|
42
|
+
'session',
|
|
43
|
+
'handoff',
|
|
44
|
+
'decisions',
|
|
45
|
+
'wip.md',
|
|
46
|
+
'builder',
|
|
47
|
+
'reviewer',
|
|
48
|
+
]);
|
|
49
|
+
|
|
50
|
+
for (const command of getPromptCommands()) {
|
|
51
|
+
const normalizedTrigger = command.trigger.toLowerCase();
|
|
52
|
+
patterns.add(normalizedTrigger);
|
|
53
|
+
patterns.add(slugifyPromptTrigger(normalizedTrigger));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return Array.from(patterns);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function getGeneratedWorkflowFiles(options = {}) {
|
|
60
|
+
const rootRelativePath = options.rootRelativePath ?? '.';
|
|
61
|
+
return WORKFLOW_REGISTRY
|
|
62
|
+
.filter((workflow) => typeof workflow.renderFile === 'function')
|
|
63
|
+
.map((workflow) => ({
|
|
64
|
+
kind: workflow.generatedFileKind,
|
|
65
|
+
relativePath: workflow.detailPath,
|
|
66
|
+
content: workflow.renderFile({
|
|
67
|
+
rootRelativePath,
|
|
68
|
+
workflow,
|
|
69
|
+
}),
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function renderPromptCommandLines(options = {}) {
|
|
74
|
+
const rootRelativePath = options.rootRelativePath ?? '.';
|
|
75
|
+
return getPromptCommands().map((command) => {
|
|
76
|
+
const detailPath = command.detailPath
|
|
77
|
+
? ` Read \`${joinRootRelative(rootRelativePath, command.detailPath)}\` for the full workflow.`
|
|
78
|
+
: '';
|
|
79
|
+
return `- \`${command.trigger}\` — ${command.summary}.${detailPath}`;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function renderDocsReviewWorkflow(options = {}) {
|
|
84
|
+
const rootRelativePath = options.rootRelativePath ?? '.';
|
|
85
|
+
const projectYamlPath = joinRootRelative(rootRelativePath, 'project.yaml');
|
|
86
|
+
const contextPath = joinRootRelative(rootRelativePath, 'context.md');
|
|
87
|
+
const architecturePath = joinRootRelative(rootRelativePath, 'architecture/');
|
|
88
|
+
const decisionsPath = joinRootRelative(rootRelativePath, 'decisions/');
|
|
89
|
+
const sessionsPath = joinRootRelative(rootRelativePath, 'sessions/');
|
|
90
|
+
const outputPath = joinRootRelative(rootRelativePath, 'state/docs-review-output.md');
|
|
91
|
+
|
|
92
|
+
return `# VibeCompass Workflow — docs review
|
|
93
|
+
|
|
94
|
+
Generated by VibeCompass. This file is a package-owned workflow guide and may be refreshed by \`vibecompass refresh-workflow --apply\`.
|
|
95
|
+
|
|
96
|
+
## Prompt trigger
|
|
97
|
+
|
|
98
|
+
When the user says \`docs review\`, run this workflow inside the current Claude Code, Codex, Cursor, or Copilot session. The npm package owns state markers and apply mechanics; the AI session owns repository inspection and writing accepted architecture docs.
|
|
99
|
+
|
|
100
|
+
## Goal
|
|
101
|
+
|
|
102
|
+
Turn starter project memory into evidence-backed architecture docs under \`architecture/<domain>/<feature>/<component>.md\`.
|
|
103
|
+
|
|
104
|
+
## Steps
|
|
105
|
+
|
|
106
|
+
1. Read \`${projectYamlPath}\`, \`${contextPath}\`, existing \`${architecturePath}\`, \`${decisionsPath}\`, and finalized \`${sessionsPath}\` notes.
|
|
107
|
+
2. Inspect the declared source repos in stages:
|
|
108
|
+
- inventory paths, manifests, configs, route/job/test directories, and existing architecture frontmatter first
|
|
109
|
+
- produce a coverage plan before reading broad source bodies
|
|
110
|
+
- read targeted source files only when the coverage plan needs evidence
|
|
111
|
+
3. Run \`vibecompass docs-review --guided --llm <tool-name> --model <model-name>\` to record the review marker and print the canonical docs-review contract. Use the current AI tool name and model when known.
|
|
112
|
+
4. Present the evidence inventory, coverage plan, proposed architecture docs, blindspots, and token-budget risks before generating accepted docs.
|
|
113
|
+
5. Draft only architecture docs the user accepts. Accepted docs must be fenced exactly as \`vibecompass-architecture-doc path=architecture/domain/feature/component.md\` blocks and must include required frontmatter: \`domain\`, \`feature\`, \`component\`, and \`status\`.
|
|
114
|
+
6. Keep each generated architecture doc focused and retrieval-oriented. Soft budget: under 12000 bytes per doc unless the extra detail is necessary and called out in review metadata or retrieval guidance.
|
|
115
|
+
7. Write the accepted fenced blocks to \`${outputPath}\`.
|
|
116
|
+
8. Run \`vibecompass docs-review --apply-output\` to validate and apply the accepted blocks. If accepted docs were written manually outside the output file, run \`vibecompass docs-review --complete\` after confirming the marker should be completed.
|
|
117
|
+
9. Run \`vibecompass status\` to confirm the docs-review marker is complete. Report the applied architecture paths, any parser warnings such as oversized docs, and any blindspots documented in the accepted docs-review output.
|
|
118
|
+
|
|
119
|
+
## Rules
|
|
120
|
+
|
|
121
|
+
- Do not duplicate the full canonical review prompt in this file. The package command prints that contract from its current implementation.
|
|
122
|
+
- Follow the canonical review prompt for evidence, blindspot, and decision-recommendation constraints.
|
|
123
|
+
- Treat the package-owned prompt as the source of truth. Tool-specific skills may wrap this workflow, but should not define a divergent docs-review protocol.
|
|
124
|
+
- Do not edit generated agent files directly. Update VibeCompass project memory or rerun package commands instead.
|
|
125
|
+
`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function slugifyPromptTrigger(trigger) {
|
|
129
|
+
return trigger.trim().replace(/\s+/g, '-');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function joinRootRelative(rootRelativePath, relativePath) {
|
|
133
|
+
if (!rootRelativePath || rootRelativePath === '.') {
|
|
134
|
+
return relativePath;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return `${rootRelativePath.replace(/\/$/, '')}/${relativePath}`;
|
|
138
|
+
}
|