waypoint-codex 0.8.1 → 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.
Files changed (30) hide show
  1. package/README.md +14 -28
  2. package/dist/src/cli.js +2 -34
  3. package/dist/src/core.js +16 -323
  4. package/dist/src/templates.js +1 -4
  5. package/dist/src/upgrade.js +0 -10
  6. package/package.json +1 -1
  7. package/templates/.agents/skills/backend-context-interview/SKILL.md +70 -0
  8. package/templates/.agents/skills/backend-ship-audit/SKILL.md +221 -0
  9. package/templates/.agents/skills/backend-ship-audit/agents/openai.yaml +3 -0
  10. package/templates/.agents/skills/backend-ship-audit/references/audit-framework.md +228 -0
  11. package/templates/.agents/skills/backend-ship-audit/references/report-template.md +92 -0
  12. package/templates/.agents/skills/frontend-context-interview/SKILL.md +60 -0
  13. package/templates/.agents/skills/frontend-ship-audit/SKILL.md +87 -0
  14. package/templates/.agents/skills/frontend-ship-audit/agents/openai.yaml +3 -0
  15. package/templates/.agents/skills/frontend-ship-audit/references/guidance-file-updates.md +57 -0
  16. package/templates/.agents/skills/frontend-ship-audit/references/report-template.md +51 -0
  17. package/templates/.agents/skills/frontend-ship-audit/references/review-framework.md +83 -0
  18. package/templates/.agents/skills/frontend-ship-audit/scripts/create_frontend_audit.py +81 -0
  19. package/templates/.codex/agents/plan-reviewer.toml +1 -2
  20. package/templates/.waypoint/README.md +2 -5
  21. package/templates/.waypoint/SOUL.md +1 -1
  22. package/templates/.waypoint/agent-operating-manual.md +12 -9
  23. package/templates/.waypoint/agents/code-health-reviewer.md +10 -1
  24. package/templates/.waypoint/agents/plan-reviewer.md +7 -2
  25. package/templates/.waypoint/config.toml +0 -3
  26. package/templates/managed-agents-block.md +38 -2
  27. package/templates/.waypoint/automations/README.md +0 -18
  28. package/templates/.waypoint/automations/docs-garden.toml +0 -7
  29. package/templates/.waypoint/automations/repo-health.toml +0 -8
  30. package/templates/.waypoint/rules/README.md +0 -6
package/README.md CHANGED
@@ -28,6 +28,7 @@ Waypoint scaffolds a Codex-friendly repo structure built around a few core piece
28
28
  - `.waypoint/TRACKS_INDEX.md` for tracker routing
29
29
  - `.waypoint/context/` for generated startup context
30
30
  - `.agents/skills/` for repo-local workflows like planning, tracking, audits, and QA
31
+ - `.codex/` for the default reviewer-agent pack
31
32
 
32
33
  The philosophy is simple:
33
34
 
@@ -66,7 +67,7 @@ npx waypoint-codex@latest --help
66
67
  Inside the repo you want to prepare for Codex:
67
68
 
68
69
  ```bash
69
- waypoint init --with-roles --with-automations
70
+ waypoint init
70
71
  waypoint doctor
71
72
  ```
72
73
 
@@ -75,6 +76,9 @@ That gives you a repo that looks roughly like this:
75
76
  ```text
76
77
  repo/
77
78
  ├── AGENTS.md
79
+ ├── .codex/
80
+ │ ├── agents/
81
+ │ └── config.toml
78
82
  ├── .agents/
79
83
  │ └── skills/
80
84
  └── .waypoint/
@@ -98,39 +102,29 @@ From there, start your Codex session in the repo and follow the generated bootst
98
102
  waypoint init
99
103
  ```
100
104
 
101
- By default, `waypoint init` updates the global CLI to the latest published `waypoint-codex` first, then scaffolds with that fresh version. If you want to scaffold with the currently installed binary instead, use:
105
+ By default, `waypoint init` updates the global CLI to the latest published `waypoint-codex` first, then scaffolds with that fresh version. It also installs the reviewer-agent pack by default. If you want to scaffold with the currently installed binary instead, use:
102
106
 
103
107
  ```bash
104
108
  waypoint init --skip-cli-update
105
109
  ```
106
110
 
107
- ### Full local workflow setup
108
-
109
- ```bash
110
- waypoint init --with-roles --with-rules --with-automations
111
- ```
112
-
113
111
  ### App-friendly profile
114
112
 
115
113
  ```bash
116
- waypoint init --app-friendly --with-roles --with-automations
114
+ waypoint init --app-friendly
117
115
  ```
118
116
 
119
117
  Flags you can combine:
120
118
 
121
119
  - `--app-friendly`
122
- - `--with-roles`
123
- - `--with-rules`
124
- - `--with-automations`
125
120
  - `--skip-cli-update`
126
121
 
127
122
  ## Main commands
128
123
 
129
124
  - `waypoint init` — update the CLI to latest by default, then scaffold or refresh the repo
130
125
  - `waypoint doctor` — validate health and report drift
131
- - `waypoint sync` — rebuild the docs index and sync optional user-home artifacts
126
+ - `waypoint sync` — rebuild the docs and tracker indexes
132
127
  - `waypoint upgrade` — update the CLI and refresh the current repo using its saved config
133
- - `waypoint import-legacy` — analyze an older repo layout and produce an adoption report
134
128
 
135
129
  ## Built-in skills
136
130
 
@@ -141,21 +135,24 @@ Waypoint ships a strong default skill pack for real coding work:
141
135
  - `docs-sync`
142
136
  - `code-guide-audit`
143
137
  - `break-it-qa`
138
+ - `frontend-ship-audit`
139
+ - `backend-ship-audit`
144
140
  - `workspace-compress`
145
141
  - `pre-pr-hygiene`
146
142
  - `pr-review`
147
143
 
148
144
  These are repo-local, so the workflow travels with the project.
145
+ `break-it-qa`, `frontend-ship-audit`, and `backend-ship-audit` are user-invoked audit skills, not default autonomous agent steps.
149
146
 
150
- ## Optional reviewer roles
147
+ ## Reviewer agents
151
148
 
152
- If you initialize with `--with-roles`, Waypoint scaffolds:
149
+ Waypoint scaffolds these reviewer agents by default:
153
150
 
154
151
  - `code-health-reviewer`
155
152
  - `code-reviewer`
156
153
  - `plan-reviewer`
157
154
 
158
- The intended workflow is chunk-based: once there is a meaningful reviewable slice, run the reviewers in parallel, fix real findings, then close out. A recent self-authored commit is the preferred scope anchor when one cleanly represents the slice, but it is not the only valid trigger.
155
+ The intended workflow is closeout-based: run `code-reviewer` before considering any non-trivial implementation slice complete, and run `code-health-reviewer` before considering medium or large changes complete, especially when they add structure, duplicate logic, or introduce new abstractions. If both apply, run them in parallel. A recent self-authored commit is the preferred scope anchor when one cleanly represents the slice, but it is not the only valid trigger.
159
156
 
160
157
  ## What makes it different
161
158
 
@@ -185,22 +182,11 @@ If you only want to update the CLI:
185
182
  waypoint upgrade --skip-repo-refresh
186
183
  ```
187
184
 
188
- ## Importing an existing repo
189
-
190
- If you already have an older assistant setup or repo-memory system:
191
-
192
- ```bash
193
- waypoint import-legacy /path/to/source-repo /path/to/new-repo --init-target
194
- ```
195
-
196
- This generates an adoption report and helps separate durable docs from old runtime-specific scaffolding.
197
-
198
185
  ## Learn more
199
186
 
200
187
  - [Overview](docs/overview.md)
201
188
  - [Architecture](docs/architecture.md)
202
189
  - [Upgrading](docs/upgrading.md)
203
- - [Importing Existing Repositories](docs/importing-existing-repos.md)
204
190
  - [Releasing](docs/releasing.md)
205
191
 
206
192
  ## License
package/dist/src/cli.js CHANGED
@@ -4,7 +4,7 @@ import { readFileSync } from "node:fs";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import path from "node:path";
6
6
  import process from "node:process";
7
- import { doctorRepository, importLegacyRepo, initRepository, loadWaypointConfig, syncRepository } from "./core.js";
7
+ import { doctorRepository, initRepository, loadWaypointConfig, syncRepository } from "./core.js";
8
8
  import { maybeUpgradeWaypointBeforeInit, upgradeWaypoint } from "./upgrade.js";
9
9
  const VERSION = JSON.parse(readFileSync(path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../package.json"), "utf8")).version;
10
10
  function resolveRepo(input) {
@@ -29,9 +29,8 @@ function printHelp() {
29
29
  Commands:
30
30
  init Initialize a repository with Waypoint scaffolding (auto-updates CLI unless skipped)
31
31
  doctor Validate repository health and report drift
32
- sync Rebuild docs index and sync optional user-home artifacts
32
+ sync Rebuild docs and tracker indexes
33
33
  upgrade Update the global Waypoint CLI and refresh this repo using existing config
34
- import-legacy Analyze a legacy repository layout and produce a Waypoint adoption report
35
34
  `);
36
35
  }
37
36
  async function main() {
@@ -50,9 +49,6 @@ async function main() {
50
49
  args: argv.slice(1),
51
50
  options: {
52
51
  "app-friendly": { type: "boolean", default: false },
53
- "with-roles": { type: "boolean", default: false },
54
- "with-rules": { type: "boolean", default: false },
55
- "with-automations": { type: "boolean", default: false },
56
52
  "skip-cli-update": { type: "boolean", default: false }
57
53
  },
58
54
  allowPositionals: true
@@ -70,9 +66,6 @@ async function main() {
70
66
  }
71
67
  const results = initRepository(projectRoot, {
72
68
  profile: values["app-friendly"] ? "app-friendly" : "universal",
73
- withRoles: values["with-roles"],
74
- withRules: values["with-rules"],
75
- withAutomations: values["with-automations"]
76
69
  });
77
70
  for (const line of results) {
78
71
  console.log(`- ${line}`);
@@ -116,31 +109,6 @@ async function main() {
116
109
  }
117
110
  return 0;
118
111
  }
119
- if (command === "import-legacy") {
120
- const { values, positionals } = parseArgs({
121
- args: argv.slice(1),
122
- options: {
123
- "init-target": { type: "boolean", default: false }
124
- },
125
- allowPositionals: true
126
- });
127
- if (positionals.length === 0) {
128
- console.error("import-legacy requires a source repository path.");
129
- return 2;
130
- }
131
- const sourceRepo = resolveRepo(positionals[0]);
132
- const targetRepo = positionals[1] ? resolveRepo(positionals[1]) : undefined;
133
- const result = importLegacyRepo(sourceRepo, targetRepo, {
134
- initTarget: values["init-target"]
135
- });
136
- for (const line of result.actions) {
137
- console.log(`- ${line}`);
138
- }
139
- if (!targetRepo) {
140
- console.log(result.report);
141
- }
142
- return 0;
143
- }
144
112
  if (command === "upgrade") {
145
113
  const { values, positionals } = parseArgs({
146
114
  args: argv.slice(1),
package/dist/src/core.js CHANGED
@@ -1,6 +1,4 @@
1
- import { createHash } from "node:crypto";
2
- import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync, } from "node:fs";
3
- import os from "node:os";
1
+ import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync, } from "node:fs";
4
2
  import path from "node:path";
5
3
  import * as TOML from "@iarna/toml";
6
4
  import { renderDocsIndex } from "./docs-index.js";
@@ -12,8 +10,6 @@ const DEFAULT_DOCS_INDEX = ".waypoint/DOCS_INDEX.md";
12
10
  const DEFAULT_TRACK_DIR = ".waypoint/track";
13
11
  const DEFAULT_TRACKS_INDEX = ".waypoint/TRACKS_INDEX.md";
14
12
  const DEFAULT_WORKSPACE = ".waypoint/WORKSPACE.md";
15
- const STATE_DIR = ".waypoint/state";
16
- const SYNC_RECORDS_FILE = ".waypoint/state/sync-records.json";
17
13
  const TIMESTAMPED_WORKSPACE_SECTIONS = new Set([
18
14
  "## Active Trackers",
19
15
  "## Current State",
@@ -102,8 +98,6 @@ function scaffoldSkills(projectRoot) {
102
98
  }
103
99
  function scaffoldWaypointOptionalTemplates(projectRoot) {
104
100
  copyTemplateTree(templatePath(".waypoint/agents"), path.join(projectRoot, ".waypoint/agents"));
105
- copyTemplateTree(templatePath(".waypoint/automations"), path.join(projectRoot, ".waypoint/automations"));
106
- copyTemplateTree(templatePath(".waypoint/rules"), path.join(projectRoot, ".waypoint/rules"));
107
101
  copyTemplateTree(templatePath(".waypoint/scripts"), path.join(projectRoot, ".waypoint/scripts"));
108
102
  copyTemplateTree(templatePath(".waypoint/track"), path.join(projectRoot, ".waypoint/track"));
109
103
  }
@@ -135,21 +129,18 @@ export function initRepository(projectRoot, options) {
135
129
  ".codex/agents/reviewer.toml",
136
130
  ".codex/agents/architect.toml",
137
131
  ".codex/agents/implementer.toml",
132
+ ".waypoint/automations",
133
+ ".waypoint/rules",
134
+ ".waypoint/state",
138
135
  ]) {
139
136
  removePathIfExists(path.join(projectRoot, deprecatedPath));
140
137
  }
141
- ensureDir(path.join(projectRoot, ".waypoint/automations"));
142
- ensureDir(path.join(projectRoot, ".waypoint/rules"));
143
- ensureDir(path.join(projectRoot, STATE_DIR));
144
138
  writeText(path.join(projectRoot, ".waypoint/README.md"), readTemplate(".waypoint/README.md"));
145
139
  writeText(path.join(projectRoot, ".waypoint/SOUL.md"), readTemplate(".waypoint/SOUL.md"));
146
140
  writeText(path.join(projectRoot, ".waypoint/agent-operating-manual.md"), readTemplate(".waypoint/agent-operating-manual.md"));
147
141
  scaffoldWaypointOptionalTemplates(projectRoot);
148
142
  writeText(path.join(projectRoot, DEFAULT_CONFIG_PATH), renderWaypointConfig({
149
143
  profile: options.profile,
150
- roles: options.withRoles,
151
- rules: options.withRules,
152
- automations: options.withAutomations,
153
144
  }));
154
145
  writeIfMissing(path.join(projectRoot, DEFAULT_WORKSPACE), readTemplate("WORKSPACE.md"));
155
146
  ensureDir(path.join(projectRoot, DEFAULT_DOCS_DIR));
@@ -158,9 +149,7 @@ export function initRepository(projectRoot, options) {
158
149
  writeIfMissing(path.join(projectRoot, ".waypoint/docs/code-guide.md"), readTemplate(".waypoint/docs/code-guide.md"));
159
150
  upsertManagedBlock(path.join(projectRoot, "AGENTS.md"), readTemplate("managed-agents-block.md"));
160
151
  scaffoldSkills(projectRoot);
161
- if (options.withRoles) {
162
- scaffoldOptionalCodex(projectRoot);
163
- }
152
+ scaffoldOptionalCodex(projectRoot);
164
153
  appendGitignoreSnippet(projectRoot);
165
154
  const docsIndex = renderDocsIndex(projectRoot, path.join(projectRoot, DEFAULT_DOCS_DIR));
166
155
  const tracksIndex = renderTracksIndex(projectRoot, path.join(projectRoot, DEFAULT_TRACK_DIR));
@@ -171,6 +160,7 @@ export function initRepository(projectRoot, options) {
171
160
  "Installed managed AGENTS block",
172
161
  "Created .waypoint/WORKSPACE.md, .waypoint/docs/, and .waypoint/track/ scaffold",
173
162
  "Installed repo-local Waypoint skills",
163
+ "Installed reviewer agents and project Codex config",
174
164
  "Generated .waypoint/DOCS_INDEX.md and .waypoint/TRACKS_INDEX.md",
175
165
  ];
176
166
  }
@@ -181,27 +171,6 @@ export function loadWaypointConfig(projectRoot) {
181
171
  }
182
172
  return TOML.parse(readFileSync(configPath, "utf8"));
183
173
  }
184
- function loadSyncRecords(projectRoot) {
185
- const syncPath = path.join(projectRoot, SYNC_RECORDS_FILE);
186
- if (!existsSync(syncPath)) {
187
- return {};
188
- }
189
- try {
190
- return JSON.parse(readFileSync(syncPath, "utf8"));
191
- }
192
- catch {
193
- return {};
194
- }
195
- }
196
- function saveSyncRecords(projectRoot, records) {
197
- writeText(path.join(projectRoot, SYNC_RECORDS_FILE), `${JSON.stringify(records, null, 2)}\n`);
198
- }
199
- function hashFile(filePath) {
200
- return createHash("sha256").update(readFileSync(filePath)).digest("hex");
201
- }
202
- function codexHome() {
203
- return process.env.CODEX_HOME ?? path.join(os.homedir(), ".codex");
204
- }
205
174
  function findWorkspaceTimestampViolations(workspaceText) {
206
175
  let currentSection = "";
207
176
  const violations = new Set();
@@ -223,111 +192,6 @@ function findWorkspaceTimestampViolations(workspaceText) {
223
192
  }
224
193
  return [...violations];
225
194
  }
226
- function renderCodexAutomation(spec, cwd) {
227
- const now = Date.now();
228
- const rrule = spec.rrule?.startsWith("RRULE:") ? spec.rrule : `RRULE:${spec.rrule}`;
229
- return [
230
- "version = 1",
231
- `id = ${JSON.stringify(spec.id)}`,
232
- `name = ${JSON.stringify(spec.name)}`,
233
- `prompt = ${JSON.stringify(spec.prompt)}`,
234
- `status = ${JSON.stringify(spec.status ?? "ACTIVE")}`,
235
- `rrule = ${JSON.stringify(rrule)}`,
236
- `execution_environment = ${JSON.stringify(spec.execution_environment ?? "worktree")}`,
237
- `cwds = ${JSON.stringify(spec.cwds ?? [cwd])}`,
238
- `created_at = ${now}`,
239
- `updated_at = ${now}`,
240
- ].join("\n") + "\n";
241
- }
242
- function isKebabCase(value) {
243
- return /^[a-z0-9-]+$/.test(value);
244
- }
245
- function validateAutomationSpecFile(filePath) {
246
- const errors = [];
247
- let parsed;
248
- try {
249
- parsed = TOML.parse(readFileSync(filePath, "utf8"));
250
- }
251
- catch (error) {
252
- return [`invalid TOML: ${error instanceof Error ? error.message : String(error)}`];
253
- }
254
- for (const key of ["id", "name", "prompt", "rrule"]) {
255
- if (!parsed[key]) {
256
- errors.push(`missing required key \`${key}\``);
257
- }
258
- }
259
- if (parsed.id && !isKebabCase(parsed.id)) {
260
- errors.push("automation id must use lowercase kebab-case");
261
- }
262
- return errors;
263
- }
264
- function syncAutomations(projectRoot) {
265
- const sourceDir = path.join(projectRoot, ".waypoint/automations");
266
- if (!existsSync(sourceDir)) {
267
- return [];
268
- }
269
- const targetRoot = path.join(codexHome(), "automations");
270
- ensureDir(targetRoot);
271
- const records = loadSyncRecords(projectRoot);
272
- const results = [];
273
- for (const entry of readdirSync(sourceDir)) {
274
- if (!entry.endsWith(".toml")) {
275
- continue;
276
- }
277
- const sourcePath = path.join(sourceDir, entry);
278
- const errors = validateAutomationSpecFile(sourcePath);
279
- if (errors.length > 0) {
280
- results.push(`Skipped ${entry}: ${errors.join("; ")}`);
281
- continue;
282
- }
283
- const spec = TOML.parse(readFileSync(sourcePath, "utf8"));
284
- if (spec.enabled === false) {
285
- continue;
286
- }
287
- const targetDir = path.join(targetRoot, spec.id);
288
- const targetPath = path.join(targetDir, "automation.toml");
289
- ensureDir(targetDir);
290
- writeText(targetPath, renderCodexAutomation(spec, projectRoot));
291
- records[sourcePath] = {
292
- artifact_type: "automation",
293
- source_path: sourcePath,
294
- target_path: targetPath,
295
- source_hash: hashFile(sourcePath),
296
- target_hash: hashFile(targetPath),
297
- };
298
- results.push(`Synced automation \`${spec.id}\``);
299
- }
300
- saveSyncRecords(projectRoot, records);
301
- return results;
302
- }
303
- function syncRules(projectRoot) {
304
- const sourceDir = path.join(projectRoot, ".waypoint/rules");
305
- if (!existsSync(sourceDir)) {
306
- return [];
307
- }
308
- const targetRoot = path.join(codexHome(), "rules");
309
- ensureDir(targetRoot);
310
- const records = loadSyncRecords(projectRoot);
311
- const results = [];
312
- for (const entry of readdirSync(sourceDir)) {
313
- if (!entry.endsWith(".rules")) {
314
- continue;
315
- }
316
- const sourcePath = path.join(sourceDir, entry);
317
- const targetPath = path.join(targetRoot, `waypoint-${entry}`);
318
- copyFileSync(sourcePath, targetPath);
319
- records[sourcePath] = {
320
- artifact_type: "rules",
321
- source_path: sourcePath,
322
- target_path: targetPath,
323
- source_hash: hashFile(sourcePath),
324
- target_hash: hashFile(targetPath),
325
- };
326
- results.push(`Synced rules \`${entry}\``);
327
- }
328
- saveSyncRecords(projectRoot, records);
329
- return results;
330
- }
331
195
  export function doctorRepository(projectRoot) {
332
196
  const findings = [];
333
197
  const config = loadWaypointConfig(projectRoot);
@@ -532,55 +396,15 @@ export function doctorRepository(projectRoot) {
532
396
  });
533
397
  }
534
398
  }
535
- const featureMap = config.features ?? {};
536
- if (featureMap.automations) {
537
- const records = loadSyncRecords(projectRoot);
538
- const automationDir = path.join(projectRoot, ".waypoint/automations");
539
- if (existsSync(automationDir)) {
540
- for (const entry of readdirSync(automationDir)) {
541
- if (!entry.endsWith(".toml")) {
542
- continue;
543
- }
544
- const filePath = path.join(automationDir, entry);
545
- const errors = validateAutomationSpecFile(filePath);
546
- for (const error of errors) {
547
- findings.push({
548
- severity: "error",
549
- category: "automations",
550
- message: `${path.relative(projectRoot, filePath)}: ${error}`,
551
- remediation: "Fix the automation spec and rerun `waypoint sync`.",
552
- paths: [filePath],
553
- });
554
- }
555
- if (errors.length === 0) {
556
- const spec = TOML.parse(readFileSync(filePath, "utf8"));
557
- if (spec.enabled === false) {
558
- continue;
559
- }
560
- }
561
- if (errors.length === 0 && !records[filePath]) {
562
- findings.push({
563
- severity: "info",
564
- category: "automations",
565
- message: `Automation \`${path.basename(entry, ".toml")}\` has not been synced.`,
566
- remediation: "Run `waypoint sync` to install it into Codex home.",
567
- paths: [filePath],
568
- });
569
- }
570
- }
571
- }
572
- }
573
- if (featureMap.roles) {
574
- const codexConfigPath = path.join(projectRoot, ".codex/config.toml");
575
- if (!existsSync(codexConfigPath)) {
576
- findings.push({
577
- severity: "warn",
578
- category: "roles",
579
- message: "Role support is enabled but .codex/config.toml is missing.",
580
- remediation: "Run `waypoint init --with-roles` or create the project Codex config files.",
581
- paths: [codexConfigPath],
582
- });
583
- }
399
+ const codexConfigPath = path.join(projectRoot, ".codex/config.toml");
400
+ if (!existsSync(codexConfigPath)) {
401
+ findings.push({
402
+ severity: "warn",
403
+ category: "roles",
404
+ message: "Reviewer agent config is missing from .codex/config.toml.",
405
+ remediation: "Run `waypoint init` or create the project Codex config files.",
406
+ paths: [codexConfigPath],
407
+ });
584
408
  }
585
409
  return findings;
586
410
  }
@@ -594,136 +418,5 @@ export function syncRepository(projectRoot) {
594
418
  const tracksIndex = renderTracksIndex(projectRoot, trackDir);
595
419
  writeText(docsIndexPath, `${docsIndex.content}\n`);
596
420
  writeText(tracksIndexPath, `${tracksIndex.content}\n`);
597
- const results = ["Rebuilt .waypoint/DOCS_INDEX.md", "Rebuilt .waypoint/TRACKS_INDEX.md"];
598
- const featureMap = config.features ?? {};
599
- if (featureMap.rules) {
600
- results.push(...syncRules(projectRoot));
601
- }
602
- if (featureMap.automations) {
603
- results.push(...syncAutomations(projectRoot));
604
- }
605
- return results;
606
- }
607
- export function importLegacyRepo(sourceRepo, targetRepo, options = {}) {
608
- const sourceDocsDir = path.join(sourceRepo, ".meridian/docs");
609
- const sourceSkillsDir = path.join(sourceRepo, "skills");
610
- const sourceCommandsDir = path.join(sourceRepo, "commands");
611
- const sourceAgentsDir = path.join(sourceRepo, "agents");
612
- const sourceHooksPath = path.join(sourceRepo, "hooks/hooks.json");
613
- const sourceScriptsDir = path.join(sourceRepo, "scripts");
614
- const portableDocs = existsSync(sourceDocsDir)
615
- ? readdirSync(sourceDocsDir).filter((entry) => entry.endsWith(".md")).sort()
616
- : [];
617
- const portableSkills = existsSync(sourceSkillsDir)
618
- ? readdirSync(sourceSkillsDir)
619
- .map((entry) => path.join("skills", entry, "SKILL.md"))
620
- .filter((relPath) => existsSync(path.join(sourceRepo, relPath)))
621
- .sort()
622
- : [];
623
- const portableCommands = existsSync(sourceCommandsDir)
624
- ? readdirSync(sourceCommandsDir)
625
- .filter((entry) => entry.endsWith(".md"))
626
- .map((entry) => path.join("commands", entry))
627
- .sort()
628
- : [];
629
- const agentFiles = existsSync(sourceAgentsDir)
630
- ? readdirSync(sourceAgentsDir)
631
- .filter((entry) => entry.endsWith(".md"))
632
- .map((entry) => path.join("agents", entry))
633
- .sort()
634
- : [];
635
- const hookFiles = existsSync(sourceHooksPath) ? [path.join("hooks", "hooks.json")] : [];
636
- const scriptFiles = existsSync(sourceScriptsDir)
637
- ? collectFiles(sourceScriptsDir)
638
- .filter((filePath) => filePath.endsWith(".py"))
639
- .map((filePath) => path.relative(sourceRepo, filePath))
640
- .sort()
641
- : [];
642
- const actions = [];
643
- if (targetRepo && options.initTarget) {
644
- actions.push(...initRepository(targetRepo, {
645
- profile: "universal",
646
- withRoles: false,
647
- withRules: false,
648
- withAutomations: false,
649
- }));
650
- }
651
- if (targetRepo) {
652
- const importDir = path.join(targetRepo, ".waypoint/docs/legacy-import");
653
- ensureDir(importDir);
654
- for (const docName of portableDocs) {
655
- copyFileSync(path.join(sourceDocsDir, docName), path.join(importDir, docName));
656
- }
657
- if (portableDocs.length > 0) {
658
- actions.push(`Copied ${portableDocs.length} legacy docs into ${importDir}`);
659
- }
660
- const docsIndex = renderDocsIndex(targetRepo, path.join(targetRepo, DEFAULT_DOCS_DIR));
661
- writeText(path.join(targetRepo, DEFAULT_DOCS_INDEX), `${docsIndex.content}\n`);
662
- }
663
- const report = [
664
- "# Legacy Repository Adoption Report",
665
- "",
666
- `Source: \`${sourceRepo}\``,
667
- "",
668
- "## Portable as-is or with light rewriting",
669
- "",
670
- `- Docs: ${portableDocs.length}`,
671
- `- Skills: ${portableSkills.length}`,
672
- `- Commands/prompts worth reviewing for skill conversion: ${portableCommands.length}`,
673
- "",
674
- "### Docs",
675
- ...(portableDocs.length > 0
676
- ? portableDocs.map((entry) => `- \`.meridian/docs/${entry}\``)
677
- : ["- None"]),
678
- "",
679
- "### Skills",
680
- ...(portableSkills.length > 0 ? portableSkills.map((entry) => `- \`${entry}\``) : ["- None"]),
681
- "",
682
- "## Replace with explicit Waypoint patterns",
683
- "",
684
- "- hook-based session injection -> AGENTS routing, context generation, repo-local skills, doctor/sync",
685
- "- hidden stop-hook policing -> advisory workflow skills and visible repo state",
686
- "- transcript learners -> maintenance skills and optional app automations",
687
- "- opaque reviewer plumbing -> optional Codex roles where actually useful",
688
- "",
689
- "## Legacy machinery to drop",
690
- "",
691
- `- Hook registration files: ${hookFiles.length}`,
692
- `- Hook/runtime scripts: ${scriptFiles.length}`,
693
- "",
694
- "### Hook/runtime files",
695
- ...((hookFiles.length + scriptFiles.length) > 0
696
- ? [...hookFiles, ...scriptFiles].map((entry) => `- \`${entry}\``)
697
- : ["- None"]),
698
- "",
699
- "## Agent files to reinterpret, not port literally",
700
- "",
701
- ...(agentFiles.length > 0 ? agentFiles.map((entry) => `- \`${entry}\``) : ["- None"]),
702
- "",
703
- "## Notes",
704
- "",
705
- "- The strongest reusable assets are methodology, docs patterns, and review/planning discipline.",
706
- "- The weakest portability surface is hook-dependent session machinery and transcript-coupled automation.",
707
- "",
708
- ].join("\n");
709
- if (targetRepo) {
710
- const reportPath = path.join(targetRepo, ".waypoint/IMPORT_LEGACY.md");
711
- writeText(reportPath, report);
712
- actions.push(`Wrote migration report to ${reportPath}`);
713
- }
714
- return { report, actions };
715
- }
716
- function collectFiles(rootDir) {
717
- const output = [];
718
- for (const entry of readdirSync(rootDir)) {
719
- const fullPath = path.join(rootDir, entry);
720
- const stat = statSync(fullPath);
721
- if (stat.isDirectory()) {
722
- output.push(...collectFiles(fullPath));
723
- }
724
- else {
725
- output.push(fullPath);
726
- }
727
- }
728
- return output;
421
+ return ["Rebuilt .waypoint/DOCS_INDEX.md", "Rebuilt .waypoint/TRACKS_INDEX.md"];
729
422
  }
@@ -27,8 +27,5 @@ export function readTemplate(relativePath) {
27
27
  }
28
28
  export function renderWaypointConfig(options) {
29
29
  return readTemplate(".waypoint/config.toml")
30
- .replace("__PROFILE__", options.profile)
31
- .replace("__ROLES__", String(options.roles))
32
- .replace("__RULES__", String(options.rules))
33
- .replace("__AUTOMATIONS__", String(options.automations));
30
+ .replace("__PROFILE__", options.profile);
34
31
  }
@@ -9,16 +9,6 @@ export function buildInitArgs(projectRoot, config) {
9
9
  if (config.profile === "app-friendly") {
10
10
  args.push("--app-friendly");
11
11
  }
12
- const featureMap = config.features ?? {};
13
- if (featureMap.roles) {
14
- args.push("--with-roles");
15
- }
16
- if (featureMap.rules) {
17
- args.push("--with-rules");
18
- }
19
- if (featureMap.automations) {
20
- args.push("--with-automations");
21
- }
22
12
  return args;
23
13
  }
24
14
  function parseVersion(version) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waypoint-codex",
3
- "version": "0.8.1",
3
+ "version": "0.9.0",
4
4
  "description": "Codex-native repository operating system: scaffolding, docs routing, repo-local skills, doctor, and sync.",
5
5
  "license": "MIT",
6
6
  "type": "module",