@vibecompass/vibecompass 0.8.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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.0 - 2026-06-14
4
+
5
+ - Add explicit local folder sources for non-Git projects: `project.yaml.repos[]` may use `source: local` plus `path`, and `init` accepts `--repo-local <id=path>`.
6
+ - Keep blank Git remotes invalid, but report an actionable `--repo-local` hint when `--repo <id=remote>` resolves to an empty value.
7
+ - Update guided init, starter docs, status, scanning, and read-model output so local-source roots validate and render cleanly.
8
+ - Bump docs-review to `VibeCompass Docs Review Prompt v3`, requiring first-pass docs to include a user journey, project/system map, and core journey-facing feature summaries.
9
+ - Add `vibecompass-project-map version=1` support inside `architecture/overview/project-shape.md`, including nested-fence parsing so generated overview docs can round-trip the machine-readable journey map block.
10
+
3
11
  ## 0.8.0 - 2026-06-12
4
12
 
5
13
  - Add named sync targets (D-236): `connect-hosted --target <name>` binds one project root to multiple hosted environments (for example `dev` on localhost and `prod` on vibecompass.dev).
package/README.md CHANGED
@@ -38,6 +38,15 @@ Create project memory:
38
38
  npx -y @vibecompass/vibecompass init --guided
39
39
  ```
40
40
 
41
+ For a folder that is not a Git repo, use an explicit local source:
42
+
43
+ ```bash
44
+ npx -y @vibecompass/vibecompass init \
45
+ --name "My Project" \
46
+ --mode local-primary \
47
+ --repo-local app=.
48
+ ```
49
+
41
50
  Check what to do next:
42
51
 
43
52
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibecompass/vibecompass",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Local-first project-memory core for VibeCompass",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -568,6 +568,11 @@ export function parseCliArgs(argv) {
568
568
  parsed.repos.push({ id, remote });
569
569
  break;
570
570
  }
571
+ case '--repo-local': {
572
+ const [id, repoPath] = splitAssignment(value, '--repo-local');
573
+ parsed.repos.push({ id, source: 'local', path: repoPath });
574
+ break;
575
+ }
571
576
  case '--repo-branch': {
572
577
  const [id, defaultBranch] = splitAssignment(value, '--repo-branch');
573
578
  parsed.repoBranches.set(id, defaultBranch);
@@ -1461,6 +1466,11 @@ function writeWarnings(io, warnings = []) {
1461
1466
  function splitAssignment(value, flagName) {
1462
1467
  const separatorIndex = value.indexOf('=');
1463
1468
  if (separatorIndex <= 0 || separatorIndex === value.length - 1) {
1469
+ if (flagName === '--repo' && separatorIndex > 0 && separatorIndex === value.length - 1) {
1470
+ throw new Error(
1471
+ '--repo remote resolved to empty. For a non-Git folder, use --repo-local <id=path> instead of --repo <id=remote>.',
1472
+ );
1473
+ }
1464
1474
  throw new Error(`${flagName} expects id=value.`);
1465
1475
  }
1466
1476
 
@@ -1495,7 +1505,8 @@ function usageText() {
1495
1505
  ' --placement <workspace-root|dedicated-memory-repo|primary-repo>',
1496
1506
  ' Optional explicit placement pattern',
1497
1507
  ' --guided Ask placement and setup questions interactively',
1498
- ' --repo <id=remote> Repeatable repo descriptor',
1508
+ ' --repo <id=remote> Repeatable Git-backed repo descriptor',
1509
+ ' --repo-local <id=path> Repeatable local folder source for non-Git projects',
1499
1510
  ' --repo-branch <id=branch> Optional per-repo default branch',
1500
1511
  ' --sync-api-url <url> Optional hosted sync api_url',
1501
1512
  ' --sync-project-id <id> Optional hosted sync project_id',
@@ -7,7 +7,7 @@ import { writeStateManifest } from './manifest.js';
7
7
  import { parseSimpleYaml } from './simple-yaml.js';
8
8
  import { readSyncCursor, resolveSyncBinding } from './sync-binding.js';
9
9
 
10
- const DOCS_REVIEW_PROMPT_VERSION = 'VibeCompass Docs Review Prompt v2';
10
+ const DOCS_REVIEW_PROMPT_VERSION = 'VibeCompass Docs Review Prompt v3';
11
11
  const ARCHITECTURE_DOC_SOFT_SIZE_LIMIT_BYTES = 12000;
12
12
  const COVERAGE_PLAN_OUTPUT_VERSION = 1;
13
13
  const COVERAGE_PLAN_STATUSES = new Set(['accepted', 'deferred', 'missing']);
@@ -785,13 +785,13 @@ function extractAnthropicText(body) {
785
785
 
786
786
  function parseArchitectureDocBlocks(source) {
787
787
  const blocks = [];
788
- const pattern = /^```vibecompass-architecture-doc\s+path=([^\s`]+)\s*\n([\s\S]*?)^```[ \t]*$/gm;
788
+ const pattern = /^(`{3,})vibecompass-architecture-doc\s+path=([^\s`]+)\s*\n([\s\S]*?)^\1[ \t]*$/gm;
789
789
  let match;
790
790
 
791
791
  while ((match = pattern.exec(source)) !== null) {
792
792
  blocks.push({
793
- path: normalizeBlockPath(match[1]),
794
- content: match[2].replace(/\n$/, ''),
793
+ path: normalizeBlockPath(match[2]),
794
+ content: match[3].replace(/\n$/, ''),
795
795
  });
796
796
  }
797
797
 
@@ -829,8 +829,8 @@ function parseDecisionRecommendationBlocks(source) {
829
829
  }
830
830
 
831
831
  function countMalformedArchitectureDocFences(source) {
832
- const fencePattern = /^```vibecompass-architecture-doc\b.*$/gm;
833
- const acceptedOpeningPattern = /^```vibecompass-architecture-doc\s+path=[^\s`]+\s*$/;
832
+ const fencePattern = /^`{3,}vibecompass-architecture-doc\b.*$/gm;
833
+ const acceptedOpeningPattern = /^`{3,}vibecompass-architecture-doc\s+path=[^\s`]+\s*$/;
834
834
  let count = 0;
835
835
  let match;
836
836
 
@@ -1705,18 +1705,20 @@ function renderReviewPrompt(options) {
1705
1705
  'Stage 1 — Evidence inventory:',
1706
1706
  '- Build a compact repo inventory from file paths, manifests/config files, route/job/test directories, and existing architecture frontmatter before reading large file bodies.',
1707
1707
  '- Mine finalized session notes for decision candidates and product constraints, but cap proposed decisions to the five highest-value architecture choices.',
1708
- '- Identify candidate domains, features, components, and ownership boundaries with concrete `repo:path` evidence.',
1708
+ '- Identify candidate domains, features, components, ownership boundaries, user journey entry points, feature-to-feature relationships, and system-layer connections with concrete `repo:path` evidence.',
1709
1709
  '- Do not fetch or summarize broad source bodies until the coverage plan says a file is needed.',
1710
1710
  '',
1711
1711
  'Stage 2 — Coverage plan:',
1712
1712
  '- Propose the smallest useful architecture-doc set that will let future agents understand the project and retrieve targeted context.',
1713
- '- Prioritize entry points, data ownership, external integrations, jobs/async boundaries, auth/security boundaries, and test surfaces.',
1713
+ '- The minimum useful set must cover: user journey, project/system map (frontend/backend/API/data/integration structure and connections), and summaries of the core journey-facing features.',
1714
+ '- Prioritize entry points, user-flow/gating relationships, data ownership, external integrations, jobs/async boundaries, auth/security boundaries, and test surfaces.',
1714
1715
  '- Mark each proposed doc as `comprehensive`, `partial`, or `initial`, with the reason and blindspots.',
1715
1716
  '- Emit the accepted plan as one `vibecompass-coverage-plan version=1` JSON fence before architecture-doc blocks.',
1716
1717
  '- Ask for user acceptance before emitting fenced architecture-doc blocks.',
1717
1718
  '',
1718
1719
  'Stage 3 — Bounded doc generation:',
1719
1720
  '- Generate only accepted docs, one complete fenced block per architecture path.',
1721
+ '- Ensure `architecture/overview/project-shape.md` includes a concise system map plus one `vibecompass-project-map version=1` JSON fence that lists journey-facing features and supported relationships.',
1720
1722
  '- Keep docs concise and retrieval-oriented: explain contracts, flows, invariants, and ownership; do not rewrite source code or produce file-by-file walkthroughs.',
1721
1723
  `- 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.`,
1722
1724
  '- Include only the most important involved files; prefer representative entry points and owned contracts over exhaustive file lists.',
@@ -1746,18 +1748,46 @@ function renderReviewPrompt(options) {
1746
1748
  '',
1747
1749
  '## Review Rules',
1748
1750
  '1. Do not delete `architecture/overview/project-shape.md`.',
1749
- '2. Add evidence-backed component docs alongside the overview.',
1750
- '3. Update `architecture/overview/project-shape.md` coverage and blindspot sections to summarize what has now been mapped.',
1751
- '4. Keep all implementation claims source-backed with `repo:path` evidence.',
1752
- '5. Use only the exact confidence and coverage enum values listed above.',
1753
- '6. Put uncertainty in `Blindspots`; do not fill gaps with guesses.',
1754
- '7. Do not append real `D-NNN` decisions without explicit user acceptance. Propose candidate decisions separately.',
1755
- '8. Do not edit `decisions/INDEX.md` directly unless a canonical decision file was explicitly accepted and appended.',
1756
- '9. Optimize for future retrieval: project-level docs stay compact; component docs carry focused context for a specific area.',
1751
+ '2. Add or update `architecture/overview/project-shape.md` so it explains the project/system map and includes the accepted `vibecompass-project-map version=1` block.',
1752
+ '3. Add evidence-backed component docs alongside the overview for core journey-facing features and important supporting systems.',
1753
+ '4. Update `architecture/overview/project-shape.md` coverage and blindspot sections to summarize what has now been mapped.',
1754
+ '5. Keep all implementation claims source-backed with `repo:path` evidence.',
1755
+ '6. Use only the exact confidence and coverage enum values listed above.',
1756
+ '7. Put uncertainty in `Blindspots`; do not fill gaps with guesses.',
1757
+ '8. Do not append real `D-NNN` decisions without explicit user acceptance. Propose candidate decisions separately.',
1758
+ '9. Do not edit `decisions/INDEX.md` directly unless a canonical decision file was explicitly accepted and appended.',
1759
+ '10. Optimize for future retrieval: project-level docs stay compact; component docs carry focused context for a specific area.',
1760
+ '',
1761
+ '## Project Map Block',
1762
+ 'Include exactly one project-map block inside `architecture/overview/project-shape.md` when the user accepts journey/system mapping output:',
1763
+ '',
1764
+ '```vibecompass-project-map version=1',
1765
+ '{',
1766
+ ' "features": [',
1767
+ ' {',
1768
+ ' "domain": "Domain name matching architecture frontmatter",',
1769
+ ' "feature": "Feature name matching architecture frontmatter",',
1770
+ ' "is_entry_point": true,',
1771
+ ' "summary": "Short user-facing feature summary"',
1772
+ ' }',
1773
+ ' ],',
1774
+ ' "relationships": [',
1775
+ ' {',
1776
+ ' "from": { "domain": "Domain", "feature": "Feature" },',
1777
+ ' "to": { "domain": "Domain", "feature": "Feature" },',
1778
+ ' "kind": "gates | navigates_to | depends_on | writes_to",',
1779
+ ' "label": "Short evidence-backed relationship label"',
1780
+ ' }',
1781
+ ' ]',
1782
+ '}',
1783
+ '```',
1784
+ '',
1785
+ 'Only include relationships supported by evidence. Prefer `navigates_to` and `gates` for the main user journey; use `depends_on` and `writes_to` for supporting system relationships. If useful journey links cannot be inferred, state that as a coverage gap rather than inventing links.',
1757
1786
  '',
1758
1787
  '## Output Contract',
1759
1788
  'First provide a concise findings summary with:',
1760
1789
  '- mapped areas',
1790
+ '- user journey and project/system map coverage',
1761
1791
  '- gaps/blindspots',
1762
1792
  '- evidence inventory summary',
1763
1793
  '- coverage plan and proposed architecture docs',
@@ -1791,6 +1821,8 @@ function renderReviewPrompt(options) {
1791
1821
  '<complete markdown file content>',
1792
1822
  '```',
1793
1823
  '',
1824
+ 'If the complete markdown file content contains its own fenced block, such as `vibecompass-project-map version=1`, use a longer outer fence for the architecture-doc block (for example four backticks) so the inner fence stays inside the document body.',
1825
+ '',
1794
1826
  'If the review surfaced accepted decision candidates, output each candidate as a separate block without assigning a D-number:',
1795
1827
  '',
1796
1828
  '```vibecompass-decision-recommendation target=decisions/cross-cutting.md',
package/src/init.js CHANGED
@@ -257,13 +257,42 @@ function normalizeInitOptions(options) {
257
257
  }
258
258
  seenRepoIds.add(repo.id);
259
259
 
260
- if (typeof repo.remote !== 'string' || repo.remote.trim() === '') {
261
- throw new Error(`repo "${repo.id}" requires a non-empty remote.`);
260
+ const source = typeof repo.source === 'string' && repo.source.trim() !== ''
261
+ ? repo.source.trim()
262
+ : null;
263
+ const pathValue = typeof repo.path === 'string' && repo.path.trim() !== ''
264
+ ? repo.path.trim()
265
+ : null;
266
+ const remote = typeof repo.remote === 'string' ? repo.remote.trim() : '';
267
+
268
+ if (source && !['git', 'local'].includes(source)) {
269
+ throw new Error(`repo "${repo.id}" source must be git or local.`);
270
+ }
271
+
272
+ if (source === 'local' || (!source && !remote && pathValue)) {
273
+ if (!['local-only', 'local-primary'].includes(preparedOptions.mode)) {
274
+ throw new Error(`repo "${repo.id}" local sources are supported only in local-only or local-primary mode.`);
275
+ }
276
+
277
+ if (!pathValue) {
278
+ throw new Error(`repo "${repo.id}" source local requires a non-empty path.`);
279
+ }
280
+
281
+ return {
282
+ id: repo.id,
283
+ source: 'local',
284
+ path: pathValue,
285
+ };
286
+ }
287
+
288
+ if (!remote) {
289
+ throw new Error(`repo "${repo.id}" requires a non-empty remote, or use a local repo source with source: local and path.`);
262
290
  }
263
291
 
264
292
  return {
265
293
  id: repo.id,
266
- remote: repo.remote,
294
+ ...(source === 'git' ? { source: 'git' } : {}),
295
+ remote,
267
296
  ...(repo.defaultBranch ? { default_branch: repo.defaultBranch } : {}),
268
297
  };
269
298
  });
@@ -34,7 +34,7 @@ const KNOWN_PROJECT_FIELDS = new Set([
34
34
  'sync',
35
35
  'metadata',
36
36
  ]);
37
- const KNOWN_REPO_FIELDS = new Set(['id', 'remote', 'default_branch']);
37
+ const KNOWN_REPO_FIELDS = new Set(['id', 'source', 'remote', 'path', 'default_branch']);
38
38
  const KNOWN_SYNC_FIELDS = new Set([
39
39
  'provider',
40
40
  'api_url',
@@ -278,8 +278,25 @@ function validateProjectData(data, relativePath) {
278
278
  repoIds.push(repo.id);
279
279
  }
280
280
 
281
- if (typeof repo.remote !== 'string' || repo.remote.trim() === '') {
282
- errors.push(createError(relativePath, 'project-invalid-repo-remote', `${prefix}.remote must be a non-empty string.`));
281
+ const source = typeof repo.source === 'string' && repo.source.trim() !== ''
282
+ ? repo.source.trim()
283
+ : null;
284
+ const remote = typeof repo.remote === 'string' ? repo.remote.trim() : '';
285
+ const sourcePath = typeof repo.path === 'string' ? repo.path.trim() : '';
286
+
287
+ if (source && !['git', 'local'].includes(source)) {
288
+ errors.push(createError(relativePath, 'project-invalid-repo-source', `${prefix}.source must be git or local.`));
289
+ }
290
+
291
+ if (source === 'local' || (!source && !remote && sourcePath)) {
292
+ if (!['local-only', 'local-primary'].includes(data.mode)) {
293
+ errors.push(createError(relativePath, 'project-invalid-repo-source', `${prefix}.source local is supported only when mode is local-only or local-primary.`));
294
+ }
295
+ if (!sourcePath) {
296
+ errors.push(createError(relativePath, 'project-invalid-repo-path', `${prefix}.path must be a non-empty string for local sources.`));
297
+ }
298
+ } else if (!remote) {
299
+ errors.push(createError(relativePath, 'project-invalid-repo-remote', `${prefix}.remote must be a non-empty string for Git-backed sources.`));
283
300
  }
284
301
  }
285
302
  }
@@ -336,10 +353,12 @@ function validateProjectData(data, relativePath) {
336
353
  repo_ids: repoIds,
337
354
  repos: Array.isArray(data.repos)
338
355
  ? data.repos
339
- .filter((repo) => isPlainObject(repo) && typeof repo.id === 'string' && typeof repo.remote === 'string')
356
+ .filter((repo) => isPlainObject(repo) && typeof repo.id === 'string')
340
357
  .map((repo) => ({
341
358
  id: repo.id,
342
- remote: repo.remote,
359
+ source: typeof repo.source === 'string' ? repo.source : (typeof repo.remote === 'string' ? 'git' : 'local'),
360
+ remote: typeof repo.remote === 'string' ? repo.remote : null,
361
+ path: typeof repo.path === 'string' ? repo.path : null,
343
362
  default_branch: typeof repo.default_branch === 'string' ? repo.default_branch : null,
344
363
  }))
345
364
  : [],
package/src/read-model.js CHANGED
@@ -105,7 +105,9 @@ function buildProjectSummary(scanResult, currentManifest, freshness, existingMan
105
105
  const extracted = scanResult.project.extracted ?? {};
106
106
  const repos = (extracted.repos ?? []).map((repo) => ({
107
107
  id: repo.id,
108
+ source: repo.source,
108
109
  remote: repo.remote,
110
+ path: repo.path,
109
111
  default_branch: repo.default_branch,
110
112
  }));
111
113
 
@@ -451,10 +453,12 @@ function buildRepoAliasMap(repos) {
451
453
  aliases.set(repo.id, repo.id);
452
454
  aliases.set(repo.id.toLowerCase(), repo.id);
453
455
 
454
- const remoteName = repo.remote
455
- .replace(/\.git$/, '')
456
- .split('/')
457
- .pop();
456
+ const remoteName = typeof repo.remote === 'string'
457
+ ? repo.remote
458
+ .replace(/\.git$/, '')
459
+ .split('/')
460
+ .pop()
461
+ : null;
458
462
 
459
463
  if (remoteName) {
460
464
  aliases.set(remoteName, repo.id);
package/src/scaffold.js CHANGED
@@ -206,7 +206,7 @@ function generateContextMarkdown(options) {
206
206
  const workflow = resolveWorkflowSettings(options.projectConfig);
207
207
  const promptCommands = renderPromptCommandLines({ rootRelativePath }).join('\n');
208
208
  const repos = options.projectConfig.repos
209
- .map((repo) => `- \`${repo.id}\` → ${repo.remote}`)
209
+ .map((repo) => `- \`${repo.id}\` → ${formatRepoDescriptor(repo)}`)
210
210
  .join('\n');
211
211
 
212
212
  return `# Project Context — ${projectName}
@@ -348,7 +348,7 @@ automatically by package commands.
348
348
  function generateStarterArchitectureDoc(projectConfig) {
349
349
  const repos = projectConfig.repos.map((repo) => repo.id);
350
350
  const repoLines = projectConfig.repos
351
- .map((repo) => `- \`${repo.id}\` — ${repo.remote}${repo.default_branch ? ` (${repo.default_branch})` : ''}`)
351
+ .map((repo) => `- \`${repo.id}\` — ${formatRepoDescriptor(repo)}${repo.default_branch ? ` (${repo.default_branch})` : ''}`)
352
352
  .join('\n');
353
353
  const repoEvidence = projectConfig.repos
354
354
  .map((repo) => `- \`${repo.id}:/\` — declared repository root`)
@@ -379,7 +379,7 @@ ${repoLines}
379
379
  ## Coverage
380
380
  Confirmed:
381
381
  - Project identity and mode from \`project.yaml\`
382
- - Declared repository IDs and remotes from \`project.yaml\`
382
+ - Declared repository IDs and source descriptors from \`project.yaml\`
383
383
  - Project-memory root layout created by \`vibecompass init\`
384
384
 
385
385
  Not yet documented:
@@ -425,7 +425,7 @@ Do not copy this example as-is. Allocate real decision IDs from the current cano
425
425
  function generateStarterSessionNote(options) {
426
426
  const sessionDate = sessionDateFromGeneratedAt(options.generatedAt);
427
427
  const projectConfig = options.projectConfig;
428
- const repoLines = projectConfig.repos.map((repo) => `- \`${repo.id}\` — ${repo.remote}`).join('\n');
428
+ const repoLines = projectConfig.repos.map((repo) => `- \`${repo.id}\` — ${formatRepoDescriptor(repo)}`).join('\n');
429
429
 
430
430
  return `# Session — ${sessionDate}-1 — Project Memory Initialized
431
431
 
@@ -458,6 +458,14 @@ ${repoLines}
458
458
  `;
459
459
  }
460
460
 
461
+ function formatRepoDescriptor(repo) {
462
+ if (repo.source === 'local') {
463
+ return `local folder ${repo.path}`;
464
+ }
465
+
466
+ return repo.remote;
467
+ }
468
+
461
469
  function generateArchitectureGuide(projectConfig) {
462
470
  return `# Architecture
463
471
 
package/src/setup.js CHANGED
@@ -882,12 +882,13 @@ async function promptForRepos(prompter, cwd) {
882
882
 
883
883
  for (let index = 0; index < repoCount; index += 1) {
884
884
  const ordinal = index + 1;
885
- const repo = {
886
- id: await askInput(prompter, `Repo ${ordinal} id`, {
887
- defaultValue: repoCount === 1 ? repoIdDefault : `repo-${ordinal}`,
888
- }),
889
- remote: await askInput(prompter, `Repo ${ordinal} remote`),
890
- };
885
+ const repoId = await askInput(prompter, `Repo ${ordinal} id`, {
886
+ defaultValue: repoCount === 1 ? repoIdDefault : `repo-${ordinal}`,
887
+ });
888
+ const remote = await askOptionalInput(prompter, `Repo ${ordinal} remote (blank for local folder)`);
889
+ const repo = remote
890
+ ? { id: repoId, remote }
891
+ : { id: repoId, source: 'local', path: '.' };
891
892
 
892
893
  const defaultBranch = await askOptionalInput(prompter, `Repo ${ordinal} default branch`);
893
894
  if (defaultBranch) {
package/src/status.js CHANGED
@@ -143,7 +143,9 @@ async function readProjectSummary(projectFilePath) {
143
143
  .filter((repo) => repo && typeof repo === 'object')
144
144
  .map((repo) => ({
145
145
  id: typeof repo.id === 'string' ? repo.id : null,
146
+ source: typeof repo.source === 'string' ? repo.source : (typeof repo.remote === 'string' ? 'git' : 'local'),
146
147
  remote: typeof repo.remote === 'string' ? repo.remote : null,
148
+ path: typeof repo.path === 'string' ? repo.path : null,
147
149
  defaultBranch: typeof repo.default_branch === 'string' ? repo.default_branch : null,
148
150
  }))
149
151
  .filter((repo) => repo.id)
@@ -99,7 +99,7 @@ When the user says \`docs review\`, run this workflow inside the current Claude
99
99
 
100
100
  ## Goal
101
101
 
102
- Turn starter project memory into evidence-backed architecture docs under \`architecture/<domain>/<feature>/<component>.md\`, a projected coverage plan, and optional accepted decision recommendations.
102
+ Turn starter project memory into evidence-backed architecture docs under \`architecture/<domain>/<feature>/<component>.md\`, a projected coverage plan, a journey-aware project map, and optional accepted decision recommendations.
103
103
 
104
104
  ## Steps
105
105
 
@@ -109,8 +109,8 @@ Turn starter project memory into evidence-backed architecture docs under \`archi
109
109
  - produce a coverage plan before reading broad source bodies
110
110
  - read targeted source files only when the coverage plan needs evidence
111
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, token-budget risks, and any decision candidates before generating accepted output.
113
- 5. Draft only output the user accepts. The accepted plan must be fenced as \`vibecompass-coverage-plan version=1\`. Accepted architecture docs must be fenced as \`vibecompass-architecture-doc path=architecture/domain/feature/component.md\` blocks and must include required frontmatter: \`domain\`, \`feature\`, \`component\`, and \`status\`. Accepted local decisions may be fenced as \`vibecompass-decision-recommendation target=decisions/domain.md\` blocks without D-numbers.
112
+ 4. Present the evidence inventory, coverage plan, user journey, project/system map, proposed architecture docs, blindspots, token-budget risks, and any decision candidates before generating accepted output.
113
+ 5. Draft only output the user accepts. The accepted plan must be fenced as \`vibecompass-coverage-plan version=1\`. Accepted architecture docs must be fenced as \`vibecompass-architecture-doc path=architecture/domain/feature/component.md\` blocks and must include required frontmatter: \`domain\`, \`feature\`, \`component\`, and \`status\`. The accepted \`architecture/overview/project-shape.md\` doc should include exactly one \`vibecompass-project-map version=1\` JSON block with journey-facing features, entry points, and evidence-backed relationships. Accepted local decisions may be fenced as \`vibecompass-decision-recommendation target=decisions/domain.md\` blocks without D-numbers.
114
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
115
  7. Write the accepted fenced blocks to \`${outputPath}\`.
116
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.