@leing2021/super-pi 0.19.1 → 0.19.2
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 +13 -1
- package/extensions/ce-core/tools/context-handoff.ts +357 -0
- package/package.json +1 -1
- package/skills/01-brainstorm/references/handoff.md +3 -0
- package/skills/02-plan/references/handoff.md +3 -0
- package/skills/03-work/references/handoff.md +4 -0
- package/skills/04-review/references/handoff.md +2 -0
- package/skills/05-learn/SKILL.md +2 -0
- package/skills/references/pipeline-config.md +90 -2
package/README.md
CHANGED
|
@@ -180,7 +180,7 @@ Single `npm install` output filtered once pays for the entire overhead. Full eva
|
|
|
180
180
|
|
|
181
181
|
## Code Scale
|
|
182
182
|
|
|
183
|
-
~
|
|
183
|
+
~2800 lines of TypeScript implementing 16 tools, 22 Markdown reference files + 78 rule files driving 10 skills, 170 tests covering all tool logic.
|
|
184
184
|
|
|
185
185
|
Not a heavy framework. Each tool has a single responsibility, each skill works independently, and together they form a complete workflow.
|
|
186
186
|
|
|
@@ -383,6 +383,18 @@ Not a fork. Not a wrapper. Methodologies extracted and rebuilt with Pi's native
|
|
|
383
383
|
|
|
384
384
|
## Changelog
|
|
385
385
|
|
|
386
|
+
### 0.19.2 — Evidence-first handoff-lite + docs tracking rule
|
|
387
|
+
- Added `context_handoff` with evidence-first default handoff-lite generation when markdown is omitted.
|
|
388
|
+
- Standardized the shared handoff-lite template across 01-05 workflow handoffs via `skills/references/pipeline-config.md`.
|
|
389
|
+
- Added tests protecting default handoff generation and the shared handoff docs contract.
|
|
390
|
+
- Updated docs tracking so Git only uploads `docs/token-cost-evaluation.md` while other `docs/` artifacts stay local.
|
|
391
|
+
|
|
392
|
+
### 0.19.1 — Pipeline config + typecheck baseline fix
|
|
393
|
+
- Added shared pipeline config (`skills/references/pipeline-config.md`) for stage model routing via `.pi/settings.json`.
|
|
394
|
+
- Added gated auto-continue rules (`pipeline.autoContinue`) so automation does not skip required approval/review-choice steps.
|
|
395
|
+
- Added explicit README usage examples for `modelStrategy` and `pipeline.autoContinue`.
|
|
396
|
+
- Fixed TypeScript baseline issues so `bunx tsc --noEmit` passes.
|
|
397
|
+
|
|
386
398
|
### 0.19.0 — 0.69.0 alignment + learn rename
|
|
387
399
|
- TypeBox migration: `@sinclair/typebox` → `typebox` (zero old-path imports)
|
|
388
400
|
- Peer/dev dependency upgrade: pi-coding-agent `0.67.6` → `0.69.0`
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises"
|
|
2
|
+
import { existsSync } from "node:fs"
|
|
3
|
+
import path from "node:path"
|
|
4
|
+
import { normalizeSlug } from "../utils/name-utils"
|
|
5
|
+
|
|
6
|
+
export type ContextHealth = "good" | "watch" | "heavy" | "critical"
|
|
7
|
+
|
|
8
|
+
export interface ContextHandoffInput {
|
|
9
|
+
operation: "save" | "load" | "latest" | "status"
|
|
10
|
+
repoRoot: string
|
|
11
|
+
currentStage?: string
|
|
12
|
+
nextStage?: string
|
|
13
|
+
contextHealth?: ContextHealth
|
|
14
|
+
activeFiles?: string[]
|
|
15
|
+
blocker?: string
|
|
16
|
+
verification?: string
|
|
17
|
+
artifacts?: Record<string, string | undefined>
|
|
18
|
+
handoffMarkdown?: string
|
|
19
|
+
handoffPath?: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ContextStateEntry {
|
|
23
|
+
currentStage: string
|
|
24
|
+
nextStage?: string
|
|
25
|
+
contextHealth: ContextHealth
|
|
26
|
+
latestHandoffPath?: string
|
|
27
|
+
latestDatedHandoffPath?: string
|
|
28
|
+
activeFiles: string[]
|
|
29
|
+
blocker?: string
|
|
30
|
+
verification?: string
|
|
31
|
+
artifacts: Record<string, string | undefined>
|
|
32
|
+
recommendNewSession: boolean
|
|
33
|
+
updatedAt: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface ContextHandoffResult {
|
|
37
|
+
operation: string
|
|
38
|
+
found?: boolean
|
|
39
|
+
path?: string
|
|
40
|
+
latestPath?: string
|
|
41
|
+
currentStage?: string
|
|
42
|
+
nextStage?: string
|
|
43
|
+
contextHealth?: ContextHealth
|
|
44
|
+
activeFiles?: string[]
|
|
45
|
+
blocker?: string
|
|
46
|
+
verification?: string
|
|
47
|
+
artifacts?: Record<string, string | undefined>
|
|
48
|
+
recommendNewSession?: boolean
|
|
49
|
+
handoffMarkdown?: string
|
|
50
|
+
updatedAt?: string
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function ceDir(repoRoot: string): string {
|
|
54
|
+
return path.join(repoRoot, ".context", "compound-engineering")
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function handoffDir(repoRoot: string): string {
|
|
58
|
+
return path.join(ceDir(repoRoot), "handoffs")
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function stateFilePath(repoRoot: string): string {
|
|
62
|
+
return path.join(ceDir(repoRoot), "context-state.json")
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function latestHandoffPath(repoRoot: string): string {
|
|
66
|
+
return path.join(handoffDir(repoRoot), "latest.md")
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function toRepoRelative(repoRoot: string, filePath: string): string {
|
|
70
|
+
return path.relative(repoRoot, filePath)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function resolveRepoPath(repoRoot: string, filePath: string): string {
|
|
74
|
+
return path.isAbsolute(filePath) ? filePath : path.join(repoRoot, filePath)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function stageSlug(value?: string): string {
|
|
78
|
+
if (!value || value.trim().length === 0) return "unknown"
|
|
79
|
+
return normalizeSlug(value)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function buildDatedHandoffPath(repoRoot: string, currentStage?: string, nextStage?: string): string {
|
|
83
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-")
|
|
84
|
+
const fileName = `${timestamp}-${stageSlug(currentStage)}-to-${stageSlug(nextStage)}.md`
|
|
85
|
+
return path.join(handoffDir(repoRoot), fileName)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function computeRecommendNewSession(currentStage?: string, nextStage?: string, contextHealth: ContextHealth = "watch"): boolean {
|
|
89
|
+
const isCrossPhase = Boolean(currentStage && nextStage && currentStage !== nextStage)
|
|
90
|
+
const isHeavy = contextHealth === "heavy" || contextHealth === "critical"
|
|
91
|
+
return isCrossPhase && isHeavy
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function formatBullets(items: string[]): string {
|
|
95
|
+
if (items.length === 0) return "- N/A"
|
|
96
|
+
return items.map(item => `- ${item}`).join("\n")
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function formatArtifacts(artifacts: Record<string, string | undefined>): string {
|
|
100
|
+
const lines = Object.entries(artifacts)
|
|
101
|
+
.filter(([, value]) => Boolean(value && value.trim().length > 0))
|
|
102
|
+
.map(([key, value]) => `- ${key}: ${value}`)
|
|
103
|
+
|
|
104
|
+
if (lines.length === 0) return "- N/A"
|
|
105
|
+
return lines.join("\n")
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function buildDefaultHandoffMarkdown(input: {
|
|
109
|
+
currentStage: string
|
|
110
|
+
nextStage?: string
|
|
111
|
+
activeFiles: string[]
|
|
112
|
+
artifacts: Record<string, string | undefined>
|
|
113
|
+
blocker?: string
|
|
114
|
+
verification?: string
|
|
115
|
+
}): string {
|
|
116
|
+
const currentTask = input.nextStage
|
|
117
|
+
? `Continue from ${input.currentStage} to ${input.nextStage}.`
|
|
118
|
+
: `Continue ${input.currentStage}.`
|
|
119
|
+
|
|
120
|
+
const hotContext = formatBullets(input.activeFiles.slice(0, 5))
|
|
121
|
+
|
|
122
|
+
const verifiedFacts = formatBullets([
|
|
123
|
+
`Current stage: ${input.currentStage}`,
|
|
124
|
+
`Next stage: ${input.nextStage ?? "N/A"}`,
|
|
125
|
+
])
|
|
126
|
+
|
|
127
|
+
const activeFiles = formatBullets(input.activeFiles.slice(0, 5))
|
|
128
|
+
const artifacts = formatArtifacts(input.artifacts)
|
|
129
|
+
const blocker = input.blocker ?? "N/A"
|
|
130
|
+
const verification = input.verification ?? "Not run"
|
|
131
|
+
const nextMinimalStep = input.nextStage ? `/skill:${input.nextStage}` : "N/A"
|
|
132
|
+
|
|
133
|
+
return [
|
|
134
|
+
"## Current Task",
|
|
135
|
+
currentTask,
|
|
136
|
+
"",
|
|
137
|
+
"## Hot Context",
|
|
138
|
+
hotContext,
|
|
139
|
+
"",
|
|
140
|
+
"## Verified Facts",
|
|
141
|
+
verifiedFacts,
|
|
142
|
+
"",
|
|
143
|
+
"## Active Files",
|
|
144
|
+
activeFiles,
|
|
145
|
+
"",
|
|
146
|
+
"## Artifacts",
|
|
147
|
+
artifacts,
|
|
148
|
+
"",
|
|
149
|
+
"## Current Blocker",
|
|
150
|
+
`- ${blocker}`,
|
|
151
|
+
"",
|
|
152
|
+
"## Verification",
|
|
153
|
+
`- ${verification}`,
|
|
154
|
+
"",
|
|
155
|
+
"## Do Not Repeat",
|
|
156
|
+
"- Do not reload full history unless the handoff lacks required evidence.",
|
|
157
|
+
"",
|
|
158
|
+
"## Next Minimal Step",
|
|
159
|
+
`- ${nextMinimalStep}`,
|
|
160
|
+
"",
|
|
161
|
+
].join("\n")
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async function readState(repoRoot: string): Promise<ContextStateEntry | null> {
|
|
165
|
+
const filePath = stateFilePath(repoRoot)
|
|
166
|
+
if (!existsSync(filePath)) return null
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
const content = await readFile(filePath, "utf8")
|
|
170
|
+
return JSON.parse(content) as ContextStateEntry
|
|
171
|
+
} catch {
|
|
172
|
+
return null
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async function writeState(repoRoot: string, state: ContextStateEntry): Promise<void> {
|
|
177
|
+
const filePath = stateFilePath(repoRoot)
|
|
178
|
+
await mkdir(path.dirname(filePath), { recursive: true })
|
|
179
|
+
await writeFile(filePath, JSON.stringify(state, null, 2), "utf8")
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function createContextHandoffTool() {
|
|
183
|
+
return {
|
|
184
|
+
name: "context_handoff",
|
|
185
|
+
async execute(input: ContextHandoffInput): Promise<ContextHandoffResult> {
|
|
186
|
+
switch (input.operation) {
|
|
187
|
+
case "save":
|
|
188
|
+
return save(input)
|
|
189
|
+
case "load":
|
|
190
|
+
return load(input)
|
|
191
|
+
case "latest":
|
|
192
|
+
return latest(input)
|
|
193
|
+
case "status":
|
|
194
|
+
return status(input)
|
|
195
|
+
default:
|
|
196
|
+
throw new Error(`Unknown operation: ${input.operation}`)
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async function save(input: ContextHandoffInput): Promise<ContextHandoffResult> {
|
|
203
|
+
const currentStage = input.currentStage ?? "unknown"
|
|
204
|
+
const nextStage = input.nextStage
|
|
205
|
+
const contextHealth = input.contextHealth ?? "watch"
|
|
206
|
+
const activeFiles = input.activeFiles ?? []
|
|
207
|
+
const blocker = input.blocker
|
|
208
|
+
const verification = input.verification
|
|
209
|
+
const artifacts = input.artifacts ?? {}
|
|
210
|
+
const handoffMarkdown = input.handoffMarkdown?.trim().length
|
|
211
|
+
? input.handoffMarkdown
|
|
212
|
+
: buildDefaultHandoffMarkdown({
|
|
213
|
+
currentStage,
|
|
214
|
+
nextStage,
|
|
215
|
+
activeFiles,
|
|
216
|
+
artifacts,
|
|
217
|
+
blocker,
|
|
218
|
+
verification,
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
const recommendNewSession = computeRecommendNewSession(currentStage, nextStage, contextHealth)
|
|
222
|
+
const latestPath = latestHandoffPath(input.repoRoot)
|
|
223
|
+
const datedPath = buildDatedHandoffPath(input.repoRoot, currentStage, nextStage)
|
|
224
|
+
const relativeLatestPath = toRepoRelative(input.repoRoot, latestPath)
|
|
225
|
+
const relativeDatedPath = toRepoRelative(input.repoRoot, datedPath)
|
|
226
|
+
|
|
227
|
+
await mkdir(path.dirname(latestPath), { recursive: true })
|
|
228
|
+
await writeFile(latestPath, handoffMarkdown, "utf8")
|
|
229
|
+
await writeFile(datedPath, handoffMarkdown, "utf8")
|
|
230
|
+
|
|
231
|
+
const state: ContextStateEntry = {
|
|
232
|
+
currentStage,
|
|
233
|
+
nextStage,
|
|
234
|
+
contextHealth,
|
|
235
|
+
latestHandoffPath: relativeLatestPath,
|
|
236
|
+
latestDatedHandoffPath: relativeDatedPath,
|
|
237
|
+
activeFiles,
|
|
238
|
+
blocker,
|
|
239
|
+
verification,
|
|
240
|
+
artifacts,
|
|
241
|
+
recommendNewSession,
|
|
242
|
+
updatedAt: new Date().toISOString(),
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
await writeState(input.repoRoot, state)
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
operation: "save",
|
|
249
|
+
found: true,
|
|
250
|
+
path: relativeDatedPath,
|
|
251
|
+
latestPath: relativeLatestPath,
|
|
252
|
+
currentStage,
|
|
253
|
+
nextStage,
|
|
254
|
+
contextHealth,
|
|
255
|
+
activeFiles,
|
|
256
|
+
blocker,
|
|
257
|
+
verification,
|
|
258
|
+
artifacts,
|
|
259
|
+
recommendNewSession,
|
|
260
|
+
updatedAt: state.updatedAt,
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
async function load(input: ContextHandoffInput): Promise<ContextHandoffResult> {
|
|
265
|
+
const state = await readState(input.repoRoot)
|
|
266
|
+
if (!state) {
|
|
267
|
+
return {
|
|
268
|
+
operation: "load",
|
|
269
|
+
found: false,
|
|
270
|
+
contextHealth: "watch",
|
|
271
|
+
recommendNewSession: false,
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const targetPath = input.handoffPath ?? state.latestHandoffPath ?? latestHandoffPath(input.repoRoot)
|
|
276
|
+
const absoluteTargetPath = resolveRepoPath(input.repoRoot, targetPath)
|
|
277
|
+
let markdown = ""
|
|
278
|
+
if (existsSync(absoluteTargetPath)) {
|
|
279
|
+
markdown = await readFile(absoluteTargetPath, "utf8")
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return {
|
|
283
|
+
operation: "load",
|
|
284
|
+
found: true,
|
|
285
|
+
path: targetPath,
|
|
286
|
+
latestPath: state.latestHandoffPath,
|
|
287
|
+
currentStage: state.currentStage,
|
|
288
|
+
nextStage: state.nextStage,
|
|
289
|
+
contextHealth: state.contextHealth,
|
|
290
|
+
activeFiles: state.activeFiles,
|
|
291
|
+
blocker: state.blocker,
|
|
292
|
+
verification: state.verification,
|
|
293
|
+
artifacts: state.artifacts,
|
|
294
|
+
recommendNewSession: state.recommendNewSession,
|
|
295
|
+
handoffMarkdown: markdown,
|
|
296
|
+
updatedAt: state.updatedAt,
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
async function latest(input: ContextHandoffInput): Promise<ContextHandoffResult> {
|
|
301
|
+
const state = await readState(input.repoRoot)
|
|
302
|
+
if (!state || !state.latestHandoffPath) {
|
|
303
|
+
return {
|
|
304
|
+
operation: "latest",
|
|
305
|
+
found: false,
|
|
306
|
+
contextHealth: "watch",
|
|
307
|
+
recommendNewSession: false,
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return {
|
|
312
|
+
operation: "latest",
|
|
313
|
+
found: true,
|
|
314
|
+
path: state.latestDatedHandoffPath,
|
|
315
|
+
latestPath: state.latestHandoffPath,
|
|
316
|
+
currentStage: state.currentStage,
|
|
317
|
+
nextStage: state.nextStage,
|
|
318
|
+
contextHealth: state.contextHealth,
|
|
319
|
+
activeFiles: state.activeFiles,
|
|
320
|
+
blocker: state.blocker,
|
|
321
|
+
verification: state.verification,
|
|
322
|
+
artifacts: state.artifacts,
|
|
323
|
+
recommendNewSession: state.recommendNewSession,
|
|
324
|
+
updatedAt: state.updatedAt,
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
async function status(input: ContextHandoffInput): Promise<ContextHandoffResult> {
|
|
329
|
+
const state = await readState(input.repoRoot)
|
|
330
|
+
|
|
331
|
+
if (!state) {
|
|
332
|
+
return {
|
|
333
|
+
operation: "status",
|
|
334
|
+
found: false,
|
|
335
|
+
contextHealth: "watch",
|
|
336
|
+
recommendNewSession: false,
|
|
337
|
+
activeFiles: [],
|
|
338
|
+
artifacts: {},
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return {
|
|
343
|
+
operation: "status",
|
|
344
|
+
found: true,
|
|
345
|
+
path: state.latestDatedHandoffPath,
|
|
346
|
+
latestPath: state.latestHandoffPath,
|
|
347
|
+
currentStage: state.currentStage,
|
|
348
|
+
nextStage: state.nextStage,
|
|
349
|
+
contextHealth: state.contextHealth,
|
|
350
|
+
activeFiles: state.activeFiles,
|
|
351
|
+
blocker: state.blocker,
|
|
352
|
+
verification: state.verification,
|
|
353
|
+
artifacts: state.artifacts,
|
|
354
|
+
recommendNewSession: state.recommendNewSession,
|
|
355
|
+
updatedAt: state.updatedAt,
|
|
356
|
+
}
|
|
357
|
+
}
|
package/package.json
CHANGED
|
@@ -6,3 +6,6 @@ When the requirements artifact is ready:
|
|
|
6
6
|
2. Summarize the recommended direction in 2-3 bullets.
|
|
7
7
|
3. Recommend `02-plan` as the next step.
|
|
8
8
|
4. If key ambiguity remains, say so before handing off.
|
|
9
|
+
5. Provide `🧠 Context Status` (health, handoff path, active files, new-session recommendation).
|
|
10
|
+
6. Save/mention handoff-lite path under `.context/compound-engineering/handoffs/` using the shared `Handoff-lite template` in `skills/references/pipeline-config.md`.
|
|
11
|
+
7. Recommend new session only when cross-phase + health is heavy/critical, and include a copyable prompt.
|
|
@@ -6,3 +6,6 @@ When the plan is ready:
|
|
|
6
6
|
2. Summarize the main implementation units.
|
|
7
7
|
3. Recommend `03-work` as the next step.
|
|
8
8
|
4. Call out any remaining assumptions or open risks.
|
|
9
|
+
5. Provide `🧠 Context Status` (health, handoff path, active files, new-session recommendation).
|
|
10
|
+
6. Save/mention handoff-lite path under `.context/compound-engineering/handoffs/` using the shared `Handoff-lite template` in `skills/references/pipeline-config.md`.
|
|
11
|
+
7. Recommend new session only when cross-phase + health is heavy/critical, and include a copyable prompt.
|
|
@@ -6,3 +6,7 @@ When execution reaches a meaningful checkpoint:
|
|
|
6
6
|
2. Report the latest verification results.
|
|
7
7
|
3. Recommend `04-review` as the next step.
|
|
8
8
|
4. Mention any remaining implementation risk.
|
|
9
|
+
5. Include checkpoint fields: `activeFiles`, `currentUnit`, `blocker`, `verification`, `contextTiers`, `handoffPath`.
|
|
10
|
+
6. Provide `🧠 Context Status` (health, handoff path, active files, new-session recommendation).
|
|
11
|
+
7. Save/mention handoff-lite path under `.context/compound-engineering/handoffs/` using the shared `Handoff-lite template` in `skills/references/pipeline-config.md`.
|
|
12
|
+
8. Recommend new session only when cross-phase + health is heavy/critical, and include a copyable prompt.
|
|
@@ -8,6 +8,8 @@ When the review is complete:
|
|
|
8
8
|
4. After autofix, report what was changed and whether re-review confirms the fix.
|
|
9
9
|
5. Recommend `05-learn` when the review surfaced a reusable learning or newly solved problem.
|
|
10
10
|
6. Mention any relevant plan or solution artifacts referenced during review.
|
|
11
|
+
7. Provide `🧠 Context Status` (health, handoff path, active files, new-session recommendation).
|
|
12
|
+
8. Save/mention handoff-lite path under `.context/compound-engineering/handoffs/` using the shared `Handoff-lite template` in `skills/references/pipeline-config.md`.
|
|
11
13
|
|
|
12
14
|
## Autofix loop
|
|
13
15
|
|
package/skills/05-learn/SKILL.md
CHANGED
|
@@ -32,5 +32,7 @@ See [shared pipeline instructions](../references/pipeline-config.md) for model r
|
|
|
32
32
|
5. Choose the correct category using `references/category-map.md`.
|
|
33
33
|
6. Write or update the solution artifact under `docs/solutions/<category>/`.
|
|
34
34
|
7. Mention how future `02-plan` and `04-review` runs should benefit from the new learning.
|
|
35
|
+
8. Include `🧠 Context Status` (health, handoff path, active files, new-session recommendation) for workflow closure.
|
|
36
|
+
9. Save/mention handoff-lite path under `.context/compound-engineering/handoffs/` using the shared `Handoff-lite template` in `skills/references/pipeline-config.md`.
|
|
35
37
|
|
|
36
38
|
Before finishing this skill, apply the completion checklist in [shared pipeline instructions](../references/pipeline-config.md).
|
|
@@ -18,9 +18,9 @@ Run this checklist before normal skill workflow:
|
|
|
18
18
|
5. If `targetModel` exists and differs from the current model, run `/model <targetModel>`.
|
|
19
19
|
6. If switching fails, continue with current model and mention the failure once.
|
|
20
20
|
|
|
21
|
-
## End of skill: status + optional auto-continue
|
|
21
|
+
## End of skill: status + context + optional auto-continue
|
|
22
22
|
|
|
23
|
-
Before final completion, always output
|
|
23
|
+
Before final completion, always output these blocks (replace placeholders with real values, never output angle-bracket placeholders literally):
|
|
24
24
|
|
|
25
25
|
```
|
|
26
26
|
---
|
|
@@ -29,6 +29,13 @@ Before final completion, always output this block (replace placeholders with rea
|
|
|
29
29
|
- Output: <main artifact path or N/A>
|
|
30
30
|
- Next: <next skill command or Completed>
|
|
31
31
|
---
|
|
32
|
+
|
|
33
|
+
🧠 Context Status
|
|
34
|
+
- Health: good | watch | heavy | critical
|
|
35
|
+
- Handoff: <path or N/A>
|
|
36
|
+
- Active: <1-5 active files or N/A>
|
|
37
|
+
- New session: recommended | not needed
|
|
38
|
+
---
|
|
32
39
|
```
|
|
33
40
|
|
|
34
41
|
Next step mapping:
|
|
@@ -47,3 +54,84 @@ Then read `.pi/settings.json` → `pipeline.autoContinue`:
|
|
|
47
54
|
- `04-review`: optional QA choice is resolved (A/B/C flow completed) and user confirmed to proceed.
|
|
48
55
|
- Any unclear/ambiguous state: do not auto-continue; stop and ask.
|
|
49
56
|
- When gates are satisfied, automatically trigger the mapped next skill command.
|
|
57
|
+
|
|
58
|
+
### Handoff-lite template
|
|
59
|
+
|
|
60
|
+
When a stage produces or updates handoff-lite, use this evidence-first structure and keep it concise (target <= 1500 tokens):
|
|
61
|
+
|
|
62
|
+
```md
|
|
63
|
+
## Current Task
|
|
64
|
+
|
|
65
|
+
## Hot Context
|
|
66
|
+
- 1-5 must-know facts for the next step
|
|
67
|
+
|
|
68
|
+
## Verified Facts
|
|
69
|
+
- already validated facts (do not re-prove)
|
|
70
|
+
|
|
71
|
+
## Active Files
|
|
72
|
+
- 1-5 file paths only
|
|
73
|
+
|
|
74
|
+
## Artifacts
|
|
75
|
+
- requirements: <path or N/A>
|
|
76
|
+
- plan: <path or N/A>
|
|
77
|
+
- checkpoint: <path or N/A>
|
|
78
|
+
- proof: <path or N/A>
|
|
79
|
+
|
|
80
|
+
## Current Blocker
|
|
81
|
+
- <blocker or N/A>
|
|
82
|
+
|
|
83
|
+
## Verification
|
|
84
|
+
- <latest command + result or Not run>
|
|
85
|
+
|
|
86
|
+
## Do Not Repeat
|
|
87
|
+
- what should not be re-read/re-run unless needed
|
|
88
|
+
|
|
89
|
+
## Next Minimal Step
|
|
90
|
+
- exact next command/action
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Rules:
|
|
94
|
+
- Use `N/A` instead of inventing facts.
|
|
95
|
+
- Keep broad history in artifact paths, not expanded narrative.
|
|
96
|
+
- If `context_handoff` is unavailable, manually write this shape to `.context/compound-engineering/handoffs/latest.md` and mention the path.
|
|
97
|
+
|
|
98
|
+
### New-session recommendation rule
|
|
99
|
+
|
|
100
|
+
Recommend a new session only when both are true:
|
|
101
|
+
|
|
102
|
+
1. Phase is changing (`Current` != next stage)
|
|
103
|
+
2. Context health is `heavy` or `critical`
|
|
104
|
+
|
|
105
|
+
When recommending a new session, include a directly copyable prompt:
|
|
106
|
+
|
|
107
|
+
```md
|
|
108
|
+
## 建议新开 Session
|
|
109
|
+
|
|
110
|
+
原因:当前 `<current stage>` 已完成,下一步将进入 `<next stage>`。当前窗口已经包含较多已完成阶段上下文,继续执行会降低 Token ROI,并增加旧上下文干扰后续判断的风险。
|
|
111
|
+
|
|
112
|
+
建议:新开一个窗口,把下面这段 Prompt 复制进去即可继续。
|
|
113
|
+
|
|
114
|
+
```text
|
|
115
|
+
继续这个 Super Pi workflow,不要重新开始。
|
|
116
|
+
|
|
117
|
+
Repo: <repo path>
|
|
118
|
+
|
|
119
|
+
请先读取:
|
|
120
|
+
- <latest plan/requirements artifact>
|
|
121
|
+
- <latest handoff-lite path>
|
|
122
|
+
- <latest checkpoint path or summary>
|
|
123
|
+
|
|
124
|
+
然后继续:
|
|
125
|
+
- 执行 <next skill command>
|
|
126
|
+
|
|
127
|
+
上下文策略:
|
|
128
|
+
- hot: 仅保留当前执行必须文件(1-5)
|
|
129
|
+
- warm: 通过 artifact path 按需回读
|
|
130
|
+
- cold: 不进入当前窗口,除非明确需要
|
|
131
|
+
|
|
132
|
+
核心原则:
|
|
133
|
+
- 不重复已完成阶段
|
|
134
|
+
- 优先验证当前阶段输出
|
|
135
|
+
- 控制 token,保持高 ROI
|
|
136
|
+
```
|
|
137
|
+
```
|