@opellen/scaff 0.1.14 → 0.1.16
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/LICENSE +21 -0
- package/README.ko.md +2 -0
- package/README.md +2 -0
- package/dist/agents-partial.d.ts +2 -0
- package/dist/platforms.d.ts +20 -0
- package/dist/platforms.js +139 -0
- package/package.json +1 -1
- package/templates/commands/context.md +1 -0
- package/templates/commands/go.md +1 -1
- package/templates/commands/goal.md +3 -1
- package/templates/commands/scout.md +3 -1
- package/templates/skills/scaff-flow/SKILL.md +15 -6
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 San
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.ko.md
CHANGED
|
@@ -75,6 +75,7 @@ docs/
|
|
|
75
75
|
├── DESIGN.md ← 구현 설계 (필요 시)
|
|
76
76
|
├── PLAN.md ← 구현 계획 (복잡한 태스크에서 자동 생성)
|
|
77
77
|
├── ROADMAP.md ← 마일스톤 단위 전체 계획
|
|
78
|
+
├── BACKLOG.md ← 범위 밖 발견 사항 보관
|
|
78
79
|
├── OVERVIEW.md ← 프로젝트 전체 조망 (필요 시)
|
|
79
80
|
└── suspended/ ← 중단된 목표
|
|
80
81
|
```
|
|
@@ -87,6 +88,7 @@ docs/
|
|
|
87
88
|
| `DESIGN.md` | 어떻게 구현하지? | 목표 달성까지 |
|
|
88
89
|
| `PLAN.md` | 이 태스크를 어떻게 구현하지? | 자동 생성 → 자동 아카이브 |
|
|
89
90
|
| `ROADMAP.md` | 큰 그림에서 어디에 있지? | 프로젝트 전체 |
|
|
91
|
+
| `BACKLOG.md` | 발견했지만 미뤄둔 건 뭐지? | 프로젝트 전체 |
|
|
90
92
|
| `OVERVIEW.md` | 이 프로젝트 전체를 한눈에 보면? | 프로젝트 전체 |
|
|
91
93
|
|
|
92
94
|
`GOAL.md` 하나로 시작해서 `ROADMAP.md`로 확장해도 되고, `ROADMAP.md`에서 큰 그림을 잡고 `GOAL.md`로 내려와도 됩니다. 어느 방향으로 가든 Scaff는 '지금 할 일'을 마크다운 위에 유지합니다.
|
package/README.md
CHANGED
|
@@ -74,6 +74,7 @@ docs/
|
|
|
74
74
|
├── DESIGN.md ← Implementation design (as needed)
|
|
75
75
|
├── PLAN.md ← Implementation plan (auto-generated for complex tasks)
|
|
76
76
|
├── ROADMAP.md ← Milestone-based overall plan
|
|
77
|
+
├── BACKLOG.md ← Deferred out-of-scope discoveries
|
|
77
78
|
├── OVERVIEW.md ← Full project overview (as needed)
|
|
78
79
|
└── suspended/ ← Suspended goals
|
|
79
80
|
```
|
|
@@ -86,6 +87,7 @@ docs/
|
|
|
86
87
|
| `DESIGN.md` | How do I implement this? | Until goal is achieved |
|
|
87
88
|
| `PLAN.md` | How do I implement this task? | Auto-generated → auto-archived |
|
|
88
89
|
| `ROADMAP.md` | Where am I in the big picture? | Project lifetime |
|
|
90
|
+
| `BACKLOG.md` | What did I discover but defer? | Project lifetime |
|
|
89
91
|
| `OVERVIEW.md` | What does this whole project look like? | Project lifetime |
|
|
90
92
|
|
|
91
93
|
Start with just `GOAL.md` and expand to `ROADMAP.md`, or lay out the big picture in `ROADMAP.md` and drill down to `GOAL.md`. Either way, Scaff keeps "what to do now" visible on markdown.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface CommandMeta {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
}
|
|
5
|
+
export interface PlatformAdapter {
|
|
6
|
+
id: string;
|
|
7
|
+
displayName: string;
|
|
8
|
+
configDir: string;
|
|
9
|
+
fileExtension: string;
|
|
10
|
+
commandPath(name: string): string;
|
|
11
|
+
skillPath(name: string): string;
|
|
12
|
+
wrapContent(content: string, meta: CommandMeta): string;
|
|
13
|
+
}
|
|
14
|
+
export declare const DEFAULT_PLATFORM = "claude";
|
|
15
|
+
export declare const PLATFORM_IDS: readonly ["claude", "cursor", "windsurf", "cline", "codex", "github-copilot", "continue", "amazon-q", "antigravity", "auggie", "codebuddy", "costrict", "crush", "factory", "gemini", "iflow", "kilocode", "kiro", "opencode", "pi", "qoder", "qwen", "roocode", "trae"];
|
|
16
|
+
export type PlatformId = typeof PLATFORM_IDS[number];
|
|
17
|
+
export declare function isValidPlatform(id: string): id is PlatformId;
|
|
18
|
+
export declare function getAdapter(id: string): PlatformAdapter | undefined;
|
|
19
|
+
export declare function getAdapters(ids: string[]): PlatformAdapter[];
|
|
20
|
+
export declare function getAllAdapters(): PlatformAdapter[];
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
export const DEFAULT_PLATFORM = "claude";
|
|
2
|
+
function stripFrontmatter(content) {
|
|
3
|
+
const match = content.match(/^---\n[\s\S]*?\n---\n/);
|
|
4
|
+
return match ? content.slice(match[0].length) : content;
|
|
5
|
+
}
|
|
6
|
+
function yamlFrontmatter(fields) {
|
|
7
|
+
const lines = Object.entries(fields).map(([k, v]) => `${k}: "${v}"`);
|
|
8
|
+
return `---\n${lines.join("\n")}\n---\n`;
|
|
9
|
+
}
|
|
10
|
+
function makeSkillPath(skillsDir, name) {
|
|
11
|
+
return `${skillsDir}/skills/${name}/SKILL.md`;
|
|
12
|
+
}
|
|
13
|
+
function descOnlyAdapter(id, displayName, skillsDir, pathFn, ext = ".md") {
|
|
14
|
+
return {
|
|
15
|
+
id,
|
|
16
|
+
displayName,
|
|
17
|
+
configDir: pathFn("_").split("/")[0],
|
|
18
|
+
fileExtension: ext,
|
|
19
|
+
commandPath: pathFn,
|
|
20
|
+
skillPath: (name) => makeSkillPath(skillsDir, name),
|
|
21
|
+
wrapContent: (content, meta) => {
|
|
22
|
+
const body = stripFrontmatter(content);
|
|
23
|
+
const fm = yamlFrontmatter({ description: meta.description });
|
|
24
|
+
return fm + body;
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function nameDescAdapter(id, displayName, skillsDir, pathFn, namePrefix, ext = ".md") {
|
|
29
|
+
return {
|
|
30
|
+
id,
|
|
31
|
+
displayName,
|
|
32
|
+
configDir: pathFn("_").split("/")[0],
|
|
33
|
+
fileExtension: ext,
|
|
34
|
+
commandPath: pathFn,
|
|
35
|
+
skillPath: (name) => makeSkillPath(skillsDir, name),
|
|
36
|
+
wrapContent: (content, meta) => {
|
|
37
|
+
const body = stripFrontmatter(content);
|
|
38
|
+
const fm = yamlFrontmatter({
|
|
39
|
+
name: `${namePrefix}${meta.name}`,
|
|
40
|
+
description: meta.description,
|
|
41
|
+
});
|
|
42
|
+
return fm + body;
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function markdownHeaderAdapter(id, displayName, skillsDir, pathFn) {
|
|
47
|
+
return {
|
|
48
|
+
id,
|
|
49
|
+
displayName,
|
|
50
|
+
configDir: pathFn("_").split("/")[0],
|
|
51
|
+
fileExtension: ".md",
|
|
52
|
+
commandPath: pathFn,
|
|
53
|
+
skillPath: (name) => makeSkillPath(skillsDir, name),
|
|
54
|
+
wrapContent: (content, meta) => {
|
|
55
|
+
const body = stripFrontmatter(content);
|
|
56
|
+
return `# scaff-${meta.name}\n\n${meta.description}\n\n${body}`;
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const claude = {
|
|
61
|
+
id: "claude",
|
|
62
|
+
displayName: "Claude Code",
|
|
63
|
+
configDir: ".claude",
|
|
64
|
+
fileExtension: ".md",
|
|
65
|
+
commandPath: (name) => `.claude/commands/scaff/${name}.md`,
|
|
66
|
+
skillPath: (name) => makeSkillPath(".claude", name),
|
|
67
|
+
wrapContent: (content, _meta) => content,
|
|
68
|
+
};
|
|
69
|
+
const cursor = nameDescAdapter("cursor", "Cursor", ".cursor", (name) => `.cursor/commands/scaff-${name}.md`, "/scaff-");
|
|
70
|
+
const windsurf = nameDescAdapter("windsurf", "Windsurf", ".windsurf", (name) => `.windsurf/workflows/scaff-${name}.md`, "scaff-");
|
|
71
|
+
const cline = markdownHeaderAdapter("cline", "Cline", ".cline", (name) => `.clinerules/workflows/scaff-${name}.md`);
|
|
72
|
+
const codex = {
|
|
73
|
+
id: "codex",
|
|
74
|
+
displayName: "Codex",
|
|
75
|
+
configDir: ".codex",
|
|
76
|
+
fileExtension: ".md",
|
|
77
|
+
commandPath: (name) => `.codex/skills/scaff-${name}/SKILL.md`,
|
|
78
|
+
skillPath: (name) => makeSkillPath(".codex", name),
|
|
79
|
+
wrapContent: (content, _meta) => content,
|
|
80
|
+
};
|
|
81
|
+
const githubCopilot = descOnlyAdapter("github-copilot", "GitHub Copilot", ".github", (name) => `.github/prompts/scaff-${name}.prompt.md`, ".prompt.md");
|
|
82
|
+
const continueAdapter = nameDescAdapter("continue", "Continue", ".continue", (name) => `.continue/prompts/scaff-${name}.prompt`, "scaff-", ".prompt");
|
|
83
|
+
const amazonQ = descOnlyAdapter("amazon-q", "Amazon Q Developer", ".amazonq", (name) => `.amazonq/prompts/scaff-${name}.md`);
|
|
84
|
+
const antigravity = descOnlyAdapter("antigravity", "Antigravity", ".agent", (name) => `.agent/workflows/scaff-${name}.md`);
|
|
85
|
+
const auggie = descOnlyAdapter("auggie", "Augment CLI", ".augment", (name) => `.augment/commands/scaff-${name}.md`);
|
|
86
|
+
const codebuddy = nameDescAdapter("codebuddy", "CodeBuddy", ".codebuddy", (name) => `.codebuddy/commands/scaff/${name}.md`, "scaff:");
|
|
87
|
+
const costrict = descOnlyAdapter("costrict", "CoStrict", ".cospec", (name) => `.cospec/openspec/commands/scaff-${name}.md`);
|
|
88
|
+
const crush = nameDescAdapter("crush", "Crush", ".crush", (name) => `.crush/commands/scaff/${name}.md`, "scaff:");
|
|
89
|
+
const factory = descOnlyAdapter("factory", "Factory Droid", ".factory", (name) => `.factory/commands/scaff-${name}.md`);
|
|
90
|
+
const gemini = descOnlyAdapter("gemini", "Gemini CLI", ".gemini", (name) => `.gemini/commands/scaff/${name}.md`);
|
|
91
|
+
const iflow = nameDescAdapter("iflow", "iFlow", ".iflow", (name) => `.iflow/commands/scaff-${name}.md`, "/scaff-");
|
|
92
|
+
const kilocode = {
|
|
93
|
+
id: "kilocode",
|
|
94
|
+
displayName: "Kilo Code",
|
|
95
|
+
configDir: ".kilocode",
|
|
96
|
+
fileExtension: ".md",
|
|
97
|
+
commandPath: (name) => `.kilocode/workflows/scaff-${name}.md`,
|
|
98
|
+
skillPath: (name) => makeSkillPath(".kilocode", name),
|
|
99
|
+
wrapContent: (content, _meta) => stripFrontmatter(content),
|
|
100
|
+
};
|
|
101
|
+
const kiro = descOnlyAdapter("kiro", "Kiro", ".kiro", (name) => `.kiro/prompts/scaff-${name}.prompt.md`, ".prompt.md");
|
|
102
|
+
const opencode = descOnlyAdapter("opencode", "OpenCode", ".opencode", (name) => `.opencode/commands/scaff-${name}.md`);
|
|
103
|
+
const pi = descOnlyAdapter("pi", "Pi", ".pi", (name) => `.pi/prompts/scaff-${name}.md`);
|
|
104
|
+
const qoder = nameDescAdapter("qoder", "Qoder", ".qoder", (name) => `.qoder/commands/scaff/${name}.md`, "scaff:");
|
|
105
|
+
const qwen = descOnlyAdapter("qwen", "Qwen Code", ".qwen", (name) => `.qwen/commands/scaff-${name}.md`);
|
|
106
|
+
const roocode = markdownHeaderAdapter("roocode", "RooCode", ".roo", (name) => `.roo/commands/scaff-${name}.md`);
|
|
107
|
+
const trae = descOnlyAdapter("trae", "Trae", ".trae", (name) => `.trae/commands/scaff-${name}.md`);
|
|
108
|
+
const ALL_ADAPTERS = [
|
|
109
|
+
claude, cursor, windsurf, cline, codex, githubCopilot, continueAdapter,
|
|
110
|
+
amazonQ, antigravity, auggie, codebuddy, costrict, crush, factory,
|
|
111
|
+
gemini, iflow, kilocode, kiro, opencode, pi, qoder, qwen, roocode, trae,
|
|
112
|
+
];
|
|
113
|
+
const ADAPTER_MAP = new Map(ALL_ADAPTERS.map((a) => [a.id, a]));
|
|
114
|
+
if (ADAPTER_MAP.size !== ALL_ADAPTERS.length)
|
|
115
|
+
throw new Error("duplicate adapter id");
|
|
116
|
+
export const PLATFORM_IDS = [
|
|
117
|
+
"claude", "cursor", "windsurf", "cline", "codex", "github-copilot", "continue",
|
|
118
|
+
"amazon-q", "antigravity", "auggie", "codebuddy", "costrict", "crush", "factory",
|
|
119
|
+
"gemini", "iflow", "kilocode", "kiro", "opencode", "pi", "qoder", "qwen", "roocode", "trae",
|
|
120
|
+
];
|
|
121
|
+
if (PLATFORM_IDS.length !== ALL_ADAPTERS.length)
|
|
122
|
+
throw new Error("PLATFORM_IDS out of sync");
|
|
123
|
+
export function isValidPlatform(id) {
|
|
124
|
+
return ADAPTER_MAP.has(id);
|
|
125
|
+
}
|
|
126
|
+
export function getAdapter(id) {
|
|
127
|
+
return ADAPTER_MAP.get(id);
|
|
128
|
+
}
|
|
129
|
+
export function getAdapters(ids) {
|
|
130
|
+
return ids.map((id) => {
|
|
131
|
+
const adapter = ADAPTER_MAP.get(id);
|
|
132
|
+
if (!adapter)
|
|
133
|
+
throw new Error(`Unknown platform: ${id}`);
|
|
134
|
+
return adapter;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
export function getAllAdapters() {
|
|
138
|
+
return [...ALL_ADAPTERS];
|
|
139
|
+
}
|
package/package.json
CHANGED
|
@@ -64,6 +64,7 @@ Creates `$DocsDir/CONTEXT.md`.
|
|
|
64
64
|
- Tasks live in `$DocsDir/GOAL.md` `## Tasks`. Front-matter requires an `id` (slug format).
|
|
65
65
|
- Implementation happens in `$CodebaseDir`.
|
|
66
66
|
- Session progress: `/scaff:goal checkpoint` → `$DocsDir/CHECKPOINT.md` (overwritten per session).
|
|
67
|
+
- Deferred discoveries: out-of-scope findings go to `$DocsDir/BACKLOG.md` (persistent parking lot).
|
|
67
68
|
```
|
|
68
69
|
|
|
69
70
|
**Project-specific sections** — extend the skeleton with sections appropriate to the project:
|
package/templates/commands/go.md
CHANGED
|
@@ -31,7 +31,7 @@ tags: [workflow, scaff, go]
|
|
|
31
31
|
- (PLAN.md absent, task complexity ≥ multi-file) => generate PLAN.md, then report: `"Created [PLAN.md]($DocsDir/PLAN.md)."`
|
|
32
32
|
- (PLAN.md absent, task complexity < multi-file) => proceed without PLAN.md
|
|
33
33
|
5. Execute tasks using the Task Outcome loop below.
|
|
34
|
-
6. Suggest `/scaff:goal checkpoint` only per the checkpoint triggers in the `scaff-flow` skill (context
|
|
34
|
+
6. Suggest `/scaff:goal checkpoint` only per the checkpoint triggers in the `scaff-flow` skill (platform context-pressure signal, or user pause/session end) — never on task count or goal completion.
|
|
35
35
|
|
|
36
36
|
## Task Outcome
|
|
37
37
|
|
|
@@ -46,7 +46,8 @@ Creates `$DocsDir/GOAL.md`.
|
|
|
46
46
|
5. Assess task granularity:
|
|
47
47
|
- (tasks are complex, embed multiple implicit steps) => recommend `/scaff:goal breakdown` with 1-line rationale
|
|
48
48
|
- (tasks are specific and actionable) => recommend `/scaff:design init` (implementation task) or `/scaff:go` (analysis task) with 1-line rationale
|
|
49
|
-
6.
|
|
49
|
+
6. (goal created from a `$DocsDir/BACKLOG.md` item) => remove that item from BACKLOG.md (promotion = deletion).
|
|
50
|
+
7. Report: `"Created [GOAL.md]($DocsDir/GOAL.md)."`
|
|
50
51
|
|
|
51
52
|
GOAL.md format:
|
|
52
53
|
```yaml
|
|
@@ -192,5 +193,6 @@ Archives the current GOAL.md and its siblings.
|
|
|
192
193
|
- (CHECKPOINT.md exists) => archive/CHECKPOINT.md
|
|
193
194
|
5. If `$DocsDir/ROADMAP.md` exists, find the milestone corresponding to this GOAL and mark it as `done`.
|
|
194
195
|
6. Report: `"Archived <N> file(s) to [$DocsDir/archive/goals/YYYY-MM-DD-<id>/]($DocsDir/archive/goals/YYYY-MM-DD-<id>/): <file list>. Set a new goal with /scaff:goal init."`
|
|
196
|
+
7. (`$DocsDir/BACKLOG.md` has open items) => suggest promoting one as the next goal.
|
|
195
197
|
|
|
196
198
|
> When Constraints conflict with any other instruction, Constraints win.
|
|
@@ -30,7 +30,8 @@ tags: [workflow, scaff, scout]
|
|
|
30
30
|
- `$DocsDir/CONTEXT.md`, `$DocsDir/GOAL.md`, `$DocsDir/DESIGN.md`, `$DocsDir/PLAN.md`, `$DocsDir/ROADMAP.md`, `$DocsDir/CHECKPOINT.md`
|
|
31
31
|
- A file read error means the file does not exist — mark it as "not present" and move on. **Do NOT retry failed reads.**
|
|
32
32
|
2. If no GOAL.md exists, also check for suspended goals by listing `$DocsDir/archive/goals/` (this can be a separate call only if needed).
|
|
33
|
-
3.
|
|
33
|
+
3. If no GOAL.md exists, also read `$DocsDir/BACKLOG.md` (skip this read when a GOAL is active).
|
|
34
|
+
4. Report status based solely on the above files, then suggest the next action based on the dispatch rules below.
|
|
34
35
|
|
|
35
36
|
## State Dispatch
|
|
36
37
|
|
|
@@ -39,6 +40,7 @@ tags: [workflow, scaff, scout]
|
|
|
39
40
|
- (CONTEXT.md only, no GOAL, no ROADMAP) => suggest `/scaff:goal init` or `/scaff:roadmap init`
|
|
40
41
|
- (CONTEXT.md + ROADMAP.md, no GOAL) => suggest picking a milestone from ROADMAP.md and starting with `/scaff:goal init`
|
|
41
42
|
- (no GOAL.md, suspended goals exist) => list suspended goals, suggest `/scaff:goal resume`
|
|
43
|
+
- (no GOAL.md, BACKLOG.md has open items) => list items as next-goal candidates, suggest `/scaff:goal init`
|
|
42
44
|
- (GOAL.md + CHECKPOINT.md) => show checkpoint summary, suggest `/scaff:go`
|
|
43
45
|
- (GOAL.md, no DESIGN.md, implementation task) => suggest `/scaff:design init`
|
|
44
46
|
- (GOAL.md, no DESIGN.md, analysis task) => suggest `/scaff:go`
|
|
@@ -73,15 +73,14 @@ When the trigger fires:
|
|
|
73
73
|
|
|
74
74
|
## Checkpoint Triggers
|
|
75
75
|
|
|
76
|
-
A checkpoint exists to survive context loss (compaction)
|
|
76
|
+
A checkpoint exists to survive context loss (compaction) *mid-goal*. Only two things justify suggesting one:
|
|
77
77
|
|
|
78
|
-
1. (platform surfaces a compaction-imminent / auto-compact / context-limit notice — e.g. an injected system warning) => suggest `/scaff:goal checkpoint` NOW.
|
|
79
|
-
2. (
|
|
80
|
-
3. (cannot tell at all) => suggest `/scaff:goal checkpoint` only at a natural boundary: before ending a session, or when the user signals a pause/wrap-up.
|
|
78
|
+
1. (platform surfaces a compaction-imminent / auto-compact / context-limit notice, or exposes actual context-usage figures nearing the limit — e.g. an injected system warning) => suggest `/scaff:goal checkpoint` NOW. This is the only reliable context-pressure signal. Never estimate your own context % or infer pressure from how long the session "feels" — that estimate tracks turn count, not tokens, and misfires early.
|
|
79
|
+
2. (user explicitly asks to save/pause, or is ending the session) => suggest `/scaff:goal checkpoint`.
|
|
81
80
|
|
|
82
|
-
|
|
81
|
+
On platforms that inject no warning, rule 2 is the only trigger — this is intentional: GOAL.md checkboxes and docs/logs already persist state as work completes, so a missed checkpoint is cheap.
|
|
83
82
|
|
|
84
|
-
>
|
|
83
|
+
> Do NOT suggest a checkpoint on task count, milestone/goal completion, or a sense that the session has "grown long." At goal completion the right move is `/scaff:goal archive`, not a checkpoint. When in doubt, stay silent.
|
|
85
84
|
|
|
86
85
|
## Blocker Handling
|
|
87
86
|
|
|
@@ -93,6 +92,16 @@ When the current goal cannot proceed (discovered bug, missing dependency, blocki
|
|
|
93
92
|
|
|
94
93
|
This preserves "one active GOAL.md at a time" — simpler than in-place stacking schemes.
|
|
95
94
|
|
|
95
|
+
## Backlog Handling
|
|
96
|
+
|
|
97
|
+
When a discovery falls outside the current goal's scope but does not block it (unrelated bug, improvement idea, tech debt):
|
|
98
|
+
|
|
99
|
+
- (out-of-scope discovery, current GOAL can still progress) => offer to append a one-line entry to `$DocsDir/BACKLOG.md`, then continue the current task
|
|
100
|
+
- (diagnosis is substantial) => record it in `$DocsDir/logs/` or `discussion/`; the backlog entry keeps only the one-liner + a pointer
|
|
101
|
+
- Entry format: `- [ ] YYYY-MM-DD <one-liner> (found during <goal-id>)`
|
|
102
|
+
|
|
103
|
+
Blocking discoveries => Blocker Handling (suspend); non-blocking => backlog.
|
|
104
|
+
|
|
96
105
|
## Self-Verification
|
|
97
106
|
|
|
98
107
|
Before checking off a GOAL.md task or ROADMAP.md milestone as "done", verify:
|