forgetrail 0.4.20 → 0.5.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/CONTINUATION_PROMPT.md +5 -5
- package/INITIAL_PROMPT.md +15 -15
- package/README.md +5 -5
- package/TRACKING_SCHEMA.md +16 -7
- package/TRY_FORGETRAIL.md +3 -3
- package/WORKFLOW.md +50 -45
- package/content/AGENT_INTEGRATION_claude.md +1 -1
- package/content/AGENT_INTEGRATION_cursor.md +3 -3
- package/content/AGENT_INTEGRATION_generic.md +5 -5
- package/content/AGENT_INTEGRATION_grok.md +8 -8
- package/content/COMPANION_TOOLS.md +1 -1
- package/content/FORGETRAIL_LITE.md +72 -68
- package/content/FORGETRAIL_PROGRESS.md +3 -3
- package/content/GENESIS_SPEC_PROMPT.md +1 -1
- package/content/GENESIS_STUB.md +1 -1
- package/content/GREENFIELD_INTAKE.md +6 -6
- package/content/KICKOFF_WITHOUT_MCP.md +1 -1
- package/content/NEW_PROJECT_BOOTSTRAP.md +27 -27
- package/content/PLAN_MODE_PATTERNS.md +4 -4
- package/content/POST_BOOTSTRAP_USER_MESSAGE.md +1 -1
- package/content/SESSION_RESUME_MCP.md +7 -7
- package/content/companion-tools.json +1 -1
- package/content/cursor-rules/forgetrail-phase-status.mdc +8 -9
- package/content/examples/two-session-continuity.md +31 -67
- package/content/forgetrail-workspace-README.md +2 -2
- package/content/hooks/README.md +3 -3
- package/content/hooks/session-start.mjs +58 -63
- package/content/hooks/session-stop.mjs +49 -30
- package/content/hooks/validate-tracking-core.mjs +34 -1
- package/content/scripts/forgetrail-dev-launcher.mjs +12 -2
- package/content/skills/forgetrail/SKILL.md +21 -21
- package/content/skills/forgetrail/SKILL_FACTS.md +2 -2
- package/docs/CONTEXT_PROMPT.md +1 -1
- package/docs/NPM.md +8 -8
- package/docs/PHASE_1_BRIEF.md +7 -7
- package/package.json +69 -70
- package/scripts/forgetrail-cli.mjs +1 -1
- package/scripts/install-lib.mjs +1 -0
- package/scripts/install.mjs +6 -23
- package/scripts/publish-gate.mjs +6 -4
- package/scripts/tracking-cutover.test.mjs +109 -0
- package/scripts/workspace-index.mjs +9 -1
package/package.json
CHANGED
|
@@ -1,70 +1,69 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "forgetrail",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"private": false,
|
|
5
|
-
"description": "ForgeTrail: a persistent development system for building software with AI agents. CLI, Lite protocol, and methodology templates.",
|
|
6
|
-
"license": "Apache-2.0",
|
|
7
|
-
"type": "module",
|
|
8
|
-
"bin": {
|
|
9
|
-
"forgetrail": "./scripts/forgetrail-cli.mjs"
|
|
10
|
-
},
|
|
11
|
-
"files": [
|
|
12
|
-
"scripts/",
|
|
13
|
-
"content/",
|
|
14
|
-
"docs/",
|
|
15
|
-
"prompts/",
|
|
16
|
-
"WORKFLOW.md",
|
|
17
|
-
"TRACKING_SCHEMA.md",
|
|
18
|
-
"workflow_tracking.json",
|
|
19
|
-
"INITIAL_PROMPT.md",
|
|
20
|
-
"CONTINUATION_PROMPT.md",
|
|
21
|
-
"TRY_FORGETRAIL.md",
|
|
22
|
-
"README.md",
|
|
23
|
-
"LICENSE"
|
|
24
|
-
],
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
"mcp"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "forgetrail",
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "ForgeTrail: a persistent development system for building software with AI agents. CLI, Lite protocol, and methodology templates.",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"bin": {
|
|
9
|
+
"forgetrail": "./scripts/forgetrail-cli.mjs"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"scripts/",
|
|
13
|
+
"content/",
|
|
14
|
+
"docs/",
|
|
15
|
+
"prompts/",
|
|
16
|
+
"WORKFLOW.md",
|
|
17
|
+
"TRACKING_SCHEMA.md",
|
|
18
|
+
"workflow_tracking.json",
|
|
19
|
+
"INITIAL_PROMPT.md",
|
|
20
|
+
"CONTINUATION_PROMPT.md",
|
|
21
|
+
"TRY_FORGETRAIL.md",
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=20"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"forgetrail",
|
|
30
|
+
"mcp",
|
|
31
|
+
"ai-agents",
|
|
32
|
+
"cursor",
|
|
33
|
+
"claude",
|
|
34
|
+
"methodology",
|
|
35
|
+
"lite"
|
|
36
|
+
],
|
|
37
|
+
"author": {
|
|
38
|
+
"name": "Catalyst Forge LLC",
|
|
39
|
+
"url": "https://catalystforge.com"
|
|
40
|
+
},
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "git+https://github.com/Catalyst-Forge-LLC/forgetrail.git"
|
|
44
|
+
},
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/Catalyst-Forge-LLC/forgetrail/issues"
|
|
47
|
+
},
|
|
48
|
+
"homepage": "https://forgetrail.dev",
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public"
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"workspace:index": "node scripts/workspace-index.mjs",
|
|
54
|
+
"install:forgetrail": "node scripts/install-forgetrail.mjs",
|
|
55
|
+
"install:lite": "node scripts/install-forgetrail-lite.mjs",
|
|
56
|
+
"link:global": "node scripts/link-global.mjs",
|
|
57
|
+
"mcp": "node scripts/mcp-status.mjs dev",
|
|
58
|
+
"mcp:build": "node scripts/mcp-status.mjs build",
|
|
59
|
+
"mcp:status": "node scripts/mcp-status.mjs status",
|
|
60
|
+
"mcp:ping": "node scripts/mcp-status.mjs ping",
|
|
61
|
+
"mcp:cursor-config": "node scripts/mcp-status.mjs cursor-config",
|
|
62
|
+
"mcp:inspector": "node scripts/mcp-status.mjs inspector",
|
|
63
|
+
"ship": "pnpm --dir site run ship",
|
|
64
|
+
"site:dev": "pnpm --dir site dev",
|
|
65
|
+
"site:build": "pnpm --dir site run build",
|
|
66
|
+
"site:deploy": "pnpm --dir site run ship",
|
|
67
|
+
"pack:check": "node scripts/publish-gate.mjs"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -36,7 +36,7 @@ Install options:
|
|
|
36
36
|
--with-genesis-stub With --lite: also create docs/GENESIS.md stub
|
|
37
37
|
--force, -f Overwrite existing files
|
|
38
38
|
--dry-run Preview without writing
|
|
39
|
-
--skip-tracking
|
|
39
|
+
--skip-tracking Accepted and ignored. A tracking JSON file is not installed.
|
|
40
40
|
--path, -p <dir> Install elsewhere (default: current directory)
|
|
41
41
|
--help, -h Show help
|
|
42
42
|
|
package/scripts/install-lib.mjs
CHANGED
|
@@ -109,6 +109,7 @@ export function copyContentDir(fromDir, toDir, opts) {
|
|
|
109
109
|
ensureDir(toDir, opts.dryRun);
|
|
110
110
|
for (const name of readdirSync(fromDir)) {
|
|
111
111
|
if (name === "skills") continue;
|
|
112
|
+
if (name === "LITE_WORKFLOW_TRACKING.json") continue;
|
|
112
113
|
if (MCP_ONLY_CONTENT.has(name)) continue;
|
|
113
114
|
copyPath(join(fromDir, name), join(toDir, name), opts);
|
|
114
115
|
}
|
package/scripts/install.mjs
CHANGED
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
const ROOT_FILES = [
|
|
18
18
|
"WORKFLOW.md",
|
|
19
19
|
"TRACKING_SCHEMA.md",
|
|
20
|
-
"workflow_tracking.json",
|
|
21
20
|
"INITIAL_PROMPT.md",
|
|
22
21
|
"CONTINUATION_PROMPT.md",
|
|
23
22
|
"LICENSE",
|
|
@@ -70,14 +69,6 @@ export function runInstallForgetrail(rawArgv, { defaultToCwd = false } = {}) {
|
|
|
70
69
|
copyPath(join(FORGETRAIL_ROOT, "prompts"), join(forgetrailDir, "prompts"), opts);
|
|
71
70
|
copyContentDir(contentSrc, contentDest, opts);
|
|
72
71
|
|
|
73
|
-
if (!args.skipTracking) {
|
|
74
|
-
copyPath(
|
|
75
|
-
join(FORGETRAIL_ROOT, "workflow_tracking.json"),
|
|
76
|
-
join(target, ".forgetrail", "workflow_tracking.json"),
|
|
77
|
-
{ ...opts, force: args.force }
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
72
|
const hooksSrc = join(FORGETRAIL_ROOT, "content", "hooks");
|
|
82
73
|
const hooksDest = join(target, ".forgetrail", "hooks");
|
|
83
74
|
ensureDir(hooksDest, args.dryRun);
|
|
@@ -95,7 +86,7 @@ export function runInstallForgetrail(rawArgv, { defaultToCwd = false } = {}) {
|
|
|
95
86
|
console.log("\nDone.");
|
|
96
87
|
console.log(" Methodology: _forgetrail/WORKFLOW.md");
|
|
97
88
|
console.log(" First chat: _forgetrail/INITIAL_PROMPT.md");
|
|
98
|
-
console.log("
|
|
89
|
+
console.log(" Project record: appledger/ (not workflow_tracking.json)");
|
|
99
90
|
console.log(" Hooks: .forgetrail/hooks/ (enforced via .cursor/hooks.json)");
|
|
100
91
|
return { target, mode: "full" };
|
|
101
92
|
}
|
|
@@ -127,14 +118,6 @@ export function runInstallLite(rawArgv, { defaultToCwd = false } = {}) {
|
|
|
127
118
|
);
|
|
128
119
|
}
|
|
129
120
|
|
|
130
|
-
if (!args.skipTracking) {
|
|
131
|
-
copyPath(
|
|
132
|
-
join(contentDir, "LITE_WORKFLOW_TRACKING.json"),
|
|
133
|
-
join(forgetrailDir, "workflow_tracking.json"),
|
|
134
|
-
opts
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
121
|
const hooksSrc = join(contentDir, "hooks");
|
|
139
122
|
const hooksDest = join(forgetrailDir, "hooks");
|
|
140
123
|
ensureDir(hooksDest, args.dryRun);
|
|
@@ -158,7 +141,7 @@ export function runInstallLite(rawArgv, { defaultToCwd = false } = {}) {
|
|
|
158
141
|
|
|
159
142
|
console.log("\nDone.");
|
|
160
143
|
console.log(" Protocol: .forgetrail/FORGETRAIL_LITE.md");
|
|
161
|
-
console.log("
|
|
144
|
+
console.log(" Project record: appledger/ (a tracking JSON file is not installed)");
|
|
162
145
|
console.log(" Hooks: .forgetrail/hooks/ (enforced via .cursor/hooks.json)");
|
|
163
146
|
if (args.withGenesisStub) {
|
|
164
147
|
console.log(" Genesis: docs/GENESIS.md (stub — replace with your spec)");
|
|
@@ -177,12 +160,12 @@ Usage:
|
|
|
177
160
|
Options:
|
|
178
161
|
--path, -p <dir> Target project root (default: current directory for \`forgetrail\` CLI)
|
|
179
162
|
--force, -f Overwrite existing files
|
|
180
|
-
--skip-tracking
|
|
163
|
+
--skip-tracking Accepted and ignored. A tracking JSON file is not installed.
|
|
181
164
|
--dry-run Print actions only
|
|
182
165
|
|
|
183
166
|
Installs:
|
|
184
167
|
<target>/_forgetrail/ WORKFLOW, templates, prompts, content/ (curated)
|
|
185
|
-
<target>/.forgetrail/
|
|
168
|
+
<target>/.forgetrail/ hooks only. Project state belongs in appledger/.
|
|
186
169
|
`.trim();
|
|
187
170
|
|
|
188
171
|
export const INSTALL_LITE_HELP = `
|
|
@@ -195,11 +178,11 @@ Usage:
|
|
|
195
178
|
Options:
|
|
196
179
|
--path, -p <dir> Target project root (default: current directory for \`forgetrail\` CLI)
|
|
197
180
|
--force, -f Overwrite existing files
|
|
198
|
-
--skip-tracking
|
|
181
|
+
--skip-tracking Accepted and ignored. A tracking JSON file is not installed.
|
|
199
182
|
--with-genesis-stub Also create docs/GENESIS.md stub (for the Try path)
|
|
200
183
|
--dry-run Print actions only
|
|
201
184
|
|
|
202
|
-
Installs into <target>/.forgetrail/ (FORGETRAIL_LITE.md,
|
|
185
|
+
Installs into <target>/.forgetrail/ (FORGETRAIL_LITE.md, cursor rules, hooks). Project state belongs in appledger/.
|
|
203
186
|
With --with-genesis-stub, also writes docs/GENESIS.md from content/GENESIS_STUB.md.
|
|
204
187
|
See TRY_FORGETRAIL.md in the ForgeTrail repo for the no-MCP prove-it recipe.
|
|
205
188
|
`.trim();
|
package/scripts/publish-gate.mjs
CHANGED
|
@@ -98,11 +98,13 @@ for (const needed of ["WORKFLOW.md", "README.md", "LICENSE", "content/FORGETRAIL
|
|
|
98
98
|
console.log("\n✓ forgetrail pack check passed");
|
|
99
99
|
console.log(` forgetrail@${root.version}`);
|
|
100
100
|
console.log(` forgetrail-mcp@${mcp.version} (build ok at ${MCP_ENTRY})`);
|
|
101
|
-
console.log("\nPublish (you run these):");
|
|
102
|
-
console.log(" pnpm publish --access public");
|
|
103
|
-
console.log(" pnpm --dir mcp-server publish --access public");
|
|
104
|
-
console.log("\nDry-run first if you want:");
|
|
101
|
+
console.log("\nPublish (you run these, from a clean tree, after pushing if the tarball should match GitHub):");
|
|
105
102
|
console.log(" pnpm publish --dry-run --access public");
|
|
103
|
+
console.log(" pnpm publish --access public");
|
|
104
|
+
console.log(" cd mcp-server");
|
|
105
|
+
console.log(" pnpm publish --access public");
|
|
106
|
+
console.log(" cd ..");
|
|
107
|
+
console.log("Do not use pnpm --dir mcp-server publish. npm 12 treats leftover --dir as an extra package spec.");
|
|
106
108
|
|
|
107
109
|
const here = fileURLToPath(import.meta.url);
|
|
108
110
|
if (resolve(process.argv[1] ?? "") === resolve(here)) {
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { mkdtempSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import test from "node:test";
|
|
7
|
+
import assert from "node:assert/strict";
|
|
8
|
+
import { validateTrackingData } from "../content/hooks/validate-tracking-core.mjs";
|
|
9
|
+
|
|
10
|
+
const root = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
11
|
+
|
|
12
|
+
test("a pointer is not a second decision log", () => {
|
|
13
|
+
const result = validateTrackingData({
|
|
14
|
+
record: "appledger/",
|
|
15
|
+
status: "pointer",
|
|
16
|
+
note: "Decisions live in appledger/.",
|
|
17
|
+
});
|
|
18
|
+
assert.equal(result.issues.length, 0);
|
|
19
|
+
assert.match(result.warnings.join("\n"), /pointer to appledger/);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("a legacy tracking document is a conflict", () => {
|
|
23
|
+
const result = validateTrackingData({
|
|
24
|
+
project: { name: "Notes", description: "Find notes" },
|
|
25
|
+
currentPhase: "4-feature-iteration",
|
|
26
|
+
phases: { "4-feature-iteration": { status: "in_progress", exitCriteriaRemaining: ["Edge cases"] } },
|
|
27
|
+
decisions: [{ decision: "Use local files" }],
|
|
28
|
+
sessions: [],
|
|
29
|
+
});
|
|
30
|
+
assert.match(result.issues.join("\n"), /not the system of record/);
|
|
31
|
+
assert.match(result.issues.join("\n"), /appledger migrate preview/);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("install does not create workflow_tracking.json", () => {
|
|
35
|
+
for (const args of [
|
|
36
|
+
["install", "--lite", "--dry-run"],
|
|
37
|
+
["install", "--dry-run"],
|
|
38
|
+
]) {
|
|
39
|
+
const dir = mkdtempSync(join(tmpdir(), "ft-cutover-"));
|
|
40
|
+
const result = spawnSync(process.execPath, ["scripts/forgetrail-cli.mjs", ...args, "--path", dir], {
|
|
41
|
+
cwd: root,
|
|
42
|
+
encoding: "utf8",
|
|
43
|
+
});
|
|
44
|
+
assert.equal(result.status, 0, result.stderr || result.stdout);
|
|
45
|
+
assert.doesNotMatch(result.stdout, /\\workflow_tracking\.json/);
|
|
46
|
+
assert.match(result.stdout, /Project record: appledger/);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("session start warns on a legacy file and does not quote it as the live phase", () => {
|
|
51
|
+
const dir = mkdtempSync(join(tmpdir(), "ft-session-"));
|
|
52
|
+
mkdirSync(join(dir, ".forgetrail"), { recursive: true });
|
|
53
|
+
writeFileSync(
|
|
54
|
+
join(dir, ".forgetrail", "workflow_tracking.json"),
|
|
55
|
+
JSON.stringify({
|
|
56
|
+
project: { name: "Notes" },
|
|
57
|
+
currentPhase: "4-feature-iteration",
|
|
58
|
+
phases: {},
|
|
59
|
+
decisions: [{ decision: "Keep the old log" }],
|
|
60
|
+
})
|
|
61
|
+
);
|
|
62
|
+
const result = spawnSync(process.execPath, [join(root, "content", "hooks", "session-start.mjs")], {
|
|
63
|
+
cwd: dir,
|
|
64
|
+
encoding: "utf8",
|
|
65
|
+
});
|
|
66
|
+
assert.equal(result.status, 0, result.stderr);
|
|
67
|
+
const payload = JSON.parse(result.stdout);
|
|
68
|
+
assert.match(payload.additional_context, /not the system of record/);
|
|
69
|
+
assert.doesNotMatch(payload.additional_context, /Current Phase: 4-feature-iteration/);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("Lite and workflow instructions name the ledger", () => {
|
|
73
|
+
const lite = readFileSync(join(root, "content", "FORGETRAIL_LITE.md"), "utf8");
|
|
74
|
+
const legacyAt = lite.indexOf("## 11. Legacy");
|
|
75
|
+
const resumeAt = lite.indexOf("## 12. `AGENTS.md`");
|
|
76
|
+
assert.ok(legacyAt > 0 && resumeAt > legacyAt);
|
|
77
|
+
const instructional = `${lite.slice(0, legacyAt)}\n${lite.slice(resumeAt)}`;
|
|
78
|
+
assert.match(lite.slice(legacyAt, resumeAt), /"schemaVersion": "lite-1"/);
|
|
79
|
+
assert.match(instructional, /ForgeTrail Lite v2\.2\.0/);
|
|
80
|
+
for (const line of instructional.split("\n")) {
|
|
81
|
+
if (!line.includes("workflow_tracking.json")) continue;
|
|
82
|
+
assert.match(line, /[Dd]o not|does not|not the live phase|not recreate/, line);
|
|
83
|
+
}
|
|
84
|
+
const workflow = readFileSync(join(root, "WORKFLOW.md"), "utf8");
|
|
85
|
+
assert.match(workflow, /not_applicable/);
|
|
86
|
+
assert.match(workflow, /data\.companion_outcomes/);
|
|
87
|
+
assert.doesNotMatch(workflow, /Where this file names that JSON/);
|
|
88
|
+
for (const line of workflow.split("\n")) {
|
|
89
|
+
if (!line.includes("workflow_tracking.json")) continue;
|
|
90
|
+
assert.match(line, /[Dd]o not|does not|not the system of record|not the live phase/, line);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test("kickoff names appledger init and does not require the tracking file", () => {
|
|
95
|
+
const kickoff = readFileSync(join(root, "mcp-server", "src", "index.ts"), "utf8");
|
|
96
|
+
assert.match(kickoff, /appledger init/);
|
|
97
|
+
assert.doesNotMatch(kickoff, /no separate init command/);
|
|
98
|
+
const plan = readFileSync(join(root, "content", "PLAN_MODE_PATTERNS.md"), "utf8");
|
|
99
|
+
assert.match(plan, /decision record/);
|
|
100
|
+
assert.doesNotMatch(plan, /decisions\[\]/);
|
|
101
|
+
assert.match(plan, /Do not create `\.forgetrail\/workflow_tracking\.json`/);
|
|
102
|
+
const genesis = readFileSync(join(root, "content", "GENESIS_STUB.md"), "utf8");
|
|
103
|
+
assert.match(genesis, /appledger init/);
|
|
104
|
+
assert.doesNotMatch(genesis, /Create `\.forgetrail\/workflow_tracking\.json`/);
|
|
105
|
+
const intake = readFileSync(join(root, "content", "GREENFIELD_INTAKE.md"), "utf8");
|
|
106
|
+
assert.doesNotMatch(intake, /tracking file/);
|
|
107
|
+
assert.doesNotMatch(intake, /decisions\[\]/);
|
|
108
|
+
assert.match(intake, /archetype/);
|
|
109
|
+
});
|
|
@@ -40,8 +40,9 @@ function scanWorkspace(workspaceRoot) {
|
|
|
40
40
|
|
|
41
41
|
const trackingPath = findTracking(fullPath);
|
|
42
42
|
const hooksStatus = hasHooks(fullPath);
|
|
43
|
+
const ledger = existsSync(join(fullPath, "appledger", "manifest.yaml"));
|
|
43
44
|
|
|
44
|
-
if (!trackingPath && hooksStatus === "none") {
|
|
45
|
+
if (!trackingPath && !ledger && hooksStatus === "none") {
|
|
45
46
|
continue;
|
|
46
47
|
}
|
|
47
48
|
|
|
@@ -77,9 +78,16 @@ function scanWorkspace(workspaceRoot) {
|
|
|
77
78
|
openCriteriaCount = pObj.exitCriteriaRemaining.length;
|
|
78
79
|
}
|
|
79
80
|
}
|
|
81
|
+
if (tracking.status === "pointer") {
|
|
82
|
+
phase = ledger ? "appledger" : "pointer";
|
|
83
|
+
} else if (tracking.currentPhase || tracking.phases) {
|
|
84
|
+
phase = ledger ? `legacy+${phase}` : `legacy:${phase}`;
|
|
85
|
+
}
|
|
80
86
|
} catch {}
|
|
81
87
|
}
|
|
82
88
|
|
|
89
|
+
if (ledger && phase === "-") phase = "appledger";
|
|
90
|
+
|
|
83
91
|
rows.push({
|
|
84
92
|
repo: entry,
|
|
85
93
|
name: projectName,
|