waypoint-codex 0.13.3 → 0.14.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/README.md +18 -0
- package/dist/src/core.js +86 -23
- package/dist/src/docs-index.js +20 -10
- package/dist/src/templates.js +29 -3
- package/package.json +1 -1
- package/templates/.waypoint/config.toml +2 -2
package/README.md
CHANGED
|
@@ -72,6 +72,10 @@ The philosophy is simple:
|
|
|
72
72
|
- investigation before status narration
|
|
73
73
|
- structured workflows that stay in their own tools
|
|
74
74
|
|
|
75
|
+
By default, Waypoint routes docs from `.waypoint/docs/` and plans from `.waypoint/plans/`.
|
|
76
|
+
If your repo keeps routable docs elsewhere, you can add more explicit roots in `.waypoint/config.toml` with `docs_dirs` and `plans_dirs`.
|
|
77
|
+
Waypoint scans each configured root recursively and only includes Markdown files with valid Waypoint frontmatter.
|
|
78
|
+
|
|
75
79
|
## Best fit
|
|
76
80
|
|
|
77
81
|
Waypoint is most useful when you want:
|
|
@@ -117,6 +121,20 @@ repo/
|
|
|
117
121
|
|
|
118
122
|
From there, start your Codex session in the repo and follow the generated bootstrap in `AGENTS.md`.
|
|
119
123
|
|
|
124
|
+
If you want to add more routable roots, extend `.waypoint/config.toml` like this:
|
|
125
|
+
|
|
126
|
+
```toml
|
|
127
|
+
docs_dirs = [
|
|
128
|
+
".waypoint/docs",
|
|
129
|
+
"services/app/docs",
|
|
130
|
+
]
|
|
131
|
+
|
|
132
|
+
plans_dirs = [
|
|
133
|
+
".waypoint/plans",
|
|
134
|
+
"services/app/plans",
|
|
135
|
+
]
|
|
136
|
+
```
|
|
137
|
+
|
|
120
138
|
## Built-in skills
|
|
121
139
|
|
|
122
140
|
Waypoint ships a strong default skill pack for real coding work:
|
package/dist/src/core.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync, } from "node:fs";
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, statSync, writeFileSync, } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import * as TOML from "@iarna/toml";
|
|
4
4
|
import { renderDocsIndex } from "./docs-index.js";
|
|
5
5
|
import { renderTracksIndex } from "./track-index.js";
|
|
6
|
-
import { readTemplate, renderWaypointConfig, MANAGED_BLOCK_END, MANAGED_BLOCK_START, templatePath } from "./templates.js";
|
|
6
|
+
import { defaultWaypointConfig, readTemplate, renderWaypointConfig, MANAGED_BLOCK_END, MANAGED_BLOCK_START, templatePath, } from "./templates.js";
|
|
7
7
|
const DEFAULT_CONFIG_PATH = ".waypoint/config.toml";
|
|
8
8
|
const DEFAULT_DOCS_DIR = ".waypoint/docs";
|
|
9
9
|
const DEFAULT_DOCS_INDEX = ".waypoint/DOCS_INDEX.md";
|
|
@@ -84,18 +84,75 @@ const TIMESTAMPED_WORKSPACE_SECTIONS = new Set([
|
|
|
84
84
|
"## Done Recently",
|
|
85
85
|
]);
|
|
86
86
|
const TIMESTAMPED_ENTRY_PATTERN = /^(?:[-*]|\d+\.)\s+\[\d{4}-\d{2}-\d{2} \d{2}:\d{2} [A-Z]{2,5}\]/;
|
|
87
|
+
function configuredRootDirs(projectRoot, roots, legacyRoot, fallbackRoot) {
|
|
88
|
+
const configuredRoots = roots && roots.length > 0
|
|
89
|
+
? roots
|
|
90
|
+
: legacyRoot
|
|
91
|
+
? [legacyRoot]
|
|
92
|
+
: [fallbackRoot];
|
|
93
|
+
const normalizedRoots = [];
|
|
94
|
+
const seen = new Set();
|
|
95
|
+
for (const root of configuredRoots) {
|
|
96
|
+
const trimmedRoot = root.trim();
|
|
97
|
+
if (trimmedRoot.length === 0) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const resolvedRoot = path.resolve(projectRoot, trimmedRoot);
|
|
101
|
+
let dedupeKey = path.normalize(resolvedRoot);
|
|
102
|
+
if (existsSync(resolvedRoot)) {
|
|
103
|
+
try {
|
|
104
|
+
dedupeKey = realpathSync(resolvedRoot);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
dedupeKey = path.normalize(resolvedRoot);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (seen.has(dedupeKey)) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
seen.add(dedupeKey);
|
|
114
|
+
normalizedRoots.push(resolvedRoot);
|
|
115
|
+
}
|
|
116
|
+
return normalizedRoots.length > 0 ? normalizedRoots : [path.resolve(projectRoot, fallbackRoot)];
|
|
117
|
+
}
|
|
118
|
+
function docsRootDirs(projectRoot, config) {
|
|
119
|
+
return configuredRootDirs(projectRoot, config?.docs_dirs, config?.docs_dir, DEFAULT_DOCS_DIR);
|
|
120
|
+
}
|
|
121
|
+
function plansRootDirs(projectRoot, config) {
|
|
122
|
+
return configuredRootDirs(projectRoot, config?.plans_dirs, config?.plans_dir, DEFAULT_PLANS_DIR);
|
|
123
|
+
}
|
|
124
|
+
function docsSectionHeading(projectRoot, dir) {
|
|
125
|
+
const relativePath = path.relative(projectRoot, dir).split(path.sep).join("/");
|
|
126
|
+
const normalizedPath = relativePath.length === 0 ? "." : relativePath;
|
|
127
|
+
return normalizedPath.endsWith("/") ? normalizedPath : `${normalizedPath}/`;
|
|
128
|
+
}
|
|
87
129
|
function docsIndexSections(projectRoot, config) {
|
|
88
130
|
return [
|
|
89
|
-
{
|
|
90
|
-
heading:
|
|
91
|
-
dir
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
heading:
|
|
95
|
-
dir
|
|
96
|
-
},
|
|
131
|
+
...docsRootDirs(projectRoot, config).map((dir) => ({
|
|
132
|
+
heading: docsSectionHeading(projectRoot, dir),
|
|
133
|
+
dir,
|
|
134
|
+
})),
|
|
135
|
+
...plansRootDirs(projectRoot, config).map((dir) => ({
|
|
136
|
+
heading: docsSectionHeading(projectRoot, dir),
|
|
137
|
+
dir,
|
|
138
|
+
})),
|
|
97
139
|
];
|
|
98
140
|
}
|
|
141
|
+
function buildWaypointConfig(projectRoot, existingConfig, options) {
|
|
142
|
+
const defaults = defaultWaypointConfig({ profile: options.profile });
|
|
143
|
+
return {
|
|
144
|
+
version: existingConfig?.version ?? defaults.version,
|
|
145
|
+
profile: options.profile,
|
|
146
|
+
workspace_file: existingConfig?.workspace_file ?? defaults.workspace_file,
|
|
147
|
+
docs_dirs: configuredRootDirs(projectRoot, existingConfig?.docs_dirs, existingConfig?.docs_dir, DEFAULT_DOCS_DIR).map((dir) => path.relative(projectRoot, dir).split(path.sep).join("/")),
|
|
148
|
+
plans_dirs: configuredRootDirs(projectRoot, existingConfig?.plans_dirs, existingConfig?.plans_dir, DEFAULT_PLANS_DIR).map((dir) => path.relative(projectRoot, dir).split(path.sep).join("/")),
|
|
149
|
+
docs_index_file: existingConfig?.docs_index_file ?? defaults.docs_index_file,
|
|
150
|
+
features: {
|
|
151
|
+
repo_skills: existingConfig?.features?.repo_skills ?? defaults.features?.repo_skills,
|
|
152
|
+
docs_index: existingConfig?.features?.docs_index ?? defaults.features?.docs_index,
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|
|
99
156
|
function ensureDir(dirPath) {
|
|
100
157
|
mkdirSync(dirPath, { recursive: true });
|
|
101
158
|
}
|
|
@@ -288,6 +345,7 @@ function scaffoldOptionalCodex(projectRoot) {
|
|
|
288
345
|
export function initRepository(projectRoot, options) {
|
|
289
346
|
ensureDir(projectRoot);
|
|
290
347
|
migrateLegacyRootFiles(projectRoot);
|
|
348
|
+
const config = buildWaypointConfig(projectRoot, loadWaypointConfig(projectRoot), options);
|
|
291
349
|
// Any Waypoint-owned path removed from the scaffold should be added here
|
|
292
350
|
// so `waypoint init` / `waypoint upgrade` can actively prune stale copies.
|
|
293
351
|
for (const deprecatedPath of [
|
|
@@ -325,9 +383,7 @@ export function initRepository(projectRoot, options) {
|
|
|
325
383
|
writeText(path.join(projectRoot, ".waypoint/agent-operating-manual.md"), readTemplate(".waypoint/agent-operating-manual.md"));
|
|
326
384
|
writeIfMissing(path.join(projectRoot, DEFAULT_MEMORY), readTemplate(".waypoint/MEMORY.md"));
|
|
327
385
|
scaffoldWaypointOptionalTemplates(projectRoot);
|
|
328
|
-
writeText(path.join(projectRoot, DEFAULT_CONFIG_PATH), renderWaypointConfig(
|
|
329
|
-
profile: options.profile,
|
|
330
|
-
}));
|
|
386
|
+
writeText(path.join(projectRoot, DEFAULT_CONFIG_PATH), renderWaypointConfig(config));
|
|
331
387
|
writeIfMissing(path.join(projectRoot, DEFAULT_WORKSPACE), readTemplate("WORKSPACE.md"));
|
|
332
388
|
ensureDir(path.join(projectRoot, DEFAULT_DOCS_DIR));
|
|
333
389
|
ensureDir(path.join(projectRoot, DEFAULT_PLANS_DIR));
|
|
@@ -339,9 +395,10 @@ export function initRepository(projectRoot, options) {
|
|
|
339
395
|
scaffoldSkills(projectRoot);
|
|
340
396
|
scaffoldOptionalCodex(projectRoot);
|
|
341
397
|
appendGitignoreSnippet(projectRoot);
|
|
342
|
-
const
|
|
398
|
+
const docsIndexPath = path.join(projectRoot, config.docs_index_file ?? DEFAULT_DOCS_INDEX);
|
|
399
|
+
const docsIndex = renderDocsIndex(projectRoot, docsIndexSections(projectRoot, config));
|
|
343
400
|
const tracksIndex = renderTracksIndex(projectRoot, path.join(projectRoot, DEFAULT_TRACK_DIR));
|
|
344
|
-
writeText(
|
|
401
|
+
writeText(docsIndexPath, `${docsIndex.content}\n`);
|
|
345
402
|
writeText(path.join(projectRoot, DEFAULT_TRACKS_INDEX), `${tracksIndex.content}\n`);
|
|
346
403
|
return [
|
|
347
404
|
"Initialized Waypoint scaffold",
|
|
@@ -476,27 +533,33 @@ export function doctorRepository(projectRoot) {
|
|
|
476
533
|
}
|
|
477
534
|
}
|
|
478
535
|
const docsIndexPath = path.join(projectRoot, config.docs_index_file ?? DEFAULT_DOCS_INDEX);
|
|
479
|
-
const
|
|
480
|
-
const
|
|
536
|
+
const configuredDocsDirs = docsRootDirs(projectRoot, config);
|
|
537
|
+
const configuredPlansDirs = plansRootDirs(projectRoot, config);
|
|
481
538
|
const docsIndex = renderDocsIndex(projectRoot, docsIndexSections(projectRoot, config));
|
|
482
539
|
const trackDir = path.join(projectRoot, DEFAULT_TRACK_DIR);
|
|
483
540
|
const tracksIndexPath = path.join(projectRoot, DEFAULT_TRACKS_INDEX);
|
|
484
541
|
const tracksIndex = renderTracksIndex(projectRoot, trackDir);
|
|
485
|
-
|
|
542
|
+
for (const docsDir of configuredDocsDirs) {
|
|
543
|
+
if (existsSync(docsDir)) {
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
486
546
|
findings.push({
|
|
487
547
|
severity: "error",
|
|
488
548
|
category: "docs",
|
|
489
|
-
message:
|
|
490
|
-
remediation: "
|
|
549
|
+
message: `${docsSectionHeading(projectRoot, docsDir)} directory is missing.`,
|
|
550
|
+
remediation: "Create the configured docs directory or update `.waypoint/config.toml`.",
|
|
491
551
|
paths: [docsDir],
|
|
492
552
|
});
|
|
493
553
|
}
|
|
494
|
-
|
|
554
|
+
for (const plansDir of configuredPlansDirs) {
|
|
555
|
+
if (existsSync(plansDir)) {
|
|
556
|
+
continue;
|
|
557
|
+
}
|
|
495
558
|
findings.push({
|
|
496
559
|
severity: "error",
|
|
497
560
|
category: "docs",
|
|
498
|
-
message:
|
|
499
|
-
remediation: "
|
|
561
|
+
message: `${docsSectionHeading(projectRoot, plansDir)} directory is missing.`,
|
|
562
|
+
remediation: "Create the configured plans directory or update `.waypoint/config.toml`.",
|
|
500
563
|
paths: [plansDir],
|
|
501
564
|
});
|
|
502
565
|
}
|
package/dist/src/docs-index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { existsSync, readFileSync, readdirSync, realpathSync } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
const SKIP_DIRS = new Set([
|
|
4
4
|
".git",
|
|
@@ -50,18 +50,25 @@ function parseFrontmatter(filePath) {
|
|
|
50
50
|
}
|
|
51
51
|
return { summary, lastUpdated, readWhen };
|
|
52
52
|
}
|
|
53
|
-
function walkDocs(projectRoot, currentDir, output, invalid) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
function walkDocs(projectRoot, currentDir, output, invalid, visitedDirs) {
|
|
54
|
+
const resolvedCurrentDir = realpathSync(currentDir);
|
|
55
|
+
if (visitedDirs.has(resolvedCurrentDir)) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
visitedDirs.add(resolvedCurrentDir);
|
|
59
|
+
for (const entry of readdirSync(currentDir, { withFileTypes: true })) {
|
|
60
|
+
if (entry.isSymbolicLink()) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
64
|
+
if (entry.isDirectory()) {
|
|
65
|
+
if (SKIP_DIRS.has(entry.name)) {
|
|
59
66
|
continue;
|
|
60
67
|
}
|
|
61
|
-
walkDocs(projectRoot, fullPath, output, invalid);
|
|
68
|
+
walkDocs(projectRoot, fullPath, output, invalid, visitedDirs);
|
|
62
69
|
continue;
|
|
63
70
|
}
|
|
64
|
-
if (!
|
|
71
|
+
if (!isMarkdownDoc(entry)) {
|
|
65
72
|
continue;
|
|
66
73
|
}
|
|
67
74
|
const { summary, lastUpdated, readWhen } = parseFrontmatter(fullPath);
|
|
@@ -77,10 +84,13 @@ function collectDocEntries(projectRoot, docsDir) {
|
|
|
77
84
|
const entries = [];
|
|
78
85
|
const invalidDocs = [];
|
|
79
86
|
if (existsSync(docsDir)) {
|
|
80
|
-
walkDocs(projectRoot, docsDir, entries, invalidDocs);
|
|
87
|
+
walkDocs(projectRoot, docsDir, entries, invalidDocs, new Set());
|
|
81
88
|
}
|
|
82
89
|
return { entries, invalidDocs };
|
|
83
90
|
}
|
|
91
|
+
function isMarkdownDoc(entry) {
|
|
92
|
+
return entry.isFile() && entry.name.endsWith(".md") && !SKIP_NAMES.has(entry.name);
|
|
93
|
+
}
|
|
84
94
|
export function renderDocsIndex(projectRoot, sections) {
|
|
85
95
|
const lines = [
|
|
86
96
|
"# Docs Index",
|
package/dist/src/templates.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as TOML from "@iarna/toml";
|
|
1
2
|
import { readFileSync } from "node:fs";
|
|
2
3
|
import { existsSync } from "node:fs";
|
|
3
4
|
import { fileURLToPath } from "node:url";
|
|
@@ -25,7 +26,32 @@ export function templatePath(relativePath) {
|
|
|
25
26
|
export function readTemplate(relativePath) {
|
|
26
27
|
return readFileSync(templatePath(relativePath), "utf8");
|
|
27
28
|
}
|
|
28
|
-
export function
|
|
29
|
-
return
|
|
30
|
-
|
|
29
|
+
export function defaultWaypointConfig(options) {
|
|
30
|
+
return {
|
|
31
|
+
version: 1,
|
|
32
|
+
profile: options.profile,
|
|
33
|
+
workspace_file: ".waypoint/WORKSPACE.md",
|
|
34
|
+
docs_dirs: [".waypoint/docs"],
|
|
35
|
+
plans_dirs: [".waypoint/plans"],
|
|
36
|
+
docs_index_file: ".waypoint/DOCS_INDEX.md",
|
|
37
|
+
features: {
|
|
38
|
+
repo_skills: true,
|
|
39
|
+
docs_index: true,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export function renderWaypointConfig(config) {
|
|
44
|
+
const renderedConfig = {
|
|
45
|
+
version: config.version,
|
|
46
|
+
profile: config.profile,
|
|
47
|
+
workspace_file: config.workspace_file,
|
|
48
|
+
docs_dirs: config.docs_dirs,
|
|
49
|
+
plans_dirs: config.plans_dirs,
|
|
50
|
+
docs_index_file: config.docs_index_file,
|
|
51
|
+
features: config.features ? {
|
|
52
|
+
repo_skills: config.features.repo_skills,
|
|
53
|
+
docs_index: config.features.docs_index,
|
|
54
|
+
} : undefined,
|
|
55
|
+
};
|
|
56
|
+
return TOML.stringify(renderedConfig);
|
|
31
57
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
version = 1
|
|
2
2
|
profile = "__PROFILE__"
|
|
3
3
|
workspace_file = ".waypoint/WORKSPACE.md"
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
docs_dirs = [".waypoint/docs"]
|
|
5
|
+
plans_dirs = [".waypoint/plans"]
|
|
6
6
|
docs_index_file = ".waypoint/DOCS_INDEX.md"
|
|
7
7
|
|
|
8
8
|
[features]
|