@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 +8 -0
- package/README.md +9 -0
- package/package.json +1 -1
- package/src/cli.js +12 -1
- package/src/docs-review.js +48 -16
- package/src/init.js +32 -3
- package/src/project-memory.js +24 -5
- package/src/read-model.js +8 -4
- package/src/scaffold.js +12 -4
- package/src/setup.js +7 -6
- package/src/status.js +2 -0
- package/src/workflows/registry.js +3 -3
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
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',
|
package/src/docs-review.js
CHANGED
|
@@ -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
|
|
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 =
|
|
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[
|
|
794
|
-
content: match[
|
|
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 =
|
|
833
|
-
const acceptedOpeningPattern =
|
|
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,
|
|
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
|
-
'-
|
|
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
|
|
1750
|
-
'3.
|
|
1751
|
-
'4.
|
|
1752
|
-
'5.
|
|
1753
|
-
'6.
|
|
1754
|
-
'7.
|
|
1755
|
-
'8. Do not
|
|
1756
|
-
'9.
|
|
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
|
-
|
|
261
|
-
|
|
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
|
-
|
|
294
|
+
...(source === 'git' ? { source: 'git' } : {}),
|
|
295
|
+
remote,
|
|
267
296
|
...(repo.defaultBranch ? { default_branch: repo.defaultBranch } : {}),
|
|
268
297
|
};
|
|
269
298
|
});
|
package/src/project-memory.js
CHANGED
|
@@ -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
|
-
|
|
282
|
-
|
|
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'
|
|
356
|
+
.filter((repo) => isPlainObject(repo) && typeof repo.id === 'string')
|
|
340
357
|
.map((repo) => ({
|
|
341
358
|
id: repo.id,
|
|
342
|
-
|
|
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
|
-
.
|
|
456
|
-
|
|
457
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
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.
|