waypoint-codex 0.7.0 → 0.8.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 +8 -6
- package/dist/src/core.js +71 -6
- package/dist/src/track-index.js +107 -0
- package/package.json +1 -1
- package/templates/.agents/skills/code-guide-audit/SKILL.md +2 -0
- package/templates/.agents/skills/planning/SKILL.md +2 -0
- package/templates/.agents/skills/work-tracker/SKILL.md +110 -0
- package/templates/.agents/skills/workspace-compress/SKILL.md +3 -0
- package/templates/.waypoint/agent-operating-manual.md +5 -4
- package/templates/.waypoint/docs/README.md +2 -0
- package/templates/.waypoint/scripts/build-track-index.mjs +169 -0
- package/templates/.waypoint/scripts/prepare-context.mjs +24 -0
- package/templates/.waypoint/track/README.md +38 -0
- package/templates/.waypoint/track/_template.md +44 -0
- package/templates/WORKSPACE.md +5 -1
- package/templates/managed-agents-block.md +2 -0
- package/templates/.agents/skills/error-audit/SKILL.md +0 -69
- package/templates/.agents/skills/error-audit/references/error-patterns.md +0 -37
- package/templates/.agents/skills/observability-audit/SKILL.md +0 -67
- package/templates/.agents/skills/observability-audit/references/observability-patterns.md +0 -35
- package/templates/.agents/skills/ux-states-audit/SKILL.md +0 -63
- package/templates/.agents/skills/ux-states-audit/references/ux-patterns.md +0 -34
package/README.md
CHANGED
|
@@ -22,10 +22,12 @@ Waypoint scaffolds a Codex-friendly repo structure built around a few core piece
|
|
|
22
22
|
|
|
23
23
|
- `AGENTS.md` for the startup contract
|
|
24
24
|
- `.waypoint/WORKSPACE.md` for live operational state
|
|
25
|
+
- `.waypoint/track/` for active long-running execution trackers
|
|
25
26
|
- `.waypoint/docs/` for durable project memory
|
|
26
27
|
- `.waypoint/DOCS_INDEX.md` for docs routing
|
|
28
|
+
- `.waypoint/TRACKS_INDEX.md` for tracker routing
|
|
27
29
|
- `.waypoint/context/` for generated startup context
|
|
28
|
-
- `.agents/skills/` for repo-local workflows like planning, audits, and QA
|
|
30
|
+
- `.agents/skills/` for repo-local workflows like planning, tracking, audits, and QA
|
|
29
31
|
|
|
30
32
|
The philosophy is simple:
|
|
31
33
|
|
|
@@ -40,7 +42,7 @@ Waypoint is most useful when you want:
|
|
|
40
42
|
|
|
41
43
|
- multi-session continuity in a real repo
|
|
42
44
|
- a durable docs and workspace structure for agents
|
|
43
|
-
- stronger planning, review, QA, and closeout defaults
|
|
45
|
+
- stronger planning, tracking, review, QA, and closeout defaults
|
|
44
46
|
- repo-local scaffolding instead of a bunch of global mystery behavior
|
|
45
47
|
|
|
46
48
|
If you only use Codex for tiny one-off edits, Waypoint is probably unnecessary.
|
|
@@ -76,9 +78,11 @@ repo/
|
|
|
76
78
|
├── .agents/
|
|
77
79
|
│ └── skills/
|
|
78
80
|
└── .waypoint/
|
|
79
|
-
├── WORKSPACE.md
|
|
80
81
|
├── DOCS_INDEX.md
|
|
82
|
+
├── TRACKS_INDEX.md
|
|
83
|
+
├── WORKSPACE.md
|
|
81
84
|
├── docs/
|
|
85
|
+
├── track/
|
|
82
86
|
├── context/
|
|
83
87
|
├── scripts/
|
|
84
88
|
└── ...
|
|
@@ -126,9 +130,7 @@ Flags you can combine:
|
|
|
126
130
|
Waypoint ships a strong default skill pack for real coding work:
|
|
127
131
|
|
|
128
132
|
- `planning`
|
|
129
|
-
- `
|
|
130
|
-
- `observability-audit`
|
|
131
|
-
- `ux-states-audit`
|
|
133
|
+
- `work-tracker`
|
|
132
134
|
- `docs-sync`
|
|
133
135
|
- `code-guide-audit`
|
|
134
136
|
- `break-it-qa`
|
package/dist/src/core.js
CHANGED
|
@@ -4,14 +4,18 @@ import os from "node:os";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import * as TOML from "@iarna/toml";
|
|
6
6
|
import { renderDocsIndex } from "./docs-index.js";
|
|
7
|
+
import { renderTracksIndex } from "./track-index.js";
|
|
7
8
|
import { readTemplate, renderWaypointConfig, MANAGED_BLOCK_END, MANAGED_BLOCK_START, templatePath } from "./templates.js";
|
|
8
9
|
const DEFAULT_CONFIG_PATH = ".waypoint/config.toml";
|
|
9
10
|
const DEFAULT_DOCS_DIR = ".waypoint/docs";
|
|
10
11
|
const DEFAULT_DOCS_INDEX = ".waypoint/DOCS_INDEX.md";
|
|
12
|
+
const DEFAULT_TRACK_DIR = ".waypoint/track";
|
|
13
|
+
const DEFAULT_TRACKS_INDEX = ".waypoint/TRACKS_INDEX.md";
|
|
11
14
|
const DEFAULT_WORKSPACE = ".waypoint/WORKSPACE.md";
|
|
12
15
|
const STATE_DIR = ".waypoint/state";
|
|
13
16
|
const SYNC_RECORDS_FILE = ".waypoint/state/sync-records.json";
|
|
14
17
|
const TIMESTAMPED_WORKSPACE_SECTIONS = new Set([
|
|
18
|
+
"## Active Trackers",
|
|
15
19
|
"## Current State",
|
|
16
20
|
"## In Progress",
|
|
17
21
|
"## Next",
|
|
@@ -101,6 +105,7 @@ function scaffoldWaypointOptionalTemplates(projectRoot) {
|
|
|
101
105
|
copyTemplateTree(templatePath(".waypoint/automations"), path.join(projectRoot, ".waypoint/automations"));
|
|
102
106
|
copyTemplateTree(templatePath(".waypoint/rules"), path.join(projectRoot, ".waypoint/rules"));
|
|
103
107
|
copyTemplateTree(templatePath(".waypoint/scripts"), path.join(projectRoot, ".waypoint/scripts"));
|
|
108
|
+
copyTemplateTree(templatePath(".waypoint/track"), path.join(projectRoot, ".waypoint/track"));
|
|
104
109
|
}
|
|
105
110
|
function scaffoldOptionalCodex(projectRoot) {
|
|
106
111
|
copyTemplateTree(templatePath(".codex"), path.join(projectRoot, ".codex"));
|
|
@@ -112,6 +117,9 @@ export function initRepository(projectRoot, options) {
|
|
|
112
117
|
"docs/README.md",
|
|
113
118
|
"docs/code-guide.md",
|
|
114
119
|
"docs/legacy-import",
|
|
120
|
+
".agents/skills/error-audit",
|
|
121
|
+
".agents/skills/observability-audit",
|
|
122
|
+
".agents/skills/ux-states-audit",
|
|
115
123
|
"WAYPOINT_MIGRATION.md",
|
|
116
124
|
".agents/skills/waypoint-planning",
|
|
117
125
|
".agents/skills/waypoint-docs",
|
|
@@ -145,6 +153,7 @@ export function initRepository(projectRoot, options) {
|
|
|
145
153
|
}));
|
|
146
154
|
writeIfMissing(path.join(projectRoot, DEFAULT_WORKSPACE), readTemplate("WORKSPACE.md"));
|
|
147
155
|
ensureDir(path.join(projectRoot, DEFAULT_DOCS_DIR));
|
|
156
|
+
ensureDir(path.join(projectRoot, DEFAULT_TRACK_DIR));
|
|
148
157
|
writeIfMissing(path.join(projectRoot, ".waypoint/docs/README.md"), readTemplate(".waypoint/docs/README.md"));
|
|
149
158
|
writeIfMissing(path.join(projectRoot, ".waypoint/docs/code-guide.md"), readTemplate(".waypoint/docs/code-guide.md"));
|
|
150
159
|
upsertManagedBlock(path.join(projectRoot, "AGENTS.md"), readTemplate("managed-agents-block.md"));
|
|
@@ -154,13 +163,15 @@ export function initRepository(projectRoot, options) {
|
|
|
154
163
|
}
|
|
155
164
|
appendGitignoreSnippet(projectRoot);
|
|
156
165
|
const docsIndex = renderDocsIndex(projectRoot, path.join(projectRoot, DEFAULT_DOCS_DIR));
|
|
166
|
+
const tracksIndex = renderTracksIndex(projectRoot, path.join(projectRoot, DEFAULT_TRACK_DIR));
|
|
157
167
|
writeText(path.join(projectRoot, DEFAULT_DOCS_INDEX), `${docsIndex.content}\n`);
|
|
168
|
+
writeText(path.join(projectRoot, DEFAULT_TRACKS_INDEX), `${tracksIndex.content}\n`);
|
|
158
169
|
return [
|
|
159
170
|
"Initialized Waypoint scaffold",
|
|
160
171
|
"Installed managed AGENTS block",
|
|
161
|
-
"Created .waypoint/WORKSPACE.md and .waypoint/
|
|
172
|
+
"Created .waypoint/WORKSPACE.md, .waypoint/docs/, and .waypoint/track/ scaffold",
|
|
162
173
|
"Installed repo-local Waypoint skills",
|
|
163
|
-
"Generated .waypoint/DOCS_INDEX.md",
|
|
174
|
+
"Generated .waypoint/DOCS_INDEX.md and .waypoint/TRACKS_INDEX.md",
|
|
164
175
|
];
|
|
165
176
|
}
|
|
166
177
|
export function loadWaypointConfig(projectRoot) {
|
|
@@ -366,6 +377,7 @@ export function doctorRepository(projectRoot) {
|
|
|
366
377
|
const workspaceText = readFileSync(workspacePath, "utf8");
|
|
367
378
|
for (const section of [
|
|
368
379
|
"## Active Goal",
|
|
380
|
+
"## Active Trackers",
|
|
369
381
|
"## Current State",
|
|
370
382
|
"## In Progress",
|
|
371
383
|
"## Next",
|
|
@@ -398,6 +410,7 @@ export function doctorRepository(projectRoot) {
|
|
|
398
410
|
path.join(projectRoot, ".waypoint", "agent-operating-manual.md"),
|
|
399
411
|
path.join(projectRoot, ".waypoint", "scripts", "prepare-context.mjs"),
|
|
400
412
|
path.join(projectRoot, ".waypoint", "scripts", "build-docs-index.mjs"),
|
|
413
|
+
path.join(projectRoot, ".waypoint", "scripts", "build-track-index.mjs"),
|
|
401
414
|
]) {
|
|
402
415
|
if (!existsSync(requiredFile)) {
|
|
403
416
|
findings.push({
|
|
@@ -412,6 +425,9 @@ export function doctorRepository(projectRoot) {
|
|
|
412
425
|
const docsDir = path.join(projectRoot, config.docs_dir ?? DEFAULT_DOCS_DIR);
|
|
413
426
|
const docsIndexPath = path.join(projectRoot, config.docs_index_file ?? DEFAULT_DOCS_INDEX);
|
|
414
427
|
const docsIndex = renderDocsIndex(projectRoot, docsDir);
|
|
428
|
+
const trackDir = path.join(projectRoot, DEFAULT_TRACK_DIR);
|
|
429
|
+
const tracksIndexPath = path.join(projectRoot, DEFAULT_TRACKS_INDEX);
|
|
430
|
+
const tracksIndex = renderTracksIndex(projectRoot, trackDir);
|
|
415
431
|
if (!existsSync(docsDir)) {
|
|
416
432
|
findings.push({
|
|
417
433
|
severity: "error",
|
|
@@ -448,11 +464,56 @@ export function doctorRepository(projectRoot) {
|
|
|
448
464
|
paths: [docsIndexPath],
|
|
449
465
|
});
|
|
450
466
|
}
|
|
467
|
+
if (!existsSync(trackDir)) {
|
|
468
|
+
findings.push({
|
|
469
|
+
severity: "error",
|
|
470
|
+
category: "track",
|
|
471
|
+
message: ".waypoint/track/ directory is missing.",
|
|
472
|
+
remediation: "Run `waypoint init` to scaffold track files.",
|
|
473
|
+
paths: [trackDir],
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
for (const relPath of tracksIndex.invalidTracks) {
|
|
477
|
+
findings.push({
|
|
478
|
+
severity: "warn",
|
|
479
|
+
category: "track",
|
|
480
|
+
message: `Tracker is missing valid frontmatter or status: ${relPath}`,
|
|
481
|
+
remediation: "Add `summary`, `last_updated`, `status`, and `read_when` frontmatter using the track template.",
|
|
482
|
+
paths: [path.join(projectRoot, relPath)],
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
if (!existsSync(tracksIndexPath)) {
|
|
486
|
+
findings.push({
|
|
487
|
+
severity: "warn",
|
|
488
|
+
category: "track",
|
|
489
|
+
message: ".waypoint/TRACKS_INDEX.md is missing.",
|
|
490
|
+
remediation: "Run `waypoint sync` to generate the tracks index.",
|
|
491
|
+
paths: [tracksIndexPath],
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
else if (readFileSync(tracksIndexPath, "utf8").trimEnd() !== tracksIndex.content.trimEnd()) {
|
|
495
|
+
findings.push({
|
|
496
|
+
severity: "warn",
|
|
497
|
+
category: "track",
|
|
498
|
+
message: ".waypoint/TRACKS_INDEX.md is stale.",
|
|
499
|
+
remediation: "Run `waypoint sync` to rebuild the tracks index.",
|
|
500
|
+
paths: [tracksIndexPath],
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
if (existsSync(workspacePath) &&
|
|
504
|
+
tracksIndex.activeTrackPaths.length > 0 &&
|
|
505
|
+
!tracksIndex.activeTrackPaths.some((trackPath) => readFileSync(workspacePath, "utf8").includes(trackPath))) {
|
|
506
|
+
findings.push({
|
|
507
|
+
severity: "warn",
|
|
508
|
+
category: "track",
|
|
509
|
+
message: "Workspace does not reference any active tracker file.",
|
|
510
|
+
remediation: "Add the active `.waypoint/track/*.md` file paths under `## Active Trackers` in `.waypoint/WORKSPACE.md`.",
|
|
511
|
+
paths: [workspacePath, ...tracksIndex.activeTrackPaths.map((trackPath) => path.join(projectRoot, trackPath))],
|
|
512
|
+
});
|
|
513
|
+
}
|
|
451
514
|
for (const skillName of [
|
|
452
515
|
"planning",
|
|
453
|
-
"
|
|
454
|
-
"observability-audit",
|
|
455
|
-
"ux-states-audit",
|
|
516
|
+
"work-tracker",
|
|
456
517
|
"docs-sync",
|
|
457
518
|
"code-guide-audit",
|
|
458
519
|
"break-it-qa",
|
|
@@ -528,8 +589,12 @@ export function syncRepository(projectRoot) {
|
|
|
528
589
|
const docsDir = path.join(projectRoot, config.docs_dir ?? DEFAULT_DOCS_DIR);
|
|
529
590
|
const docsIndexPath = path.join(projectRoot, config.docs_index_file ?? DEFAULT_DOCS_INDEX);
|
|
530
591
|
const docsIndex = renderDocsIndex(projectRoot, docsDir);
|
|
592
|
+
const trackDir = path.join(projectRoot, DEFAULT_TRACK_DIR);
|
|
593
|
+
const tracksIndexPath = path.join(projectRoot, DEFAULT_TRACKS_INDEX);
|
|
594
|
+
const tracksIndex = renderTracksIndex(projectRoot, trackDir);
|
|
531
595
|
writeText(docsIndexPath, `${docsIndex.content}\n`);
|
|
532
|
-
|
|
596
|
+
writeText(tracksIndexPath, `${tracksIndex.content}\n`);
|
|
597
|
+
const results = ["Rebuilt .waypoint/DOCS_INDEX.md", "Rebuilt .waypoint/TRACKS_INDEX.md"];
|
|
533
598
|
const featureMap = config.features ?? {};
|
|
534
599
|
if (featureMap.rules) {
|
|
535
600
|
results.push(...syncRules(projectRoot));
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const VALID_TRACK_STATUSES = new Set(["active", "blocked", "paused", "done", "archived"]);
|
|
4
|
+
const ACTIVE_TRACK_STATUSES = new Set(["active", "blocked", "paused"]);
|
|
5
|
+
const SKIP_NAMES = new Set(["README.md", "CHANGELOG.md", "LICENSE.md"]);
|
|
6
|
+
function shouldSkipTrackFile(entry) {
|
|
7
|
+
return SKIP_NAMES.has(entry) || entry.startsWith("_");
|
|
8
|
+
}
|
|
9
|
+
function parseFrontmatter(filePath) {
|
|
10
|
+
const text = readFileSync(filePath, "utf8");
|
|
11
|
+
if (!text.startsWith("---\n")) {
|
|
12
|
+
return { summary: "", lastUpdated: "", readWhen: [], status: "" };
|
|
13
|
+
}
|
|
14
|
+
const endIndex = text.indexOf("\n---\n", 4);
|
|
15
|
+
if (endIndex === -1) {
|
|
16
|
+
return { summary: "", lastUpdated: "", readWhen: [], status: "" };
|
|
17
|
+
}
|
|
18
|
+
const frontmatter = text.slice(4, endIndex);
|
|
19
|
+
let summary = "";
|
|
20
|
+
let lastUpdated = "";
|
|
21
|
+
let status = "";
|
|
22
|
+
const readWhen = [];
|
|
23
|
+
let collectingReadWhen = false;
|
|
24
|
+
for (const rawLine of frontmatter.split("\n")) {
|
|
25
|
+
const line = rawLine.trim();
|
|
26
|
+
if (line.startsWith("summary:")) {
|
|
27
|
+
summary = line.slice("summary:".length).trim().replace(/^['"]|['"]$/g, "");
|
|
28
|
+
collectingReadWhen = false;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (line.startsWith("last_updated:")) {
|
|
32
|
+
lastUpdated = line.slice("last_updated:".length).trim().replace(/^['"]|['"]$/g, "");
|
|
33
|
+
collectingReadWhen = false;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (line.startsWith("status:")) {
|
|
37
|
+
status = line.slice("status:".length).trim().replace(/^['"]|['"]$/g, "").toLowerCase();
|
|
38
|
+
collectingReadWhen = false;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (line.startsWith("read_when:")) {
|
|
42
|
+
collectingReadWhen = true;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (collectingReadWhen && line.startsWith("- ")) {
|
|
46
|
+
readWhen.push(line.slice(2).trim());
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (collectingReadWhen && line.length > 0) {
|
|
50
|
+
collectingReadWhen = false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return { summary, lastUpdated, readWhen, status };
|
|
54
|
+
}
|
|
55
|
+
function walkTracks(projectRoot, currentDir, output, invalid) {
|
|
56
|
+
for (const entry of readdirSync(currentDir)) {
|
|
57
|
+
const fullPath = path.join(currentDir, entry);
|
|
58
|
+
const stat = statSync(fullPath);
|
|
59
|
+
if (stat.isDirectory()) {
|
|
60
|
+
walkTracks(projectRoot, fullPath, output, invalid);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (!entry.endsWith(".md") || shouldSkipTrackFile(entry)) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const { summary, lastUpdated, readWhen, status } = parseFrontmatter(fullPath);
|
|
67
|
+
const relPath = path.relative(projectRoot, fullPath);
|
|
68
|
+
if (!summary || !lastUpdated || readWhen.length === 0 || !VALID_TRACK_STATUSES.has(status)) {
|
|
69
|
+
invalid.push(relPath);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
output.push({ path: relPath, summary, readWhen, status });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
export function renderTracksIndex(projectRoot, trackDir) {
|
|
76
|
+
const entries = [];
|
|
77
|
+
const invalidTracks = [];
|
|
78
|
+
if (existsSync(trackDir)) {
|
|
79
|
+
walkTracks(projectRoot, trackDir, entries, invalidTracks);
|
|
80
|
+
}
|
|
81
|
+
const lines = [
|
|
82
|
+
"# Tracks Index",
|
|
83
|
+
"",
|
|
84
|
+
"Auto-generated by `waypoint sync` / `waypoint doctor`. Read active trackers when resuming long-running work.",
|
|
85
|
+
"",
|
|
86
|
+
"## .waypoint/track/",
|
|
87
|
+
"",
|
|
88
|
+
];
|
|
89
|
+
if (entries.length === 0) {
|
|
90
|
+
lines.push("No tracker files found.");
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
for (const entry of entries.sort((a, b) => a.path.localeCompare(b.path))) {
|
|
94
|
+
lines.push(`- **${entry.path}** — [${entry.status}] ${entry.summary}`);
|
|
95
|
+
lines.push(` Read when: ${entry.readWhen.join("; ")}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
lines.push("");
|
|
99
|
+
return {
|
|
100
|
+
content: `${lines.join("\n")}`,
|
|
101
|
+
invalidTracks,
|
|
102
|
+
activeTrackPaths: entries
|
|
103
|
+
.filter((entry) => ACTIVE_TRACK_STATUSES.has(entry.status))
|
|
104
|
+
.map((entry) => entry.path)
|
|
105
|
+
.sort((a, b) => a.localeCompare(b)),
|
|
106
|
+
};
|
|
107
|
+
}
|
package/package.json
CHANGED
|
@@ -47,6 +47,8 @@ Skip rules that genuinely do not apply, but say that you skipped them.
|
|
|
47
47
|
|
|
48
48
|
This skill is narrower than `pre-pr-hygiene`. Use that other skill for broader ship-readiness.
|
|
49
49
|
|
|
50
|
+
If this audit produces a large remediation campaign, create or update a tracker under `.waypoint/track/` before switching into implementation so the fix list does not live only in chat.
|
|
51
|
+
|
|
50
52
|
## Step 4: Verify Evidence
|
|
51
53
|
|
|
52
54
|
Ground each finding in the actual code.
|
|
@@ -36,6 +36,8 @@ The plan belongs in the repo, not only in chat.
|
|
|
36
36
|
- Make sure the doc remains discoverable through the routed docs layer.
|
|
37
37
|
- In chat, return only a concise summary plus the path to the plan doc.
|
|
38
38
|
|
|
39
|
+
If the planned implementation will be large, multi-step, or likely to span multiple sessions, also create or update a tracker under `.waypoint/track/` and link it from `WORKSPACE.md` before implementation begins.
|
|
40
|
+
|
|
39
41
|
## The Core Loop
|
|
40
42
|
|
|
41
43
|
```
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: work-tracker
|
|
3
|
+
description: Create or maintain a durable tracker under `.waypoint/track/` for large multi-step work. Use when implementation will span multiple sessions, when an audit or review produces many fix items, when verification has a long checklist, or whenever `WORKSPACE.md` would become too detailed if it tried to hold the whole execution log.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Work Tracker
|
|
7
|
+
|
|
8
|
+
Use this skill when the work is too large, too long-running, or too itemized to live safely in `WORKSPACE.md`.
|
|
9
|
+
|
|
10
|
+
This skill owns the execution tracker layer:
|
|
11
|
+
|
|
12
|
+
- create or update `.waypoint/track/<slug>.md`
|
|
13
|
+
- keep `WORKSPACE.md` pointing at the active tracker
|
|
14
|
+
- move detailed checklists and progress into the tracker instead of bloating the workspace
|
|
15
|
+
|
|
16
|
+
## Read First
|
|
17
|
+
|
|
18
|
+
Before tracking:
|
|
19
|
+
|
|
20
|
+
1. Read `.waypoint/SOUL.md`
|
|
21
|
+
2. Read `.waypoint/agent-operating-manual.md`
|
|
22
|
+
3. Read `.waypoint/WORKSPACE.md`
|
|
23
|
+
4. Read `.waypoint/context/MANIFEST.md`
|
|
24
|
+
5. Read every file listed in that manifest
|
|
25
|
+
6. Read `.waypoint/track/README.md`
|
|
26
|
+
|
|
27
|
+
## When A Tracker Is Required
|
|
28
|
+
|
|
29
|
+
Create or update a tracker when any of these are true:
|
|
30
|
+
|
|
31
|
+
- the work will likely span multiple sessions
|
|
32
|
+
- there are many actionable items to implement
|
|
33
|
+
- an audit, QA pass, or review produced a remediation campaign
|
|
34
|
+
- verification requires a substantial checklist
|
|
35
|
+
- `WORKSPACE.md` would become noisy if it carried all the detail
|
|
36
|
+
|
|
37
|
+
Small, single-shot work does not need a tracker.
|
|
38
|
+
|
|
39
|
+
## Step 1: Choose The Tracker File
|
|
40
|
+
|
|
41
|
+
- Use `.waypoint/track/<kebab-case-slug>.md`.
|
|
42
|
+
- If a relevant tracker already exists, update it instead of creating a competing one.
|
|
43
|
+
- Keep one tracker per coherent workstream, not one tracker per tiny edit.
|
|
44
|
+
|
|
45
|
+
## Step 2: Set The Frontmatter
|
|
46
|
+
|
|
47
|
+
Trackers need:
|
|
48
|
+
|
|
49
|
+
```yaml
|
|
50
|
+
---
|
|
51
|
+
summary: One-line description
|
|
52
|
+
last_updated: "2026-03-13 11:38 PDT"
|
|
53
|
+
status: active
|
|
54
|
+
read_when:
|
|
55
|
+
- resuming this workstream
|
|
56
|
+
---
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Valid statuses:
|
|
60
|
+
|
|
61
|
+
- `active`
|
|
62
|
+
- `blocked`
|
|
63
|
+
- `paused`
|
|
64
|
+
- `done`
|
|
65
|
+
- `archived`
|
|
66
|
+
|
|
67
|
+
Use `active` unless there is a clear reason not to.
|
|
68
|
+
|
|
69
|
+
## Step 3: Structure The Tracker
|
|
70
|
+
|
|
71
|
+
A good tracker usually includes:
|
|
72
|
+
|
|
73
|
+
- `Goal`
|
|
74
|
+
- `Source`
|
|
75
|
+
- `Current State`
|
|
76
|
+
- `Next`
|
|
77
|
+
- `Workstreams`
|
|
78
|
+
- `Verification`
|
|
79
|
+
- `Decisions`
|
|
80
|
+
- `Notes`
|
|
81
|
+
|
|
82
|
+
Use checklists when there are many concrete items. Use timestamped bullets for materially revised state.
|
|
83
|
+
|
|
84
|
+
## Step 4: Link It From The Workspace
|
|
85
|
+
|
|
86
|
+
Add or update a bullet under `## Active Trackers` in `.waypoint/WORKSPACE.md` that points at the tracker path and states the current phase or next step.
|
|
87
|
+
|
|
88
|
+
`WORKSPACE.md` should answer "what matters right now?"
|
|
89
|
+
The tracker should answer "what exactly is happening across the whole workstream?"
|
|
90
|
+
|
|
91
|
+
## Step 5: Maintain It During Execution
|
|
92
|
+
|
|
93
|
+
- Update `last_updated` whenever you materially change the tracker.
|
|
94
|
+
- Mark completed items done instead of deleting the record.
|
|
95
|
+
- Add blockers, new tasks, and verification status as the work evolves.
|
|
96
|
+
- When the workstream finishes, set `status: done` or `status: archived`.
|
|
97
|
+
|
|
98
|
+
Do not let the tracker become fiction. It must match reality.
|
|
99
|
+
|
|
100
|
+
## Step 6: Distill Durable Knowledge
|
|
101
|
+
|
|
102
|
+
If the tracker reveals durable architecture, rollout, or debugging knowledge, move that durable knowledge into `.waypoint/docs/` and leave the tracker focused on execution state.
|
|
103
|
+
|
|
104
|
+
## Report
|
|
105
|
+
|
|
106
|
+
When you create or update a tracker, report:
|
|
107
|
+
|
|
108
|
+
- the tracker path
|
|
109
|
+
- the current status
|
|
110
|
+
- what `WORKSPACE.md` now points to
|
|
@@ -39,6 +39,7 @@ Ask one question:
|
|
|
39
39
|
|
|
40
40
|
Keep only the answer to that question in the workspace. Usually that means:
|
|
41
41
|
|
|
42
|
+
- active tracker pointers
|
|
42
43
|
- current focus
|
|
43
44
|
- latest verified state
|
|
44
45
|
- open blockers or risks
|
|
@@ -52,6 +53,7 @@ Usually remove or collapse:
|
|
|
52
53
|
- validation transcripts
|
|
53
54
|
- old milestone history
|
|
54
55
|
- duplicated durable documentation
|
|
56
|
+
- per-item implementation checklists that belong in `.waypoint/track/`
|
|
55
57
|
|
|
56
58
|
Compression is documentation quality, not data loss.
|
|
57
59
|
|
|
@@ -66,6 +68,7 @@ When editing the workspace:
|
|
|
66
68
|
5. Do not turn the workspace into an archive, changelog, or debug notebook.
|
|
67
69
|
|
|
68
70
|
If durable context is missing from `.waypoint/docs/`, add or refresh the smallest coherent routed doc before removing it from the workspace.
|
|
71
|
+
If execution detail is still active but too large for the workspace, move it into `.waypoint/track/` instead of deleting it.
|
|
69
72
|
|
|
70
73
|
## Step 4: Protect User-Owned State
|
|
71
74
|
|
|
@@ -33,8 +33,9 @@ Do not skip this sequence.
|
|
|
33
33
|
The repository should contain the context the next agent needs.
|
|
34
34
|
|
|
35
35
|
- `.waypoint/WORKSPACE.md` is the live operational record: in progress, current state, next steps
|
|
36
|
+
- `.waypoint/track/` is the durable execution-tracking layer for active long-running work
|
|
36
37
|
- `.waypoint/docs/` is the durable project memory: architecture, decisions, integration notes, debugging knowledge, and durable plans
|
|
37
|
-
- `.waypoint/context/` is the generated session context bundle: current git/PR/doc index state
|
|
38
|
+
- `.waypoint/context/` is the generated session context bundle: current git/PR/doc/track index state
|
|
38
39
|
|
|
39
40
|
If something important lives only in your head or in the chat transcript, the repo is under-documented.
|
|
40
41
|
|
|
@@ -43,8 +44,10 @@ If something important lives only in your head or in the chat transcript, the re
|
|
|
43
44
|
- Read code before editing it.
|
|
44
45
|
- Follow the repo's documented patterns when they are healthy.
|
|
45
46
|
- Update `.waypoint/WORKSPACE.md` as live execution state when progress meaningfully changes. In multi-topic sections, prefix new or materially revised bullets with a local timestamp like `[2026-03-06 20:10 PST]`.
|
|
47
|
+
- For large multi-step work, create or update a tracker in `.waypoint/track/`, keep detailed execution state there, and point at it from `## Active Trackers` in `.waypoint/WORKSPACE.md`.
|
|
46
48
|
- Update `.waypoint/docs/` when durable knowledge changes, and refresh each changed routable doc's `last_updated` field.
|
|
47
49
|
- Rebuild `.waypoint/DOCS_INDEX.md` whenever routable docs change.
|
|
50
|
+
- Rebuild `.waypoint/TRACKS_INDEX.md` whenever tracker files change.
|
|
48
51
|
- Use the repo-local skills and optional reviewer agents instead of improvising from scratch.
|
|
49
52
|
- Do not kill long-running subagents or reviewer agents just because they are slow. Wait unless they are clearly stuck, failed, or the user redirects the work.
|
|
50
53
|
|
|
@@ -64,9 +67,7 @@ Do not document every trivial implementation detail. Document the non-obvious, d
|
|
|
64
67
|
## When to use Waypoint skills
|
|
65
68
|
|
|
66
69
|
- `planning` for non-trivial changes
|
|
67
|
-
- `
|
|
68
|
-
- `observability-audit` when production debugging signals look weak
|
|
69
|
-
- `ux-states-audit` when async/data-driven UI likely lacks loading, empty, or error states
|
|
70
|
+
- `work-tracker` when large multi-step work needs durable progress tracking in `.waypoint/track/`
|
|
70
71
|
- `docs-sync` when routed docs may be stale, missing, or inconsistent with the codebase
|
|
71
72
|
- `code-guide-audit` when a specific feature or file set needs a targeted coding-guide compliance check
|
|
72
73
|
- `break-it-qa` when a browser-facing feature should be attacked with invalid inputs, refreshes, repeated clicks, wrong action order, or other adversarial manual QA
|
|
@@ -13,6 +13,8 @@ Put the durable context here that the next agent will need to continue the work:
|
|
|
13
13
|
|
|
14
14
|
These are **project docs**, not Waypoint internals.
|
|
15
15
|
|
|
16
|
+
Do not use `.waypoint/docs/` as the execution tracker layer for active long-running work. That belongs under `.waypoint/track/`.
|
|
17
|
+
|
|
16
18
|
Every routable doc needs YAML frontmatter:
|
|
17
19
|
|
|
18
20
|
```yaml
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const VALID_TRACK_STATUSES = new Set(["active", "blocked", "paused", "done", "archived"]);
|
|
8
|
+
const ACTIVE_TRACK_STATUSES = new Set(["active", "blocked", "paused"]);
|
|
9
|
+
const SKIP_NAMES = new Set(["README.md", "CHANGELOG.md", "LICENSE.md"]);
|
|
10
|
+
|
|
11
|
+
export function findProjectRoot(startDir) {
|
|
12
|
+
let current = path.resolve(startDir);
|
|
13
|
+
while (true) {
|
|
14
|
+
if (existsSync(path.join(current, ".waypoint", "config.toml"))) {
|
|
15
|
+
return current;
|
|
16
|
+
}
|
|
17
|
+
const parent = path.dirname(current);
|
|
18
|
+
if (parent === current) {
|
|
19
|
+
return path.resolve(startDir);
|
|
20
|
+
}
|
|
21
|
+
current = parent;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function detectProjectRoot() {
|
|
26
|
+
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
27
|
+
const scriptBasedRoot = findProjectRoot(path.resolve(scriptDir, "../.."));
|
|
28
|
+
if (existsSync(path.join(scriptBasedRoot, ".waypoint", "config.toml"))) {
|
|
29
|
+
return scriptBasedRoot;
|
|
30
|
+
}
|
|
31
|
+
return findProjectRoot(process.cwd());
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function shouldSkipTrackFile(entry) {
|
|
35
|
+
return SKIP_NAMES.has(entry) || entry.startsWith("_");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function parseFrontmatter(filePath) {
|
|
39
|
+
const text = readFileSync(filePath, "utf8");
|
|
40
|
+
if (!text.startsWith("---\n")) {
|
|
41
|
+
return { summary: "", lastUpdated: "", readWhen: [], status: "" };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const endIndex = text.indexOf("\n---\n", 4);
|
|
45
|
+
if (endIndex === -1) {
|
|
46
|
+
return { summary: "", lastUpdated: "", readWhen: [], status: "" };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const frontmatter = text.slice(4, endIndex);
|
|
50
|
+
let summary = "";
|
|
51
|
+
let lastUpdated = "";
|
|
52
|
+
let status = "";
|
|
53
|
+
const readWhen = [];
|
|
54
|
+
let collectingReadWhen = false;
|
|
55
|
+
|
|
56
|
+
for (const rawLine of frontmatter.split("\n")) {
|
|
57
|
+
const line = rawLine.trim();
|
|
58
|
+
if (line.startsWith("summary:")) {
|
|
59
|
+
summary = line.slice("summary:".length).trim().replace(/^['"]|['"]$/g, "");
|
|
60
|
+
collectingReadWhen = false;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (line.startsWith("last_updated:")) {
|
|
64
|
+
lastUpdated = line.slice("last_updated:".length).trim().replace(/^['"]|['"]$/g, "");
|
|
65
|
+
collectingReadWhen = false;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (line.startsWith("status:")) {
|
|
69
|
+
status = line.slice("status:".length).trim().replace(/^['"]|['"]$/g, "").toLowerCase();
|
|
70
|
+
collectingReadWhen = false;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (line.startsWith("read_when:")) {
|
|
74
|
+
collectingReadWhen = true;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (collectingReadWhen && line.startsWith("- ")) {
|
|
78
|
+
readWhen.push(line.slice(2).trim());
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (collectingReadWhen && line.length > 0) {
|
|
82
|
+
collectingReadWhen = false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return { summary, lastUpdated, readWhen, status };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function walkTracks(projectRoot, currentDir, output, invalid) {
|
|
90
|
+
for (const entry of readdirSync(currentDir)) {
|
|
91
|
+
const fullPath = path.join(currentDir, entry);
|
|
92
|
+
const stat = statSync(fullPath);
|
|
93
|
+
if (stat.isDirectory()) {
|
|
94
|
+
walkTracks(projectRoot, fullPath, output, invalid);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (!entry.endsWith(".md") || shouldSkipTrackFile(entry)) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const { summary, lastUpdated, readWhen, status } = parseFrontmatter(fullPath);
|
|
103
|
+
if (!summary || !lastUpdated || readWhen.length === 0 || !VALID_TRACK_STATUSES.has(status)) {
|
|
104
|
+
invalid.push(path.relative(projectRoot, fullPath));
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
output.push({
|
|
109
|
+
path: path.relative(projectRoot, fullPath),
|
|
110
|
+
summary,
|
|
111
|
+
readWhen,
|
|
112
|
+
status,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function renderTracksIndex(projectRoot) {
|
|
118
|
+
const trackDir = path.join(projectRoot, ".waypoint", "track");
|
|
119
|
+
const entries = [];
|
|
120
|
+
const invalidTracks = [];
|
|
121
|
+
|
|
122
|
+
if (existsSync(trackDir)) {
|
|
123
|
+
walkTracks(projectRoot, trackDir, entries, invalidTracks);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const lines = [
|
|
127
|
+
"# Tracks Index",
|
|
128
|
+
"",
|
|
129
|
+
"Auto-generated by `.waypoint/scripts/build-track-index.mjs`. Read active trackers when resuming long-running work.",
|
|
130
|
+
"",
|
|
131
|
+
"## .waypoint/track/",
|
|
132
|
+
"",
|
|
133
|
+
];
|
|
134
|
+
|
|
135
|
+
if (entries.length === 0) {
|
|
136
|
+
lines.push("No tracker files found.");
|
|
137
|
+
} else {
|
|
138
|
+
entries.sort((a, b) => a.path.localeCompare(b.path));
|
|
139
|
+
for (const entry of entries) {
|
|
140
|
+
lines.push(`- **${entry.path}** — [${entry.status}] ${entry.summary}`);
|
|
141
|
+
lines.push(` Read when: ${entry.readWhen.join("; ")}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
lines.push("");
|
|
146
|
+
return {
|
|
147
|
+
content: `${lines.join("\n")}\n`,
|
|
148
|
+
invalidTracks,
|
|
149
|
+
activeTracks: entries
|
|
150
|
+
.filter((entry) => ACTIVE_TRACK_STATUSES.has(entry.status))
|
|
151
|
+
.map((entry) => entry.path)
|
|
152
|
+
.sort((a, b) => a.localeCompare(b)),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function writeTracksIndex(projectRoot) {
|
|
157
|
+
const outputPath = path.join(projectRoot, ".waypoint", "TRACKS_INDEX.md");
|
|
158
|
+
const rendered = renderTracksIndex(projectRoot);
|
|
159
|
+
writeFileSync(outputPath, rendered.content, "utf8");
|
|
160
|
+
return { outputPath, activeTracks: rendered.activeTracks, invalidTracks: rendered.invalidTracks };
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const isDirectExecution = process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
|
|
164
|
+
|
|
165
|
+
if (isDirectExecution) {
|
|
166
|
+
const projectRoot = detectProjectRoot();
|
|
167
|
+
const { outputPath } = writeTracksIndex(projectRoot);
|
|
168
|
+
console.log(`Wrote ${outputPath}`);
|
|
169
|
+
}
|
|
@@ -7,6 +7,7 @@ import path from "node:path";
|
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
|
|
9
9
|
import { findProjectRoot, writeDocsIndex } from "./build-docs-index.mjs";
|
|
10
|
+
import { writeTracksIndex } from "./build-track-index.mjs";
|
|
10
11
|
|
|
11
12
|
const __filename = fileURLToPath(import.meta.url);
|
|
12
13
|
const __dirname = path.dirname(__filename);
|
|
@@ -437,6 +438,21 @@ function writeContextFile(contextDir, name, title, body) {
|
|
|
437
438
|
return filePath;
|
|
438
439
|
}
|
|
439
440
|
|
|
441
|
+
function writeActiveTrackers(contextDir, projectRoot, activeTracks) {
|
|
442
|
+
return writeContextFile(
|
|
443
|
+
contextDir,
|
|
444
|
+
"ACTIVE_TRACKERS.md",
|
|
445
|
+
"Active Trackers",
|
|
446
|
+
activeTracks.length === 0
|
|
447
|
+
? "No active tracker files found."
|
|
448
|
+
: [
|
|
449
|
+
"These trackers should be read when resuming long-running work:",
|
|
450
|
+
"",
|
|
451
|
+
...activeTracks.map((trackPath) => `- \`${trackPath}\``),
|
|
452
|
+
].join("\n"),
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
|
|
440
456
|
function main() {
|
|
441
457
|
const projectRoot = detectProjectRoot();
|
|
442
458
|
const contextDir = path.join(projectRoot, ".waypoint", "context");
|
|
@@ -448,6 +464,7 @@ function main() {
|
|
|
448
464
|
: null;
|
|
449
465
|
|
|
450
466
|
const docsIndexPath = writeDocsIndex(projectRoot);
|
|
467
|
+
const { outputPath: tracksIndexPath, activeTracks } = writeTracksIndex(projectRoot);
|
|
451
468
|
|
|
452
469
|
const currentDatetimePath = writeContextFile(
|
|
453
470
|
contextDir,
|
|
@@ -590,6 +607,7 @@ function main() {
|
|
|
590
607
|
].join("\n")
|
|
591
608
|
);
|
|
592
609
|
const recentThreadPath = writeRecentThread(contextDir, projectRoot, threadIdOverride);
|
|
610
|
+
const activeTrackersPath = writeActiveTrackers(contextDir, projectRoot, activeTracks);
|
|
593
611
|
|
|
594
612
|
const manifestPath = path.join(contextDir, "MANIFEST.md");
|
|
595
613
|
const manifestLines = [
|
|
@@ -606,6 +624,8 @@ function main() {
|
|
|
606
624
|
`- \`${path.relative(projectRoot, prsPath)}\` — open and recently merged pull requests`,
|
|
607
625
|
`- \`${path.relative(projectRoot, recentThreadPath)}\` — latest meaningful turns from the local Codex session for this repo`,
|
|
608
626
|
`- \`${path.relative(projectRoot, docsIndexPath)}\` — current docs index`,
|
|
627
|
+
`- \`${path.relative(projectRoot, tracksIndexPath)}\` — current tracker index`,
|
|
628
|
+
`- \`${path.relative(projectRoot, activeTrackersPath)}\` — active tracker summary`,
|
|
609
629
|
"",
|
|
610
630
|
"## Stable source-of-truth files to read before this manifest",
|
|
611
631
|
"",
|
|
@@ -613,6 +633,10 @@ function main() {
|
|
|
613
633
|
"- `.waypoint/agent-operating-manual.md`",
|
|
614
634
|
"- `.waypoint/WORKSPACE.md`",
|
|
615
635
|
"",
|
|
636
|
+
"## Active tracker files to read after this manifest",
|
|
637
|
+
"",
|
|
638
|
+
...(activeTracks.length > 0 ? activeTracks.map((trackPath) => `- \`${trackPath}\``) : ["- None."]),
|
|
639
|
+
"",
|
|
616
640
|
`Generated by: \`${path.relative(projectRoot, fileURLToPath(import.meta.url))}\``,
|
|
617
641
|
"",
|
|
618
642
|
];
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Waypoint Trackers
|
|
2
|
+
|
|
3
|
+
This directory holds active execution trackers for long-running work.
|
|
4
|
+
|
|
5
|
+
Use `.waypoint/track/` when the work is too large to fit safely in `WORKSPACE.md`, especially for:
|
|
6
|
+
|
|
7
|
+
- multi-session implementation campaigns
|
|
8
|
+
- broad audits followed by remediation
|
|
9
|
+
- large fix lists or rollout work
|
|
10
|
+
- verification or review loops that will take time to close
|
|
11
|
+
|
|
12
|
+
Tracker files are **execution state**, not general project memory.
|
|
13
|
+
|
|
14
|
+
- Keep durable architecture, decisions, and long-term reference material in `.waypoint/docs/`.
|
|
15
|
+
- Keep `WORKSPACE.md` short and current.
|
|
16
|
+
- Put detailed checklists, per-item status, blockers, and verification progress in `.waypoint/track/`.
|
|
17
|
+
|
|
18
|
+
Every tracker needs YAML frontmatter:
|
|
19
|
+
|
|
20
|
+
```yaml
|
|
21
|
+
---
|
|
22
|
+
summary: One-line description
|
|
23
|
+
last_updated: "2026-03-13 11:38 PDT"
|
|
24
|
+
status: active
|
|
25
|
+
read_when:
|
|
26
|
+
- resuming the workstream
|
|
27
|
+
---
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Valid tracker statuses:
|
|
31
|
+
|
|
32
|
+
- `active`
|
|
33
|
+
- `blocked`
|
|
34
|
+
- `paused`
|
|
35
|
+
- `done`
|
|
36
|
+
- `archived`
|
|
37
|
+
|
|
38
|
+
`WORKSPACE.md` should point at the active tracker file under `## Active Trackers`.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: One-line description of the workstream
|
|
3
|
+
last_updated: "2026-03-13 11:38 PDT"
|
|
4
|
+
status: active
|
|
5
|
+
read_when:
|
|
6
|
+
- resuming this workstream
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Tracker Title
|
|
10
|
+
|
|
11
|
+
## Goal
|
|
12
|
+
|
|
13
|
+
What outcome this tracker is trying to reach.
|
|
14
|
+
|
|
15
|
+
## Source
|
|
16
|
+
|
|
17
|
+
- User request, audit, plan, or review thread that kicked off the work.
|
|
18
|
+
|
|
19
|
+
## Current State
|
|
20
|
+
|
|
21
|
+
- [2026-03-13 11:38 PDT] Current truth about the work.
|
|
22
|
+
|
|
23
|
+
## Next
|
|
24
|
+
|
|
25
|
+
- [2026-03-13 11:38 PDT] The next concrete action.
|
|
26
|
+
|
|
27
|
+
## Workstreams
|
|
28
|
+
|
|
29
|
+
### 1. Stream Name
|
|
30
|
+
|
|
31
|
+
- [ ] First task
|
|
32
|
+
- [ ] Second task
|
|
33
|
+
|
|
34
|
+
## Verification
|
|
35
|
+
|
|
36
|
+
- [ ] Verification step
|
|
37
|
+
|
|
38
|
+
## Decisions
|
|
39
|
+
|
|
40
|
+
- [2026-03-13 11:38 PDT] Decision and rationale.
|
|
41
|
+
|
|
42
|
+
## Notes
|
|
43
|
+
|
|
44
|
+
- Useful details that do not belong in `WORKSPACE.md`.
|
package/templates/WORKSPACE.md
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
# Workspace
|
|
2
2
|
|
|
3
|
-
Timestamp discipline: Prefix new or materially revised bullets in `Current State`, `In Progress`, `Next`, `Parked`, and `Done Recently` with `[YYYY-MM-DD HH:MM TZ]`.
|
|
3
|
+
Timestamp discipline: Prefix new or materially revised bullets in `Active Trackers`, `Current State`, `In Progress`, `Next`, `Parked`, and `Done Recently` with `[YYYY-MM-DD HH:MM TZ]`.
|
|
4
4
|
|
|
5
5
|
## Active Goal
|
|
6
6
|
|
|
7
7
|
Describe the main thing currently being built or changed.
|
|
8
8
|
|
|
9
|
+
## Active Trackers
|
|
10
|
+
|
|
11
|
+
List any active tracker docs under `.waypoint/track/`, with the current phase or next step.
|
|
12
|
+
|
|
9
13
|
## Current State
|
|
10
14
|
|
|
11
15
|
What is already true right now?
|
|
@@ -32,8 +32,10 @@ This is mandatory, not optional.
|
|
|
32
32
|
|
|
33
33
|
Working rules:
|
|
34
34
|
- Keep `.waypoint/WORKSPACE.md` current as the live execution state, with timestamped new or materially revised entries in multi-topic sections
|
|
35
|
+
- For large multi-step work, create or update `.waypoint/track/<slug>.md`, keep detailed execution state there, and point to it from `## Active Trackers` in `.waypoint/WORKSPACE.md`
|
|
35
36
|
- Update `.waypoint/docs/` when behavior or durable project knowledge changes, and refresh `last_updated` on touched routable docs
|
|
36
37
|
- Use the repo-local skills Waypoint ships for structured workflows when relevant
|
|
38
|
+
- Use `work-tracker` when a long-running implementation, remediation, or verification campaign needs durable progress tracking
|
|
37
39
|
- Use `docs-sync` when the docs may be stale or a change altered shipped behavior, contracts, routes, or commands
|
|
38
40
|
- Use `code-guide-audit` for a targeted coding-guide compliance pass on a specific feature, file set, or change slice
|
|
39
41
|
- Use `break-it-qa` for browser-facing features that should be tested against invalid inputs, refreshes, repeated clicks, wrong navigation, and other adversarial user behavior
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: error-audit
|
|
3
|
-
description: Audit code for silent error swallowing, fallbacks to degraded alternatives, backwards compatibility shims, and UI that fails to show errors to the user. Finds and fixes all occurrences in the specified scope.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Error Audit
|
|
7
|
-
|
|
8
|
-
The core principle: **every error belongs to the user**. Not to a catch block, not to a console, not to a null return. Scan the specified code, fix every violation, report what changed.
|
|
9
|
-
|
|
10
|
-
## Read First
|
|
11
|
-
|
|
12
|
-
1. Read `.waypoint/SOUL.md`
|
|
13
|
-
2. Read `.waypoint/agent-operating-manual.md`
|
|
14
|
-
3. Read `WORKSPACE.md`
|
|
15
|
-
4. Read `.waypoint/context/MANIFEST.md`
|
|
16
|
-
5. Read every file listed in the manifest
|
|
17
|
-
6. Read `references/error-patterns.md`
|
|
18
|
-
|
|
19
|
-
## Step 0: Understand the app's error mechanisms
|
|
20
|
-
|
|
21
|
-
Before fixing anything, identify how this app surfaces errors to users — toast notifications, error banners, error boundaries, returned error states, alert dialogs, inline messages. Use these patterns exclusively. Don't invent a new one.
|
|
22
|
-
|
|
23
|
-
## Anti-patterns to find and fix
|
|
24
|
-
|
|
25
|
-
**Silent error swallowing — backend/logic layer:**
|
|
26
|
-
- Empty catch blocks: `catch(e) {}`
|
|
27
|
-
- Log-and-continue with execution proceeding normally
|
|
28
|
-
- `.catch(() => {})` on promises
|
|
29
|
-
- Functions returning `null`, `undefined`, or empty defaults on failure instead of throwing
|
|
30
|
-
|
|
31
|
-
**Silent error swallowing — UI layer:**
|
|
32
|
-
- Data fetching catches an error and returns null/empty -> component renders blank with no explanation
|
|
33
|
-
- Error boundaries that catch but show nothing (or a generic "something went wrong" with no recovery path)
|
|
34
|
-
- `try/catch` in a loader or server action that swallows the error and returns partial/empty data
|
|
35
|
-
- Async operations where the UI has no error state at all — success renders fine, failure renders identical to loading or empty
|
|
36
|
-
|
|
37
|
-
**Fallbacks to degraded alternatives:**
|
|
38
|
-
- Catch -> silently switch to a worse model, API, or service
|
|
39
|
-
- Catch -> return cached or stale data without telling the user
|
|
40
|
-
- Catch -> offline/degraded mode with no visible indication
|
|
41
|
-
|
|
42
|
-
**Backwards compatibility shims:**
|
|
43
|
-
- `if (legacyFormat)` or `if (oldVersion)` branches
|
|
44
|
-
- Deprecated fields still being populated alongside new ones
|
|
45
|
-
- Old code paths running in parallel with new ones
|
|
46
|
-
|
|
47
|
-
**Config defaults that hide misconfiguration:**
|
|
48
|
-
- `process.env.X || 'fallback'` for required values — missing required config is a startup crash, not a default
|
|
49
|
-
- Optional environment variables that should be required
|
|
50
|
-
|
|
51
|
-
**Optional chaining hiding missing required data:**
|
|
52
|
-
- `user?.profile?.name ?? 'Guest'` when profile must always exist — the absence is a bug, not an edge case to handle silently
|
|
53
|
-
|
|
54
|
-
## Fix principles
|
|
55
|
-
|
|
56
|
-
- Throw or re-throw rather than catch-and-continue
|
|
57
|
-
- In the UI: every error path must render something visible — use the app's established error display mechanism
|
|
58
|
-
- Required config missing at startup -> log a clear message and exit
|
|
59
|
-
- Delete fallback branches — don't comment them out
|
|
60
|
-
- When unsure if a fallback was intentional, flag it in your report rather than guessing
|
|
61
|
-
|
|
62
|
-
## Reference files
|
|
63
|
-
|
|
64
|
-
- `references/error-patterns.md` — Concrete anti-patterns with structural descriptions, examples, and false positive notes. Read this before starting the audit.
|
|
65
|
-
|
|
66
|
-
## Report
|
|
67
|
-
|
|
68
|
-
After fixing, summarize by file: what was found, what the fix was. Be specific — file paths and the pattern removed.
|
|
69
|
-
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# Error Anti-Patterns Reference
|
|
2
|
-
|
|
3
|
-
Patterns to identify when auditing error handling. Each section describes the anti-pattern structurally — what the code does, not just what keywords to grep for.
|
|
4
|
-
|
|
5
|
-
## Silent error swallowing
|
|
6
|
-
|
|
7
|
-
- empty catch blocks
|
|
8
|
-
- `.catch(() => {})`
|
|
9
|
-
- broad exception handlers that return defaults
|
|
10
|
-
- ignored Go errors via `_`
|
|
11
|
-
|
|
12
|
-
## Log-and-continue
|
|
13
|
-
|
|
14
|
-
An error gets logged, but execution continues as if the operation succeeded.
|
|
15
|
-
|
|
16
|
-
## Return-null-on-failure
|
|
17
|
-
|
|
18
|
-
The function converts a real operational failure into what looks like a normal "empty" result.
|
|
19
|
-
|
|
20
|
-
## Invisible degradation
|
|
21
|
-
|
|
22
|
-
The code silently falls back to a worse model, API, cache, or degraded mode with no visible signal.
|
|
23
|
-
|
|
24
|
-
## Config defaults hiding misconfiguration
|
|
25
|
-
|
|
26
|
-
Required settings should fail loudly, not silently pick a fallback.
|
|
27
|
-
|
|
28
|
-
## UI error blindness
|
|
29
|
-
|
|
30
|
-
Failure should not render the same as loading or empty.
|
|
31
|
-
|
|
32
|
-
Quality bar:
|
|
33
|
-
|
|
34
|
-
- confirm the issue is real in context
|
|
35
|
-
- prefer concrete fixes over broad rewrites
|
|
36
|
-
- use existing repo patterns for user-visible error handling
|
|
37
|
-
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: observability-audit
|
|
3
|
-
description: Audit code for observability gaps — debug logs left in, errors caught without being logged, missing context on log entries, and untracked slow operations. Uses the app's existing observability tooling exclusively.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Observability Audit
|
|
7
|
-
|
|
8
|
-
Code that works locally but is impossible to debug in production. This skill finds and fixes observability gaps using whatever tools the app already has.
|
|
9
|
-
|
|
10
|
-
## Read First
|
|
11
|
-
|
|
12
|
-
1. Read `.waypoint/SOUL.md`
|
|
13
|
-
2. Read `.waypoint/agent-operating-manual.md`
|
|
14
|
-
3. Read `WORKSPACE.md`
|
|
15
|
-
4. Read `.waypoint/context/MANIFEST.md`
|
|
16
|
-
5. Read every file listed in the manifest
|
|
17
|
-
6. Read `references/observability-patterns.md`
|
|
18
|
-
|
|
19
|
-
## Step 0: Research existing observability tooling
|
|
20
|
-
|
|
21
|
-
Before anything else, explore the codebase to understand what's already in use:
|
|
22
|
-
|
|
23
|
-
- Error tracking
|
|
24
|
-
- Logging
|
|
25
|
-
- APM / metrics
|
|
26
|
-
- Analytics
|
|
27
|
-
- Any custom logger or telemetry utilities
|
|
28
|
-
|
|
29
|
-
Read how they're configured and how they're used. All fixes must use these — never introduce a new observability dependency or pattern.
|
|
30
|
-
|
|
31
|
-
## What to look for
|
|
32
|
-
|
|
33
|
-
**Debug artifacts left in production code**
|
|
34
|
-
|
|
35
|
-
**Errors that disappear**
|
|
36
|
-
|
|
37
|
-
**Missing context on log entries**
|
|
38
|
-
|
|
39
|
-
**Untracked slow or critical operations**
|
|
40
|
-
|
|
41
|
-
See `references/observability-patterns.md` for concrete patterns.
|
|
42
|
-
|
|
43
|
-
## Process
|
|
44
|
-
|
|
45
|
-
1. Research existing tooling
|
|
46
|
-
2. Identify the scope
|
|
47
|
-
3. Find every instance of the anti-patterns
|
|
48
|
-
4. Fix using the existing tooling and patterns
|
|
49
|
-
5. Remove debug artifacts, add context to thin logs, add tracking where missing
|
|
50
|
-
6. Report changes
|
|
51
|
-
|
|
52
|
-
## Fix principles
|
|
53
|
-
|
|
54
|
-
- Every caught error should be logged with enough context to reproduce the problem
|
|
55
|
-
- Use the existing logger/tracker — never introduce a second one
|
|
56
|
-
- Debug `console.log` goes away entirely — no conversion to structured log, just deleted
|
|
57
|
-
- Log context should include: what operation, what failed, relevant IDs
|
|
58
|
-
- Don't add logging to every function — focus on boundaries and critical paths
|
|
59
|
-
|
|
60
|
-
## Reference files
|
|
61
|
-
|
|
62
|
-
- `references/observability-patterns.md` — Detection patterns, bad/fix examples for debug artifacts, missing logging, missing context, untracked operations. Read before starting the audit.
|
|
63
|
-
|
|
64
|
-
## Report
|
|
65
|
-
|
|
66
|
-
Summarize by file: what was removed, what was added or improved, what context was missing and is now included.
|
|
67
|
-
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# Observability Anti-Patterns Reference
|
|
2
|
-
|
|
3
|
-
Use this file to guide observability audits.
|
|
4
|
-
|
|
5
|
-
## Debug artifacts
|
|
6
|
-
|
|
7
|
-
- `console.log`, `console.debug`, `print`, `fmt.Printf` in non-CLI production paths
|
|
8
|
-
- commented-out debug statements
|
|
9
|
-
- `debugger` and focused tests left behind
|
|
10
|
-
|
|
11
|
-
## Errors without useful traces
|
|
12
|
-
|
|
13
|
-
- catch/except blocks that rethrow or return without logging context
|
|
14
|
-
- tracker calls with no metadata
|
|
15
|
-
- logs that say "failed" without saying what failed
|
|
16
|
-
|
|
17
|
-
## Missing context
|
|
18
|
-
|
|
19
|
-
- no user, entity, request, or job identifiers
|
|
20
|
-
- no operation name
|
|
21
|
-
- no correlation/request ID at service boundaries
|
|
22
|
-
|
|
23
|
-
## Slow paths with no timing
|
|
24
|
-
|
|
25
|
-
- external API calls
|
|
26
|
-
- critical database queries
|
|
27
|
-
- background jobs without start/complete/fail visibility
|
|
28
|
-
- webhook handlers with no event-level logging
|
|
29
|
-
|
|
30
|
-
Quality bar:
|
|
31
|
-
|
|
32
|
-
- use the existing observability stack
|
|
33
|
-
- improve debugging value, not log volume
|
|
34
|
-
- focus on boundaries and critical paths
|
|
35
|
-
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: ux-states-audit
|
|
3
|
-
description: Audit UI code for missing loading states, empty states, and error states. Every async operation and data-driven UI must handle all three. Finds gaps and implements the missing states using the app's existing patterns.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# UX States Audit
|
|
7
|
-
|
|
8
|
-
Every piece of UI that fetches data or triggers async work has three states beyond the happy path: **loading**, **empty**, and **error**. LLMs implement the happy path and leave the rest blank. This skill finds and fills those gaps.
|
|
9
|
-
|
|
10
|
-
This is distinct from `error-audit`: `error-audit` finds errors that are suppressed. This finds states that were never implemented.
|
|
11
|
-
|
|
12
|
-
## Read First
|
|
13
|
-
|
|
14
|
-
1. Read `.waypoint/SOUL.md`
|
|
15
|
-
2. Read `.waypoint/agent-operating-manual.md`
|
|
16
|
-
3. Read `WORKSPACE.md`
|
|
17
|
-
4. Read `.waypoint/context/MANIFEST.md`
|
|
18
|
-
5. Read every file listed in the manifest
|
|
19
|
-
6. Read `references/ux-patterns.md`
|
|
20
|
-
|
|
21
|
-
## Step 0: Understand existing patterns
|
|
22
|
-
|
|
23
|
-
Before touching anything, read the codebase to understand how it currently handles these states:
|
|
24
|
-
|
|
25
|
-
- loading components or primitives
|
|
26
|
-
- empty state patterns
|
|
27
|
-
- error display patterns
|
|
28
|
-
|
|
29
|
-
Use these patterns exclusively. Don't introduce a new loading spinner if one already exists.
|
|
30
|
-
|
|
31
|
-
## What to look for
|
|
32
|
-
|
|
33
|
-
**Missing loading state**
|
|
34
|
-
|
|
35
|
-
**Missing empty state**
|
|
36
|
-
|
|
37
|
-
**Missing error state**
|
|
38
|
-
|
|
39
|
-
See `references/ux-patterns.md` for concrete patterns.
|
|
40
|
-
|
|
41
|
-
## Process
|
|
42
|
-
|
|
43
|
-
1. Identify the scope
|
|
44
|
-
2. Find every component that fetches data or triggers async work
|
|
45
|
-
3. For each: check whether loading, empty, and error states are handled
|
|
46
|
-
4. Implement missing states using the patterns found in Step 0
|
|
47
|
-
5. Report what was added, by component
|
|
48
|
-
|
|
49
|
-
## Fix principles
|
|
50
|
-
|
|
51
|
-
- Loading states should be immediate
|
|
52
|
-
- Empty states should explain the situation and, where appropriate, offer an action
|
|
53
|
-
- Error states should say what went wrong and what the user can do
|
|
54
|
-
- Don't invent new UI primitives — use what already exists
|
|
55
|
-
|
|
56
|
-
## Reference files
|
|
57
|
-
|
|
58
|
-
- `references/ux-patterns.md` — Detection patterns and examples for missing loading, empty, and error states. Read before starting the audit.
|
|
59
|
-
|
|
60
|
-
## Report
|
|
61
|
-
|
|
62
|
-
Summarize by component: which states were missing, what was added.
|
|
63
|
-
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# UX State Patterns Reference
|
|
2
|
-
|
|
3
|
-
Use this file to guide UX state audits.
|
|
4
|
-
|
|
5
|
-
## Missing loading state
|
|
6
|
-
|
|
7
|
-
Look for:
|
|
8
|
-
|
|
9
|
-
- fetch starts and nothing changes visually
|
|
10
|
-
- button-triggered async action with no pending state
|
|
11
|
-
- form submission with no disabled or in-progress signal
|
|
12
|
-
|
|
13
|
-
## Missing empty state
|
|
14
|
-
|
|
15
|
-
Look for:
|
|
16
|
-
|
|
17
|
-
- empty lists rendering blank space
|
|
18
|
-
- search results with no explanation when empty
|
|
19
|
-
- dashboard widgets vanishing instead of explaining that no data exists
|
|
20
|
-
|
|
21
|
-
## Missing error state
|
|
22
|
-
|
|
23
|
-
Look for:
|
|
24
|
-
|
|
25
|
-
- fetch failure rendering the same as loading
|
|
26
|
-
- mutation failure with no user-visible feedback
|
|
27
|
-
- components returning blank/null on failure
|
|
28
|
-
|
|
29
|
-
Quality bar:
|
|
30
|
-
|
|
31
|
-
- use the repo's established UI primitives
|
|
32
|
-
- implement all three states where relevant
|
|
33
|
-
- favor clarity over decorative treatment
|
|
34
|
-
|