minimal-vibe-coding-kit 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/.agents/skills/agentshield-security-review/SKILL.md +6 -6
  2. package/.agents/skills/agentshield-security-review/references/native-install.md +10 -10
  3. package/.agents/skills/agentshield-security-review/references/report-template.md +1 -1
  4. package/.agents/skills/agentshield-security-review/scripts/agentshield_repo_probe.py +3 -3
  5. package/.agents/skills/autoresearch-coding/README.md +1 -1
  6. package/.agents/skills/autoresearch-coding/SKILL.md +4 -4
  7. package/.agents/skills/daily-workflow-curator/SKILL.md +3 -3
  8. package/.agents/skills/parallel-analysis/SKILL.md +160 -0
  9. package/.agents/skills/path-sensitive-shell-safety/SKILL.md +68 -0
  10. package/.agents/skills/path-sensitive-shell-safety/references/workflow.md +127 -0
  11. package/.agents/skills/vibekit-init/SKILL.md +6 -6
  12. package/.claude/commands/vibe-finalize.md +1 -1
  13. package/.claude/rules/security.md +2 -0
  14. package/.claude/rules/tooling.md +1 -1
  15. package/.claude/skills/agentshield-security-review/SKILL.md +6 -6
  16. package/.claude/skills/agentshield-security-review/references/native-install.md +10 -10
  17. package/.claude/skills/agentshield-security-review/references/report-template.md +1 -1
  18. package/.claude/skills/agentshield-security-review/scripts/agentshield_repo_probe.py +3 -3
  19. package/.claude/skills/autoresearch-coding/README.md +1 -1
  20. package/.claude/skills/autoresearch-coding/SKILL.md +4 -4
  21. package/.claude/skills/daily-workflow-curator/SKILL.md +3 -3
  22. package/.claude/skills/parallel-analysis/SKILL.md +160 -0
  23. package/.claude/skills/path-sensitive-shell-safety/SKILL.md +68 -0
  24. package/.claude/skills/path-sensitive-shell-safety/references/workflow.md +127 -0
  25. package/.claude/skills/vibekit-init/SKILL.md +6 -6
  26. package/.codex-plugin/plugin.json +2 -2
  27. package/.cursor/commands/vibe-finalize.md +1 -1
  28. package/.cursor/rules/001-vibe-core.mdc +1 -1
  29. package/.cursor/rules/010-init.mdc +1 -1
  30. package/.cursor/rules/020-security-agentshield.mdc +2 -2
  31. package/.cursor/rules/030-autoresearch-loop.mdc +1 -1
  32. package/.cursor/skills/parallel-analysis/SKILL.md +160 -0
  33. package/.cursor/skills/path-sensitive-shell-safety/SKILL.md +68 -0
  34. package/.cursor/skills/path-sensitive-shell-safety/references/workflow.md +127 -0
  35. package/.vibekit/commands/vibe-finalize.md +3 -0
  36. package/{.vbkit-docs → .vibekit/docs}/AUTORESEARCH_LEDGER.md +3 -3
  37. package/{.vbkit-docs → .vibekit/docs}/BACKBONE_REFERENCE.md +1 -1
  38. package/{.vbkit-docs → .vibekit/docs}/INSTALL.md +16 -16
  39. package/{.vbkit-docs → .vibekit/docs}/RESEARCH_NOTES.md +1 -1
  40. package/{.vbkit-docs → .vibekit/docs}/SECURITY_MODEL.md +2 -2
  41. package/{.vbkit-docs → .vibekit/docs}/TOOLING_GUIDE.md +2 -2
  42. package/{.vbkit-docs → .vibekit/docs}/templates/CONTEXT_TEMPLATE.md +1 -1
  43. package/{.vbkit-docs → .vibekit/docs}/templates/PRD_TEMPLATE.md +1 -1
  44. package/{CLAUDE-template.md → .vibekit/init/CLAUDE-template.md} +1 -1
  45. package/{FIRST_PROMPT.md → .vibekit/init/FIRST_PROMPT.md} +6 -6
  46. package/{FIRST_TIME_INIT.md → .vibekit/init/FIRST_TIME_INIT.md} +14 -14
  47. package/{.vbkit-scripts → .vibekit/scripts}/agentshield-probe.mjs +1 -1
  48. package/{.vbkit-scripts → .vibekit/scripts}/daily-enhance.mjs +3 -3
  49. package/{.vbkit-scripts → .vibekit/scripts}/doctor.mjs +6 -6
  50. package/{.vbkit-scripts → .vibekit/scripts}/init-backbone.mjs +22 -22
  51. package/{.vbkit-scripts → .vibekit/scripts}/mvck.mjs +61 -25
  52. package/{.vbkit-scripts → .vibekit/scripts}/test-install.mjs +32 -18
  53. package/{.vbkit-scripts → .vibekit/scripts}/validate-kit.mjs +47 -31
  54. package/{.vbkit-scripts → .vibekit/scripts}/vibekit-finalize.mjs +7 -7
  55. package/{skills → .vibekit/skills}/agentshield-security-review/SKILL.md +6 -6
  56. package/{skills → .vibekit/skills}/agentshield-security-review/references/native-install.md +10 -10
  57. package/{skills → .vibekit/skills}/agentshield-security-review/references/report-template.md +1 -1
  58. package/{skills → .vibekit/skills}/agentshield-security-review/scripts/agentshield_repo_probe.py +3 -3
  59. package/{skills → .vibekit/skills}/autoresearch-coding/README.md +1 -1
  60. package/{skills → .vibekit/skills}/autoresearch-coding/SKILL.md +4 -4
  61. package/{skills → .vibekit/skills}/daily-workflow-curator/SKILL.md +3 -3
  62. package/.vibekit/skills/parallel-analysis/SKILL.md +160 -0
  63. package/.vibekit/skills/path-sensitive-shell-safety/SKILL.md +68 -0
  64. package/.vibekit/skills/path-sensitive-shell-safety/references/workflow.md +127 -0
  65. package/{skills → .vibekit/skills}/vibekit-init/SKILL.md +6 -6
  66. package/AGENTS.md +5 -2
  67. package/CHANGELOG.md +13 -2
  68. package/CONTRIBUTING.md +3 -3
  69. package/README.md +133 -394
  70. package/README.vi.md +135 -334
  71. package/backbone.yml +8 -7
  72. package/bin/mvck.js +1 -1
  73. package/bin/vibe-kit.js +1 -1
  74. package/install.ps1 +1 -1
  75. package/install.sh +5 -3
  76. package/package.json +22 -18
  77. package/.vbkit-commands/vibe-finalize.md +0 -3
  78. /package/{.vbkit-commands → .vibekit/commands}/autoresearch-coding.md +0 -0
  79. /package/{.vbkit-commands → .vibekit/commands}/council.md +0 -0
  80. /package/{.vbkit-commands → .vibekit/commands}/daily-enhance.md +0 -0
  81. /package/{.vbkit-commands → .vibekit/commands}/init-vibe.md +0 -0
  82. /package/{.vbkit-commands → .vibekit/commands}/security-scan.md +0 -0
  83. /package/{.vbkit-docs → .vibekit/docs}/backbone.schema.json +0 -0
  84. /package/{.vbkit-scripts → .vibekit/scripts}/pack-dry-run.mjs +0 -0
  85. /package/{skills → .vibekit/skills}/agentshield-security-review/agents/openai.yaml +0 -0
  86. /package/{skills → .vibekit/skills}/agentshield-security-review/references/review-checklist.md +0 -0
  87. /package/{skills → .vibekit/skills}/autoresearch-coding/references/experiment-contract.md +0 -0
  88. /package/{skills → .vibekit/skills}/autoresearch-coding/references/metric-extraction.md +0 -0
  89. /package/{skills → .vibekit/skills}/autoresearch-coding/references/result-ledger.md +0 -0
  90. /package/{skills → .vibekit/skills}/autoresearch-coding/scripts/log_result.py +0 -0
  91. /package/{skills → .vibekit/skills}/autoresearch-coding/scripts/run_logged.py +0 -0
  92. /package/{skills → .vibekit/skills}/clearthought/SKILL.md +0 -0
  93. /package/{skills → .vibekit/skills}/clearthought/examples/decision-framework.md +0 -0
  94. /package/{skills → .vibekit/skills}/clearthought/examples/metagame-examples.md +0 -0
  95. /package/{skills → .vibekit/skills}/clearthought/examples/sequential-thinking.md +0 -0
  96. /package/{skills → .vibekit/skills}/clearthought/references/output-schemas.md +0 -0
  97. /package/{skills → .vibekit/skills}/clearthought/references/parameter-reference.md +0 -0
  98. /package/{skills → .vibekit/skills}/coding-level/SKILL.md +0 -0
  99. /package/{skills → .vibekit/skills}/coding-level/references/level-0.md +0 -0
  100. /package/{skills → .vibekit/skills}/coding-level/references/level-1.md +0 -0
  101. /package/{skills → .vibekit/skills}/coding-level/references/level-2.md +0 -0
  102. /package/{skills → .vibekit/skills}/coding-level/references/level-3.md +0 -0
  103. /package/{skills → .vibekit/skills}/coding-level/references/level-4.md +0 -0
  104. /package/{skills → .vibekit/skills}/coding-level/references/level-5.md +0 -0
  105. /package/{skills → .vibekit/skills}/memento/SKILL.md +0 -0
  106. /package/{skills → .vibekit/skills}/reviewing-4p-priorities/SKILL.md +0 -0
  107. /package/{skills → .vibekit/skills}/reviewing-4p-priorities/examples.md +0 -0
  108. /package/{skills → .vibekit/skills}/sequential-thinking/SKILL.md +0 -0
  109. /package/{skills → .vibekit/skills}/sequential-thinking/examples/adaptive-depth.md +0 -0
  110. /package/{skills → .vibekit/skills}/sequential-thinking/examples/branching-exploration.md +0 -0
  111. /package/{skills → .vibekit/skills}/sequential-thinking/examples/linear-reasoning.md +0 -0
  112. /package/{skills → .vibekit/skills}/sequential-thinking/examples/revision-pattern.md +0 -0
  113. /package/{skills → .vibekit/skills}/sequential-thinking/references/output-schema.md +0 -0
  114. /package/{skills → .vibekit/skills}/sequential-thinking/references/parameters.md +0 -0
  115. /package/{skills → .vibekit/skills}/sequential-thinking/references/patterns.md +0 -0
  116. /package/{skills → .vibekit/skills}/visual-design-loop/SKILL.md +0 -0
  117. /package/{skills → .vibekit/skills}/visual-design-loop/agents/openai.yaml +0 -0
@@ -1,8 +1,8 @@
1
- # FIRST_TIME_INIT.md - bootstrap runbook
1
+ # .vibekit/init/FIRST_TIME_INIT.md - bootstrap runbook
2
2
 
3
3
  Audience: Claude, Cursor, Codex, or any AI coding agent in a repo that just received Minimal Vibe Coding Kit.
4
4
 
5
- Keep this flow short. Detailed schema notes live in `.vbkit-docs/BACKBONE_REFERENCE.md`.
5
+ Keep this flow short. Detailed schema notes live in `.vibekit/docs/BACKBONE_REFERENCE.md`.
6
6
 
7
7
  ## Requirements to print before starting
8
8
 
@@ -10,17 +10,17 @@ Before writing anything, print this checklist and mark each item as found, missi
10
10
 
11
11
  1. `backbone.yml` exists.
12
12
  2. `AGENTS.md` exists or will be created/merged.
13
- 3. `CLAUDE.md` exists or will be created from `CLAUDE-template.md` when Claude support is installed.
13
+ 3. `CLAUDE.md` exists or will be created from `.vibekit/init/CLAUDE-template.md` when Claude support is installed.
14
14
  4. At least one harness folder exists: `.claude/`, `.cursor/`, `.agents/`, or `.codex-plugin/`.
15
15
  5. Git status is known. If user changes exist, do not overwrite them.
16
- 6. A validation command is inferred or set to `node .vbkit-scripts/validate-kit.mjs .` for the kit itself.
16
+ 6. A validation command is inferred or set to `node .vibekit/scripts/validate-kit.mjs .` for the kit itself.
17
17
  7. Protected paths include `.env*`, secrets, lockfiles, generated files, build output, migrations, and infra unless the user says otherwise.
18
18
  8. Existing naming, architecture, resource, and localization conventions are scanned or marked missing.
19
19
 
20
20
  ## Canonical prompt
21
21
 
22
22
  ```text
23
- Read FIRST_TIME_INIT.md and initialize this repo with Minimal Vibe Coding Kit.
23
+ Read .vibekit/init/FIRST_TIME_INIT.md and initialize this repo with Minimal Vibe Coding Kit.
24
24
  First print the requirements you will check. Then run detection, propose one diff for backbone.yml and managed instruction blocks, and wait for my yes before writing.
25
25
  Include inferred project conventions for naming, architecture, resources, localization, generated definitions, and per-app/package differences.
26
26
  After approval, write the files, run validation, and summarize what changed.
@@ -64,9 +64,9 @@ Ask (keep it short):
64
64
 
65
65
  Then:
66
66
 
67
- - If `project.prd` is `none`, propose creating `.vbkit-docs/PRD.md` from `.vbkit-docs/templates/PRD_TEMPLATE.md` using the answers, and set `project.prd` to that path in the same diff.
67
+ - If `project.prd` is `none`, propose creating `.vibekit/docs/PRD.md` from `.vibekit/docs/templates/PRD_TEMPLATE.md` using the answers, and set `project.prd` to that path in the same diff.
68
68
  - If a PRD already exists, read it, link it in `project.prd`, and offer to refresh it without overwriting unapproved content.
69
- - Record domain terms and acronyms in `.vbkit-docs/CONTEXT.md` (scaffold from `.vbkit-docs/templates/CONTEXT_TEMPLATE.md`) and link it in `project.context`, so future agents stay concise.
69
+ - Record domain terms and acronyms in `.vibekit/docs/CONTEXT.md` (scaffold from `.vibekit/docs/templates/CONTEXT_TEMPLATE.md`) and link it in `project.context`, so future agents stay concise.
70
70
  - Keep the PRD short: it captures intent and focus, not a full specification.
71
71
 
72
72
  ## FIRST_TIME_INIT_RULES
@@ -85,7 +85,7 @@ Create project rules from evidence in the existing repo, not from a fixed langua
85
85
  Optional helper:
86
86
 
87
87
  ```bash
88
- node .vbkit-scripts/init-backbone.mjs . --propose
88
+ node .vibekit/scripts/init-backbone.mjs . --propose
89
89
  ```
90
90
 
91
91
  ## Propose before writing
@@ -117,14 +117,14 @@ Apply this proposed backbone and convention rules? Reply yes, edit, or abort.
117
117
  CLI helper after approval:
118
118
 
119
119
  ```bash
120
- node .vbkit-scripts/init-backbone.mjs . --write --yes
120
+ node .vibekit/scripts/init-backbone.mjs . --write --yes
121
121
  ```
122
122
 
123
123
  ## Merge rules
124
124
 
125
125
  ### CLAUDE.md
126
126
 
127
- - If no `CLAUDE.md` exists, copy `CLAUDE-template.md` to `CLAUDE.md`.
127
+ - If no `CLAUDE.md` exists, copy `.vibekit/init/CLAUDE-template.md` to `CLAUDE.md`.
128
128
  - If `CLAUDE.md` exists, append or replace only this managed block:
129
129
 
130
130
  ```markdown
@@ -134,7 +134,7 @@ node .vbkit-scripts/init-backbone.mjs . --write --yes
134
134
  ## Minimal Vibe Coding Kit
135
135
 
136
136
  - Read `backbone.yml` before changing code.
137
- - If `meta.template_status` is `uninitialized`, follow `FIRST_TIME_INIT.md` and wait for approval before writing.
137
+ - If `meta.template_status` is `uninitialized`, follow `.vibekit/init/FIRST_TIME_INIT.md` and wait for approval before writing.
138
138
  - After init, follow `backbone.yml` `conventions` before adding new project patterns.
139
139
  - Prefer project skills for multi-step workflows: `/autoresearch-coding`, `/security-scan`, `/daily-enhance`.
140
140
  <!-- END: minimal-vibe-coding-kit -->
@@ -150,10 +150,10 @@ node .vbkit-scripts/init-backbone.mjs . --write --yes
150
150
 
151
151
  Once init is `initialized` and the first prompt is complete, the bootstrap files are no longer needed in the project. Offer to graduate them so the repo stays clean.
152
152
 
153
- - Preview: `node .vbkit-scripts/vibekit-finalize.mjs . --propose`
154
- - Apply after the user agrees: `node .vbkit-scripts/vibekit-finalize.mjs . --write --yes`
153
+ - Preview: `node .vibekit/scripts/vibekit-finalize.mjs . --propose`
154
+ - Apply after the user agrees: `node .vibekit/scripts/vibekit-finalize.mjs . --write --yes`
155
155
 
156
- This moves one-time files (`FIRST_TIME_INIT.md`, `FIRST_PROMPT.md`, `PUSH_TO_GITHUB.md`, `CLAUDE-template.md` once `CLAUDE.md` exists) into the folder named by `automation.finalize.cleanup_dir` (default `_vibekit-cleanup/`), writes a `RESTORE.md`, and sets `automation.finalize.marker`. It is idempotent, reversible with `--restore --write`, and refuses to run on the kit source repo. The durable project map is `backbone.yml`; none of the graduated files are needed to keep working. Delete the cleanup folder when satisfied.
156
+ This moves one-time files (`.vibekit/init/FIRST_TIME_INIT.md`, `.vibekit/init/FIRST_PROMPT.md`, `.vibekit/init/PUSH_TO_GITHUB.md`, `.vibekit/init/CLAUDE-template.md` once `CLAUDE.md` exists) into the folder named by `automation.finalize.cleanup_dir` (default `_vibekit-cleanup/`), writes a `RESTORE.md`, and sets `automation.finalize.marker`. It is idempotent, reversible with `--restore --write`, and refuses to run on the kit source repo. The durable project map is `backbone.yml`; none of the graduated files are needed to keep working. Delete the cleanup folder when satisfied.
157
157
 
158
158
  ## Guardrails
159
159
 
@@ -5,7 +5,7 @@ import { spawnSync } from 'node:child_process';
5
5
 
6
6
  const target = path.resolve(process.argv[2] || process.cwd());
7
7
  const extra = process.argv.slice(3);
8
- const probe = path.join(target, 'skills/agentshield-security-review/scripts/agentshield_repo_probe.py');
8
+ const probe = path.join(target, '.vibekit/skills/agentshield-security-review/scripts/agentshield_repo_probe.py');
9
9
 
10
10
  if (!fs.existsSync(probe)) {
11
11
  console.error(`AgentShield probe not found: ${path.relative(target, probe)}`);
@@ -25,17 +25,17 @@ function list(dir) {
25
25
  }
26
26
 
27
27
  const checks = [];
28
- for (const rel of ['backbone.yml', 'AGENTS.md', 'FIRST_TIME_INIT.md', 'skills/autoresearch-coding/SKILL.md', 'skills/agentshield-security-review/SKILL.md']) {
28
+ for (const rel of ['backbone.yml', 'AGENTS.md', '.vibekit/init/FIRST_TIME_INIT.md', '.vibekit/skills/autoresearch-coding/SKILL.md', '.vibekit/skills/agentshield-security-review/SKILL.md']) {
29
29
  checks.push(`- ${rel}: ${exists(rel) ? 'found' : 'missing'}`);
30
30
  }
31
31
 
32
- const skills = list('skills').filter((f) => f.endsWith('SKILL.md'));
32
+ const skills = list('.vibekit/skills').filter((f) => f.endsWith('SKILL.md'));
33
33
  const claudeSkills = list('.claude/skills').filter((f) => f.endsWith('SKILL.md'));
34
34
  const codexSkills = list('.agents/skills').filter((f) => f.endsWith('SKILL.md'));
35
35
  const cursorRules = list('.cursor/rules').filter((f) => f.endsWith('.mdc'));
36
36
 
37
37
  let validation = 'not run';
38
- const validator = path.join(target, '.vbkit-scripts/validate-kit.mjs');
38
+ const validator = path.join(target, '.vibekit/scripts/validate-kit.mjs');
39
39
  if (fs.existsSync(validator)) {
40
40
  const result = spawnSync(process.execPath, [validator, target], { encoding: 'utf8' });
41
41
  validation = result.stdout.trim() || result.stderr.trim() || `exit ${result.status}`;
@@ -122,7 +122,7 @@ function runNodeScript(rel, extra = []) {
122
122
  }
123
123
 
124
124
  function runProbe() {
125
- const nodeProbeRel = '.vbkit-scripts/agentshield-probe.mjs';
125
+ const nodeProbeRel = '.vibekit/scripts/agentshield-probe.mjs';
126
126
  const nodeProbe = path.join(target, nodeProbeRel);
127
127
  if (fs.existsSync(nodeProbe)) {
128
128
  const result = spawnSync(process.execPath, [nodeProbe, target, '--json'], { encoding: 'utf8' });
@@ -134,7 +134,7 @@ function runProbe() {
134
134
  };
135
135
  }
136
136
 
137
- const probe = path.join(target, 'skills/agentshield-security-review/scripts/agentshield_repo_probe.py');
137
+ const probe = path.join(target, '.vibekit/skills/agentshield-security-review/scripts/agentshield_repo_probe.py');
138
138
  if (!fs.existsSync(probe)) return { found: false, status: null, output: 'missing' };
139
139
  for (const python of ['python', 'python3']) {
140
140
  const result = spawnSync(python, [probe, target, '--json'], { encoding: 'utf8' });
@@ -161,7 +161,7 @@ const kitVersion = isKitTemplate
161
161
  : exists('.vibekit/KIT_VERSION') ? read('.vibekit/KIT_VERSION').trim() : 'unknown';
162
162
  const surfaces = {
163
163
  agents: exists('AGENTS.md'),
164
- claude: exists('CLAUDE.md') || exists('CLAUDE-template.md') || exists('.claude'),
164
+ claude: exists('CLAUDE.md') || exists('.vibekit/init/CLAUDE-template.md') || exists('.claude'),
165
165
  cursor: exists('.cursor/rules'),
166
166
  codex: exists('.agents') || exists('.codex-plugin/plugin.json')
167
167
  };
@@ -180,7 +180,7 @@ const legacySurfaces = [
180
180
  ].filter(exists);
181
181
  const nativeReasoningSkills = ['clearthought', 'sequential-thinking', 'reviewing-4p-priorities'];
182
182
  const nativeSkillSurfaces = {
183
- shared: 'skills',
183
+ shared: '.vibekit/skills',
184
184
  claude: '.claude/skills',
185
185
  codex: '.agents/skills',
186
186
  cursor: '.cursor/skills'
@@ -192,7 +192,7 @@ for (const [surface, dir] of Object.entries(nativeSkillSurfaces)) {
192
192
  }
193
193
  }
194
194
  const commands = commandMap();
195
- const validation = runNodeScript('.vbkit-scripts/validate-kit.mjs');
195
+ const validation = runNodeScript('.vibekit/scripts/validate-kit.mjs');
196
196
  const probe = runProbe();
197
197
  const risks = [];
198
198
 
@@ -239,7 +239,7 @@ const report = {
239
239
  status: probe.status
240
240
  },
241
241
  aiRulesLoaded: {
242
- sharedSkills: listFiles('skills').filter((f) => f.endsWith('SKILL.md')).length,
242
+ sharedSkills: listFiles('.vibekit/skills').filter((f) => f.endsWith('SKILL.md')).length,
243
243
  claudeSkills: listFiles('.claude/skills').filter((f) => f.endsWith('SKILL.md')).length,
244
244
  codexSkills: listFiles('.agents/skills').filter((f) => f.endsWith('SKILL.md')).length,
245
245
  cursorSkills: listFiles('.cursor/skills').filter((f) => f.endsWith('SKILL.md')).length,
@@ -92,22 +92,22 @@ function cleanName(name) {
92
92
  }
93
93
 
94
94
  function isKitManagedPath(file) {
95
- const managedRoots = new Set(['.claude', '.cursor', '.agents', '.codex', '.codex-plugin', 'skills', '.vbkit-commands', '.vbkit-docs', '.vbkit-scripts']);
95
+ const managedRoots = new Set(['.claude', '.cursor', '.agents', '.codex', '.codex-plugin', '.vibekit']);
96
96
  const managedFiles = new Set([
97
97
  'AGENTS.md',
98
- 'CLAUDE-template.md',
99
- 'FIRST_PROMPT.md',
100
- 'FIRST_TIME_INIT.md',
98
+ '.vibekit/init/CLAUDE-template.md',
99
+ '.vibekit/init/FIRST_PROMPT.md',
100
+ '.vibekit/init/FIRST_TIME_INIT.md',
101
101
  'backbone.yml',
102
- '.vbkit-scripts/mvck.mjs',
103
- '.vbkit-scripts/init-backbone.mjs',
104
- '.vbkit-scripts/daily-enhance.mjs',
105
- '.vbkit-scripts/validate-kit.mjs',
106
- '.vbkit-scripts/doctor.mjs',
107
- '.vbkit-scripts/test-install.mjs',
108
- '.vbkit-scripts/agentshield-probe.mjs',
109
- '.vbkit-scripts/pack-dry-run.mjs',
110
- '.vbkit-scripts/vibekit-finalize.mjs'
102
+ '.vibekit/scripts/mvck.mjs',
103
+ '.vibekit/scripts/init-backbone.mjs',
104
+ '.vibekit/scripts/daily-enhance.mjs',
105
+ '.vibekit/scripts/validate-kit.mjs',
106
+ '.vibekit/scripts/doctor.mjs',
107
+ '.vibekit/scripts/test-install.mjs',
108
+ '.vibekit/scripts/agentshield-probe.mjs',
109
+ '.vibekit/scripts/pack-dry-run.mjs',
110
+ '.vibekit/scripts/vibekit-finalize.mjs'
111
111
  ]);
112
112
  const root = file.split('/')[0];
113
113
  return managedRoots.has(root) || managedFiles.has(file);
@@ -514,10 +514,10 @@ function detectConventions(files, type) {
514
514
  }
515
515
 
516
516
  const PRD_CANDIDATES = [
517
- 'PRD.md', '.vbkit-docs/PRD.md', 'prd.md', '.vbkit-docs/prd.md',
518
- 'REQUIREMENTS.md', '.vbkit-docs/REQUIREMENTS.md',
519
- 'SPEC.md', '.vbkit-docs/SPEC.md', '.vbkit-docs/spec.md',
520
- 'PRODUCT.md', '.vbkit-docs/PRODUCT.md'
517
+ 'PRD.md', '.vibekit/docs/PRD.md', 'prd.md', '.vibekit/docs/prd.md',
518
+ 'REQUIREMENTS.md', '.vibekit/docs/REQUIREMENTS.md',
519
+ 'SPEC.md', '.vibekit/docs/SPEC.md', '.vibekit/docs/spec.md',
520
+ 'PRODUCT.md', '.vibekit/docs/PRODUCT.md'
521
521
  ];
522
522
 
523
523
  function countCodeFiles(files) {
@@ -538,7 +538,7 @@ function detectPrd(files) {
538
538
  }
539
539
 
540
540
  function detectContext() {
541
- for (const candidate of ['.vbkit-docs/CONTEXT.md', 'CONTEXT.md', '.vbkit-docs/context.md']) {
541
+ for (const candidate of ['.vibekit/docs/CONTEXT.md', 'CONTEXT.md', '.vibekit/docs/context.md']) {
542
542
  if (fileExists(candidate)) return candidate;
543
543
  }
544
544
  return 'none';
@@ -547,7 +547,7 @@ function detectContext() {
547
547
  function render(data) {
548
548
  const cmd = data.commands;
549
549
  const rules = data.conventions;
550
- return `# Minimal Vibe Coding Kit backbone. See .vbkit-docs/BACKBONE_REFERENCE.md for details.\nversion: 2\nmeta:\n template_status: initialized\n initialized_at: ${yamlString(data.initializedAt)}\n template_source: minimal-vibe-coding-kit\n schema_version: 3\n init_runbook: FIRST_TIME_INIT.md\n init_done_marker: .vibekit/INIT_DONE\n\nproject:\n name: ${yamlString(data.name)}\n description: ${yamlString(data.description)}\n type: ${data.type}\n primary_language: ${data.language}\n package_manager: ${data.packageManager}\n mode: ${data.mode}\n prd: ${yamlString(data.prd)}\n context: ${yamlString(data.context)}\n\npaths:\n root: .\n apps:${yamlList(data.appPaths, 4)}\n source: ${JSON.stringify(data.sourcePaths)}\n tests: ${JSON.stringify(data.testPaths)}\n docs: [README.md, .vbkit-docs/]\n generated: [node_modules/, dist/, build/, coverage/]\n\nconventions:\n review_required_before_write: true\n scope: ${yamlString(rules.scope)}\n naming:\n files: ${yamlString(rules.naming.files)}\n directories: ${yamlString(rules.naming.directories)}\n symbols: follow existing language and framework conventions in nearby code\n evidence:${yamlList(rules.naming.evidence, 6)}\n architecture:\n detected:${yamlList(rules.architecture.detected, 6)}\n rule: ${yamlString(rules.architecture.rule)}\n resources:\n detected_asset_roots:${yamlList(rules.resources.assetRoots, 6)}\n detected_registries:${yamlList(rules.resources.registries, 6)}\n rule: ${yamlString(rules.resources.rule)}\n localization:\n detected_catalogs:${yamlList(rules.localization.catalogs, 6)}\n detected_accessors:${yamlList(rules.localization.accessors, 6)}\n rule: ${yamlString(rules.localization.rule)}\n custom_rules:\n - Add team-specific rules here during init review; future agents must follow them.\n\ncommands:\n install: ${yamlString(cmd.install)}\n test: ${yamlString(cmd.test)}\n lint: ${yamlString(cmd.lint)}\n typecheck: ${yamlString(cmd.typecheck)}\n build: ${yamlString(cmd.build)}\n validate: ${yamlString(cmd.validate)}\n\npolicy:\n default_branch: main\n branch_naming: "feat/<short-topic>"\n commit_style: conventional\n editable_paths: [.]\n protected_paths:\n - .git/\n - .env*\n - "**/*secret*"\n - "**/*token*"\n - "**/migrations/**"\n - "**/node_modules/**"\n - "**/dist/**"\n - "**/build/**"\n - "**/coverage/**"\n - "**/*lock*"\n\nagent_surfaces:\n claude: .claude/\n cursor: .cursor/\n codex: .agents/\n codex_plugin: .codex-plugin/plugin.json\n shared_skills: skills/\n shared_commands: .vbkit-commands/\n\nautomation:\n autoresearch:\n results_file: results.tsv\n logs_dir: .autoresearch/logs\n default_budget: 3\n default_timeout_seconds: 600\n daily_enhance:\n report_dir: .vibekit/reports\n write_mode: propose_only\n finalize:\n cleanup_dir: _vibekit-cleanup\n marker: .vibekit/FINALIZE_DONE\n one_time_files: [FIRST_TIME_INIT.md, FIRST_PROMPT.md, PUSH_TO_GITHUB.md, CLAUDE-template.md]\n security:\n probe: node .vbkit-scripts/agentshield-probe.mjs .\n scan: npx ecc-agentshield scan --path . --format text --min-severity medium\n`;
550
+ return `# Minimal Vibe Coding Kit backbone. See .vibekit/docs/BACKBONE_REFERENCE.md for details.\nversion: 2\nmeta:\n template_status: initialized\n initialized_at: ${yamlString(data.initializedAt)}\n template_source: minimal-vibe-coding-kit\n schema_version: 3\n init_runbook: .vibekit/init/FIRST_TIME_INIT.md\n init_done_marker: .vibekit/INIT_DONE\n\nproject:\n name: ${yamlString(data.name)}\n description: ${yamlString(data.description)}\n type: ${data.type}\n primary_language: ${data.language}\n package_manager: ${data.packageManager}\n mode: ${data.mode}\n prd: ${yamlString(data.prd)}\n context: ${yamlString(data.context)}\n\npaths:\n root: .\n apps:${yamlList(data.appPaths, 4)}\n source: ${JSON.stringify(data.sourcePaths)}\n tests: ${JSON.stringify(data.testPaths)}\n docs: [README.md, .vibekit/docs/]\n generated: [node_modules/, dist/, build/, coverage/]\n\nconventions:\n review_required_before_write: true\n scope: ${yamlString(rules.scope)}\n naming:\n files: ${yamlString(rules.naming.files)}\n directories: ${yamlString(rules.naming.directories)}\n symbols: follow existing language and framework conventions in nearby code\n evidence:${yamlList(rules.naming.evidence, 6)}\n architecture:\n detected:${yamlList(rules.architecture.detected, 6)}\n rule: ${yamlString(rules.architecture.rule)}\n resources:\n detected_asset_roots:${yamlList(rules.resources.assetRoots, 6)}\n detected_registries:${yamlList(rules.resources.registries, 6)}\n rule: ${yamlString(rules.resources.rule)}\n localization:\n detected_catalogs:${yamlList(rules.localization.catalogs, 6)}\n detected_accessors:${yamlList(rules.localization.accessors, 6)}\n rule: ${yamlString(rules.localization.rule)}\n custom_rules:\n - Add team-specific rules here during init review; future agents must follow them.\n\ncommands:\n install: ${yamlString(cmd.install)}\n test: ${yamlString(cmd.test)}\n lint: ${yamlString(cmd.lint)}\n typecheck: ${yamlString(cmd.typecheck)}\n build: ${yamlString(cmd.build)}\n validate: ${yamlString(cmd.validate)}\n\npolicy:\n default_branch: main\n branch_naming: "feat/<short-topic>"\n commit_style: conventional\n editable_paths: [.]\n protected_paths:\n - .git/\n - .env*\n - "**/*secret*"\n - "**/*token*"\n - "**/migrations/**"\n - "**/node_modules/**"\n - "**/dist/**"\n - "**/build/**"\n - "**/coverage/**"\n - "**/*lock*"\n\nagent_surfaces:\n claude: .claude/\n cursor: .cursor/\n codex: .agents/\n codex_plugin: .codex-plugin/plugin.json\n shared_skills: .vibekit/skills/\n shared_commands: .vibekit/commands/\n\nautomation:\n autoresearch:\n results_file: results.tsv\n logs_dir: .autoresearch/logs\n default_budget: 3\n default_timeout_seconds: 600\n daily_enhance:\n report_dir: .vibekit/reports\n write_mode: propose_only\n finalize:\n cleanup_dir: _vibekit-cleanup\n marker: .vibekit/FINALIZE_DONE\n one_time_files: [.vibekit/init/FIRST_TIME_INIT.md, .vibekit/init/FIRST_PROMPT.md, .vibekit/init/PUSH_TO_GITHUB.md, .vibekit/init/CLAUDE-template.md]\n security:\n probe: node .vibekit/scripts/agentshield-probe.mjs .\n scan: npx ecc-agentshield scan --path . --format text --min-severity medium\n`;
551
551
  }
552
552
 
553
553
  function inferPaths(files) {
@@ -614,15 +614,15 @@ if (shouldWrite) {
614
614
  console.log('- What are the key constraints or non-goals?');
615
615
  if (inferred.mode === 'brownfield') console.log('- Which existing area should we focus on improving first?');
616
616
  console.log(inferred.prd === 'none'
617
- ? '- Offer to create .vbkit-docs/PRD.md from .vbkit-docs/templates/PRD_TEMPLATE.md using the answers.'
617
+ ? '- Offer to create .vibekit/docs/PRD.md from .vibekit/docs/templates/PRD_TEMPLATE.md using the answers.'
618
618
  : `- Offer to refresh ${inferred.prd} with the answers; do not overwrite without approval.`);
619
619
  console.log(inferred.context === 'none'
620
- ? '- Offer to create .vbkit-docs/CONTEXT.md (glossary) from .vbkit-docs/templates/CONTEXT_TEMPLATE.md.'
620
+ ? '- Offer to create .vibekit/docs/CONTEXT.md (glossary) from .vibekit/docs/templates/CONTEXT_TEMPLATE.md.'
621
621
  : `- CONTEXT glossary found at ${inferred.context}; keep it current.`);
622
622
  console.log('\nConvention review questions:');
623
623
  for (const question of inferred.conventions.reviewQuestions) console.log(`- ${question}`);
624
624
  console.log('\nProposed backbone.yml:\n');
625
625
  console.log(out);
626
626
  console.log('Apply this proposed backbone and convention rules? Reply yes, edit, or abort.');
627
- console.log('To write it after approval, run: node .vbkit-scripts/init-backbone.mjs . --write --yes');
627
+ console.log('To write it after approval, run: node .vibekit/scripts/init-backbone.mjs . --write --yes');
628
628
  }
@@ -6,7 +6,7 @@ import { spawnSync } from 'node:child_process';
6
6
 
7
7
  const __filename = fileURLToPath(import.meta.url);
8
8
  const __dirname = path.dirname(__filename);
9
- const kitRoot = path.resolve(__dirname, '..');
9
+ const kitRoot = path.resolve(__dirname, '..', '..');
10
10
  const args = process.argv.slice(2);
11
11
 
12
12
  function usage() {
@@ -22,12 +22,12 @@ Usage:
22
22
  mvck finalize [target] [--write --yes] [--restore] [--json]
23
23
 
24
24
  Examples:
25
- node .vbkit-scripts/mvck.mjs install ~/work/my-repo --profile all
25
+ node .vibekit/scripts/mvck.mjs install ~/work/my-repo --profile all
26
26
  npx --yes minimal-vibe-coding-kit@latest update .
27
- node .vbkit-scripts/mvck.mjs init . --propose
28
- node .vbkit-scripts/mvck.mjs doctor .
29
- node .vbkit-scripts/mvck.mjs validate .
30
- node .vbkit-scripts/mvck.mjs finalize .
27
+ node .vibekit/scripts/mvck.mjs init . --propose
28
+ node .vibekit/scripts/mvck.mjs doctor .
29
+ node .vibekit/scripts/mvck.mjs validate .
30
+ node .vibekit/scripts/mvck.mjs finalize .
31
31
 
32
32
  update refreshes kit-owned files (skills, commands, rules, scripts, docs, agent
33
33
  mirrors) to the running kit version. It never overwrites user-owned files
@@ -98,13 +98,14 @@ function copyFileSafe(srcRel, destRel, target, { force = false, dryRun = false }
98
98
  return { action: fs.existsSync(dest) && force ? 'replace' : 'copy', path: destRel ?? srcRel };
99
99
  }
100
100
 
101
- function copyDirSafe(srcRel, destRel, target, { force = false, dryRun = false } = {}) {
101
+ function copyDirSafe(srcRel, destRel, target, { force = false, dryRun = false, exclude = [] } = {}) {
102
102
  const src = path.join(kitRoot, srcRel);
103
103
  const destRoot = path.join(target, destRel ?? srcRel);
104
104
  if (!fs.existsSync(src)) throw new Error(`Missing source dir: ${srcRel}`);
105
105
  let copied = 0;
106
106
  let skipped = 0;
107
107
  function copyRecursive(from, to) {
108
+ if (exclude.includes(path.relative(src, from).replaceAll(path.sep, '/'))) return;
108
109
  const stat = fs.statSync(from);
109
110
  if (stat.isDirectory()) {
110
111
  if (!dryRun) fs.mkdirSync(to, { recursive: true });
@@ -149,19 +150,30 @@ function managedBlockFromTemplate(block, begin, end) {
149
150
  return `${begin}\n${block.trim()}\n${end}`;
150
151
  }
151
152
 
152
- const KIT_SEED_FILES = ['FIRST_TIME_INIT.md', 'FIRST_PROMPT.md', 'CLAUDE-template.md', 'backbone.yml'];
153
- const KIT_SHARED_DIRS = ['skills', '.vbkit-commands', '.vbkit-docs'];
153
+ const KIT_SEED_FILES = ['.vibekit/init/FIRST_TIME_INIT.md', '.vibekit/init/FIRST_PROMPT.md', '.vibekit/init/CLAUDE-template.md', 'backbone.yml'];
154
+ const KIT_SHARED_DIRS = ['.vibekit/skills', '.vibekit/commands', '.vibekit/docs'];
155
+ // Kit-maintainer files that end-user repos do not need; never copied by install/update.
156
+ const KIT_DOC_EXCLUDES = ['RESEARCH_NOTES.md', 'AUTORESEARCH_LEDGER.md'];
154
157
  const KIT_SCRIPTS = [
155
- '.vbkit-scripts/mvck.mjs', '.vbkit-scripts/init-backbone.mjs', '.vbkit-scripts/daily-enhance.mjs', '.vbkit-scripts/validate-kit.mjs',
156
- '.vbkit-scripts/doctor.mjs', '.vbkit-scripts/test-install.mjs', '.vbkit-scripts/agentshield-probe.mjs', '.vbkit-scripts/pack-dry-run.mjs', '.vbkit-scripts/vibekit-finalize.mjs'
158
+ '.vibekit/scripts/mvck.mjs', '.vibekit/scripts/init-backbone.mjs', '.vibekit/scripts/daily-enhance.mjs', '.vibekit/scripts/validate-kit.mjs',
159
+ '.vibekit/scripts/doctor.mjs', '.vibekit/scripts/agentshield-probe.mjs', '.vibekit/scripts/vibekit-finalize.mjs'
157
160
  ];
161
+ const VALID_PROFILES = new Set(['claude', 'cursor', 'codex']);
162
+
163
+ function parseProfiles(profileRaw) {
164
+ const profiles = new Set(profileRaw === 'all' ? ['claude', 'cursor', 'codex'] : profileRaw.split(',').map((x) => x.trim()).filter(Boolean));
165
+ for (const p of profiles) {
166
+ if (!VALID_PROFILES.has(p)) throw new Error(`Unknown profile: ${p}. Valid values: all, claude, cursor, codex (comma-separated).`);
167
+ }
168
+ return profiles;
169
+ }
158
170
  const CLAUDE_DIRS = ['.claude/agents', '.claude/commands', '.claude/rules'];
159
171
  const CLAUDE_SKILLS = [
160
172
  'autoresearch-coding', 'agentshield-security-review', 'daily-workflow-curator', 'vibekit-init', 'visual-design-loop',
161
- 'clearthought', 'sequential-thinking', 'reviewing-4p-priorities', 'memento', 'coding-level'
173
+ 'clearthought', 'sequential-thinking', 'reviewing-4p-priorities', 'path-sensitive-shell-safety', 'memento', 'coding-level', 'parallel-analysis'
162
174
  ];
163
175
  const CURSOR_DIRS = ['.cursor/rules', '.cursor/commands'];
164
- const CURSOR_SKILLS = ['clearthought', 'sequential-thinking', 'reviewing-4p-priorities', 'memento', 'coding-level'];
176
+ const CURSOR_SKILLS = ['clearthought', 'sequential-thinking', 'reviewing-4p-priorities', 'path-sensitive-shell-safety', 'memento', 'coding-level', 'parallel-analysis'];
165
177
  const CODEX_DIRS = ['.agents', '.codex', '.codex-plugin'];
166
178
  const GITIGNORE_BLOCK = `# BEGIN: minimal-vibe-coding-kit\n.autoresearch/\nresults.tsv\n.vibekit/INIT_DONE\n.vibekit/FINALIZE_DONE\n.vibekit/reports/\n.vibekit/update-backup/\n_vibekit-cleanup/\nCLAUDE.local.md\n# END: minimal-vibe-coding-kit`;
167
179
 
@@ -187,9 +199,9 @@ function applyManagedBlocks(target, profiles, actions, { dryRun = false } = {})
187
199
  if (profiles.has('claude')) {
188
200
  const claudeTarget = path.join(target, 'CLAUDE.md');
189
201
  if (!fs.existsSync(claudeTarget)) {
190
- actions.push(copyFileSafe('CLAUDE-template.md', 'CLAUDE.md', target, { force: false, dryRun }));
202
+ actions.push(copyFileSafe('.vibekit/init/CLAUDE-template.md', 'CLAUDE.md', target, { force: false, dryRun }));
191
203
  } else {
192
- const block = `<!-- BEGIN: minimal-vibe-coding-kit -->\n@AGENTS.md\n\n## Minimal Vibe Coding Kit\n\n- Read \`backbone.yml\` before changing code.\n- If \`meta.template_status\` is \`uninitialized\`, follow \`FIRST_TIME_INIT.md\` and wait for approval before writing.\n- After init, follow \`backbone.yml\` \`conventions\` before adding new project patterns.\n- Prefer project skills for multi-step workflows: \`/autoresearch-coding\`, \`/security-scan\`, \`/daily-enhance\`.\n<!-- END: minimal-vibe-coding-kit -->`;
204
+ const block = `<!-- BEGIN: minimal-vibe-coding-kit -->\n@AGENTS.md\n\n## Minimal Vibe Coding Kit\n\n- Read \`backbone.yml\` before changing code.\n- If \`meta.template_status\` is \`uninitialized\`, follow \`.vibekit/init/FIRST_TIME_INIT.md\` and wait for approval before writing.\n- After init, follow \`backbone.yml\` \`conventions\` before adding new project patterns.\n- Prefer project skills for multi-step workflows: \`/autoresearch-coding\`, \`/security-scan\`, \`/daily-enhance\`.\n<!-- END: minimal-vibe-coding-kit -->`;
193
205
  appendManagedBlock(claudeTarget, block, '<!-- BEGIN: minimal-vibe-coding-kit -->', '<!-- END: minimal-vibe-coding-kit -->', { dryRun });
194
206
  actions.push({ action: 'managed-block', path: 'CLAUDE.md' });
195
207
  }
@@ -213,8 +225,7 @@ function install() {
213
225
  const dryRun = hasFlag('--dry-run');
214
226
  const json = hasFlag('--json');
215
227
  const target = parseTargetAndFlags('install', { valueFlags: ['--profile'] }).target;
216
- const profileRaw = optionValue('--profile', 'all');
217
- const profiles = new Set(profileRaw === 'all' ? ['claude', 'cursor', 'codex'] : profileRaw.split(',').map((x) => x.trim()).filter(Boolean));
228
+ const profiles = parseProfiles(optionValue('--profile', 'all'));
218
229
 
219
230
  if (!fs.existsSync(target)) throw new Error(`Target does not exist: ${target}`);
220
231
  const actions = [];
@@ -224,7 +235,7 @@ function install() {
224
235
  actions.push(copyFileSafe(file, file, target, opts));
225
236
  }
226
237
  for (const dir of KIT_SHARED_DIRS) {
227
- actions.push(copyDirSafe(dir, dir, target, opts));
238
+ actions.push(copyDirSafe(dir, dir, target, dir === '.vibekit/docs' ? { ...opts, exclude: KIT_DOC_EXCLUDES } : opts));
228
239
  }
229
240
  for (const file of KIT_SCRIPTS) {
230
241
  actions.push(copyFileSafe(file, file, target, opts));
@@ -258,7 +269,8 @@ function install() {
258
269
  writeKitVersion(target, dryRun);
259
270
  actions.push({ action: 'version-marker', path: '.vibekit/KIT_VERSION' });
260
271
 
261
- const nextPrompt = 'Read FIRST_TIME_INIT.md and initialize this repo with Minimal Vibe Coding Kit. Print requirements first, infer project conventions, propose a diff, and wait for my yes before writing.';
272
+ const nextPrompt = 'Read .vibekit/init/FIRST_TIME_INIT.md and initialize this repo with Minimal Vibe Coding Kit. Print requirements first, infer project conventions, propose a diff, and wait for my yes before writing.';
273
+ const legacyPaths = detectLegacyLayout(target);
262
274
  if (json) {
263
275
  console.log(JSON.stringify({
264
276
  status: dryRun ? 'dry-run' : 'installed',
@@ -267,6 +279,7 @@ function install() {
267
279
  force,
268
280
  dryRun,
269
281
  actions,
282
+ legacyPaths,
270
283
  nextPrompt
271
284
  }, null, 2));
272
285
  return;
@@ -274,10 +287,29 @@ function install() {
274
287
 
275
288
  console.log(dryRun ? 'Dry-run install plan:' : 'Install complete:');
276
289
  for (const a of actions) console.log(`- ${a.action}: ${a.path}`);
290
+ printLegacyLayoutNote(legacyPaths);
277
291
  console.log('\nNext prompt:');
278
292
  console.log(nextPrompt);
279
293
  }
280
294
 
295
+ // Pre-0.4 installs placed kit dirs at the target root. Detection is advisory
296
+ // only: nothing is deleted automatically, and a root `skills/` dir is flagged
297
+ // only when it contains a known kit skill (it may be the user's own folder).
298
+ function detectLegacyLayout(target) {
299
+ const legacy = ['.vbkit-scripts', '.vbkit-commands', '.vbkit-docs',
300
+ 'FIRST_TIME_INIT.md', 'FIRST_PROMPT.md', 'CLAUDE-template.md', 'PUSH_TO_GITHUB.md']
301
+ .filter((rel) => fs.existsSync(path.join(target, rel)));
302
+ if (fs.existsSync(path.join(target, 'skills', 'vibekit-init', 'SKILL.md'))) legacy.push('skills');
303
+ return legacy;
304
+ }
305
+
306
+ function printLegacyLayoutNote(legacy) {
307
+ if (!legacy.length) return;
308
+ console.log('\nLegacy kit layout detected (pre-0.4). Kit files now live under .vibekit/.');
309
+ console.log('After verifying the new .vibekit/ copies, remove or `git mv` these leftovers:');
310
+ for (const rel of legacy) console.log(`- ${rel}`);
311
+ }
312
+
281
313
  function updateFileSafe(srcRel, destRel, target, { dryRun = false, backup = null } = {}) {
282
314
  const src = path.join(kitRoot, srcRel);
283
315
  const dest = path.join(target, destRel ?? srcRel);
@@ -312,10 +344,12 @@ function updateFileSafe(srcRel, destRel, target, { dryRun = false, backup = null
312
344
  function updateDirSafe(srcRel, target, opts) {
313
345
  const src = path.join(kitRoot, srcRel);
314
346
  if (!fs.existsSync(src)) throw new Error(`Missing source dir: ${srcRel}`);
347
+ const exclude = opts.exclude ?? [];
315
348
  const results = [];
316
349
  function walk(current) {
317
350
  for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
318
351
  const child = path.join(current, entry.name);
352
+ if (exclude.includes(path.relative(src, child).replaceAll(path.sep, '/'))) continue;
319
353
  if (entry.isDirectory()) walk(child);
320
354
  else {
321
355
  const rel = path.join(srcRel, path.relative(src, child)).replaceAll(path.sep, '/');
@@ -332,15 +366,14 @@ function update() {
332
366
  const json = hasFlag('--json');
333
367
  const noBackup = hasFlag('--no-backup');
334
368
  const target = parseTargetAndFlags('update', { valueFlags: ['--profile'] }).target;
335
- const profileRaw = optionValue('--profile', 'all');
336
- const profiles = new Set(profileRaw === 'all' ? ['claude', 'cursor', 'codex'] : profileRaw.split(',').map((x) => x.trim()).filter(Boolean));
369
+ const profiles = parseProfiles(optionValue('--profile', 'all'));
337
370
 
338
371
  if (!fs.existsSync(target)) throw new Error(`Target does not exist: ${target}`);
339
372
  if (fs.realpathSync(kitRoot) === fs.realpathSync(target)) {
340
373
  throw new Error('Update source and target are the same directory. Run the update from a newer kit, e.g.: npx --yes minimal-vibe-coding-kit@latest update .');
341
374
  }
342
- if (!fs.existsSync(path.join(target, 'backbone.yml')) && !fs.existsSync(path.join(target, '.vbkit-scripts'))) {
343
- throw new Error('Kit not detected in target (no backbone.yml or .vbkit-scripts). Run mvck install first.');
375
+ if (!fs.existsSync(path.join(target, 'backbone.yml')) && !fs.existsSync(path.join(target, '.vibekit/scripts'))) {
376
+ throw new Error('Kit not detected in target (no backbone.yml or .vibekit/scripts). Run mvck install first.');
344
377
  }
345
378
 
346
379
  const previousVersionFile = path.join(target, '.vibekit', 'KIT_VERSION');
@@ -352,7 +385,7 @@ function update() {
352
385
  const actions = [];
353
386
 
354
387
  // Kit-owned surfaces: refresh to the running kit version, never delete extras.
355
- for (const dir of KIT_SHARED_DIRS) actions.push(...updateDirSafe(dir, target, opts));
388
+ for (const dir of KIT_SHARED_DIRS) actions.push(...updateDirSafe(dir, target, dir === '.vibekit/docs' ? { ...opts, exclude: KIT_DOC_EXCLUDES } : opts));
356
389
  for (const file of KIT_SCRIPTS) actions.push(updateFileSafe(file, file, target, opts));
357
390
  if (profiles.has('claude')) {
358
391
  for (const dir of CLAUDE_DIRS) actions.push(...updateDirSafe(dir, target, opts));
@@ -381,6 +414,7 @@ function update() {
381
414
  const backupInfo = backup && backup.count > 0 ? path.relative(target, backup.dir) : null;
382
415
  const preserved = ['backbone.yml', 'CLAUDE.md', 'AGENTS.md content outside the managed block', '.claude/settings.json', '.cursor/settings.json'];
383
416
 
417
+ const legacyPaths = detectLegacyLayout(target);
384
418
  if (json) {
385
419
  console.log(JSON.stringify({
386
420
  status: dryRun ? 'dry-run' : 'updated',
@@ -391,6 +425,7 @@ function update() {
391
425
  summary,
392
426
  backupDir: backupInfo,
393
427
  preserved,
428
+ legacyPaths,
394
429
  actions: actions.filter((a) => a.action !== 'unchanged')
395
430
  }, null, 2));
396
431
  return;
@@ -405,11 +440,12 @@ function update() {
405
440
  console.log(`\nSummary: ${summary.add} added, ${summary.update} updated, ${summary.unchanged} unchanged.`);
406
441
  if (backupInfo) console.log(`Backups of replaced files: ${backupInfo}/`);
407
442
  console.log(`Preserved (never overwritten by update): ${preserved.join(', ')}.`);
443
+ printLegacyLayoutNote(legacyPaths);
408
444
  }
409
445
 
410
446
  function delegate(scriptName, { valueFlags = [] } = {}) {
411
447
  const { target, flags } = parseTargetAndFlags(args[0], { valueFlags });
412
- const script = path.join(kitRoot, '.vbkit-scripts', scriptName);
448
+ const script = path.join(kitRoot, '.vibekit/scripts', scriptName);
413
449
  const childArgs = [script, target, ...flags];
414
450
  const result = spawnSync(process.execPath, childArgs, { stdio: 'inherit' });
415
451
  process.exit(result.status ?? 1);
@@ -6,7 +6,7 @@ import { spawnSync } from 'node:child_process';
6
6
  import { fileURLToPath } from 'node:url';
7
7
 
8
8
  const __filename = fileURLToPath(import.meta.url);
9
- const kitRoot = path.resolve(path.dirname(__filename), '..');
9
+ const kitRoot = path.resolve(path.dirname(__filename), '..', '..');
10
10
  const node = process.execPath;
11
11
  const keep = process.argv.includes('--keep');
12
12
  const temps = [];
@@ -44,21 +44,35 @@ function count(text, marker) {
44
44
 
45
45
  try {
46
46
  const clean = tempDir('clean');
47
- run(['.vbkit-scripts/mvck.mjs', 'install', clean, '--profile', 'all']);
48
- run(['.vbkit-scripts/validate-kit.mjs', clean]);
47
+ run(['.vibekit/scripts/mvck.mjs', 'install', clean, '--profile', 'all']);
48
+ run(['.vibekit/scripts/validate-kit.mjs', clean]);
49
49
  assert(fs.existsSync(path.join(clean, 'AGENTS.md')), 'clean install creates AGENTS.md');
50
- assert(fs.existsSync(path.join(clean, '.vbkit-commands')), 'clean install creates .vbkit-commands');
51
- assert(fs.existsSync(path.join(clean, '.vbkit-scripts')), 'clean install creates .vbkit-scripts');
52
- assert(fs.existsSync(path.join(clean, '.vbkit-docs')), 'clean install creates .vbkit-docs');
50
+ assert(fs.existsSync(path.join(clean, '.vibekit/commands')), 'clean install creates .vibekit/commands');
51
+ assert(fs.existsSync(path.join(clean, '.vibekit/scripts')), 'clean install creates .vibekit/scripts');
52
+ assert(fs.existsSync(path.join(clean, '.vibekit/docs')), 'clean install creates .vibekit/docs');
53
53
  assert(!fs.existsSync(path.join(clean, 'commands')), 'clean install does not create root commands');
54
54
  assert(!fs.existsSync(path.join(clean, 'scripts')), 'clean install does not create root scripts');
55
55
  assert(!fs.existsSync(path.join(clean, 'docs')), 'clean install does not create root docs');
56
+ assert(fs.existsSync(path.join(clean, '.vibekit/skills/vibekit-init/SKILL.md')), 'clean install creates .vibekit/skills');
57
+ assert(fs.existsSync(path.join(clean, '.vibekit/init/FIRST_TIME_INIT.md')), 'clean install seeds init files under .vibekit/init');
58
+ assert(!fs.existsSync(path.join(clean, 'skills')), 'clean install does not create root skills');
59
+ assert(!fs.existsSync(path.join(clean, '.vbkit-scripts')), 'clean install does not create legacy .vbkit-scripts');
60
+ assert(!fs.existsSync(path.join(clean, '.vbkit-commands')), 'clean install does not create legacy .vbkit-commands');
61
+ assert(!fs.existsSync(path.join(clean, '.vbkit-docs')), 'clean install does not create legacy .vbkit-docs');
62
+ assert(!fs.existsSync(path.join(clean, 'FIRST_TIME_INIT.md')), 'clean install does not seed root FIRST_TIME_INIT.md');
63
+ assert(!fs.existsSync(path.join(clean, '.vibekit/scripts/test-install.mjs')), 'clean install omits kit-dev test-install.mjs');
64
+ assert(!fs.existsSync(path.join(clean, '.vibekit/scripts/pack-dry-run.mjs')), 'clean install omits kit-dev pack-dry-run.mjs');
65
+ assert(!fs.existsSync(path.join(clean, '.vibekit/docs/RESEARCH_NOTES.md')), 'clean install omits maintainer RESEARCH_NOTES.md');
66
+ assert(!fs.existsSync(path.join(clean, '.vibekit/docs/AUTORESEARCH_LEDGER.md')), 'clean install omits maintainer AUTORESEARCH_LEDGER.md');
67
+ assert(fs.existsSync(path.join(clean, '.vibekit/docs/INSTALL.md')), 'clean install keeps end-user docs like INSTALL.md');
68
+ run(['.vibekit/scripts/mvck.mjs', 'install', clean, '--profile', 'bogus'], { expect: 1 });
69
+ assert(true, 'install rejects an unknown --profile value');
56
70
 
57
71
  const existing = tempDir('existing');
58
72
  fs.writeFileSync(path.join(existing, 'AGENTS.md'), '# Existing\n');
59
73
  fs.writeFileSync(path.join(existing, 'CLAUDE.md'), '# Existing Claude\n');
60
- run(['.vbkit-scripts/mvck.mjs', 'install', existing, '--profile', 'all']);
61
- run(['.vbkit-scripts/mvck.mjs', 'install', existing, '--profile', 'all']);
74
+ run(['.vibekit/scripts/mvck.mjs', 'install', existing, '--profile', 'all']);
75
+ run(['.vibekit/scripts/mvck.mjs', 'install', existing, '--profile', 'all']);
62
76
 
63
77
  const agents = fs.readFileSync(path.join(existing, 'AGENTS.md'), 'utf8');
64
78
  const claude = fs.readFileSync(path.join(existing, 'CLAUDE.md'), 'utf8');
@@ -70,39 +84,39 @@ try {
70
84
  assert(count(claude, 'END: minimal-vibe-coding-kit') === 1, 'CLAUDE.md has one managed end marker');
71
85
 
72
86
  const cwdTarget = tempDir('cwd-target');
73
- run([path.join(kitRoot, '.vbkit-scripts/mvck.mjs'), 'install', '--profile', 'all'], { cwd: cwdTarget });
87
+ run([path.join(kitRoot, '.vibekit/scripts/mvck.mjs'), 'install', '--profile', 'all'], { cwd: cwdTarget });
74
88
  assert(fs.existsSync(path.join(cwdTarget, 'backbone.yml')), 'install without target uses current working directory');
75
89
 
76
- const proposed = run([path.join(kitRoot, '.vbkit-scripts/mvck.mjs'), 'init', '--propose'], { cwd: cwdTarget });
90
+ const proposed = run([path.join(kitRoot, '.vibekit/scripts/mvck.mjs'), 'init', '--propose'], { cwd: cwdTarget });
77
91
  assert(proposed.stdout.includes('Proposed backbone.yml'), 'init --propose without target preserves flag');
78
92
 
79
- const jsonPlan = run(['.vbkit-scripts/mvck.mjs', 'install', clean, '--dry-run', '--json']);
93
+ const jsonPlan = run(['.vibekit/scripts/mvck.mjs', 'install', clean, '--dry-run', '--json']);
80
94
  const parsed = JSON.parse(jsonPlan.stdout);
81
95
  assert(parsed.status === 'dry-run' && parsed.dryRun === true, 'install --dry-run --json returns machine-readable plan');
82
96
 
83
97
  const upd = tempDir('update');
84
- run(['.vbkit-scripts/mvck.mjs', 'install', upd, '--profile', 'all']);
98
+ run(['.vibekit/scripts/mvck.mjs', 'install', upd, '--profile', 'all']);
85
99
  assert(fs.existsSync(path.join(upd, '.vibekit/KIT_VERSION')), 'install stamps .vibekit/KIT_VERSION');
86
100
  fs.appendFileSync(path.join(upd, 'backbone.yml'), '# user-custom-line\n');
87
- fs.writeFileSync(path.join(upd, 'skills/memento/SKILL.md'), '# stale kit file\n');
101
+ fs.writeFileSync(path.join(upd, '.vibekit/skills/memento/SKILL.md'), '# stale kit file\n');
88
102
  fs.rmSync(path.join(upd, '.claude/skills/coding-level'), { recursive: true, force: true });
89
103
 
90
- run(['.vbkit-scripts/mvck.mjs', 'update', upd]);
91
- assert(fs.readFileSync(path.join(upd, 'skills/memento/SKILL.md'), 'utf8').includes('name: memento'), 'update refreshes stale kit files');
104
+ run(['.vibekit/scripts/mvck.mjs', 'update', upd]);
105
+ assert(fs.readFileSync(path.join(upd, '.vibekit/skills/memento/SKILL.md'), 'utf8').includes('name: memento'), 'update refreshes stale kit files');
92
106
  assert(fs.existsSync(path.join(upd, '.claude/skills/coding-level/SKILL.md')), 'update re-adds missing kit skill mirrors');
93
107
  assert(fs.readFileSync(path.join(upd, 'backbone.yml'), 'utf8').includes('# user-custom-line'), 'update preserves user-modified backbone.yml');
94
108
  const backupRoot = path.join(upd, '.vibekit', 'update-backup');
95
109
  assert(fs.existsSync(backupRoot) && fs.readdirSync(backupRoot).length >= 1, 'update backs up replaced kit files');
96
- run(['.vbkit-scripts/validate-kit.mjs', upd]);
110
+ run(['.vibekit/scripts/validate-kit.mjs', upd]);
97
111
 
98
112
  const updAgents = fs.readFileSync(path.join(upd, 'AGENTS.md'), 'utf8');
99
113
  assert(count(updAgents, 'BEGIN: minimal-vibe-coding-kit') === 1, 'update keeps one managed begin marker in AGENTS.md');
100
114
 
101
115
  const emptyTarget = tempDir('update-empty');
102
- run(['.vbkit-scripts/mvck.mjs', 'update', emptyTarget], { expect: 1 });
116
+ run(['.vibekit/scripts/mvck.mjs', 'update', emptyTarget], { expect: 1 });
103
117
  assert(true, 'update refuses a target without the kit installed');
104
118
 
105
- const updPlan = run(['.vbkit-scripts/mvck.mjs', 'update', upd, '--dry-run', '--json']);
119
+ const updPlan = run(['.vibekit/scripts/mvck.mjs', 'update', upd, '--dry-run', '--json']);
106
120
  const updParsed = JSON.parse(updPlan.stdout);
107
121
  assert(updParsed.status === 'dry-run' && typeof updParsed.toVersion === 'string', 'update --dry-run --json returns machine-readable plan');
108
122