fdeops 3.9.16 → 3.9.17
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 +6 -2
- package/bin/check.js +13 -0
- package/bin/fde.js +70 -19
- package/bin/lib/trust.js +3 -1
- package/package.json +1 -1
- package/skills/fde/SKILL.md +16 -3
- package/skills/fde/references/build.md +1 -1
- package/skills/fde/references/debrief.md +22 -8
- package/skills/fde/references/review.md +8 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](https://nodejs.org)
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
**Memory + methodology + skills, in one kit.** Skill packs teach your AI agent how to build. None of them remember who the client is, what was decided, or what's safe to ship. FDEOps adds the missing layer: a private fieldbook per engagement (`.fde/`), a field methodology (land → close), and one `@fde` skill that routes it all. Built for Forward Deployed Engineers, and anyone embedded in client work: consultants, agency developers, solutions architects, fractional CTOs. Feels like a second brain; behaves like a defensible record (dated, sourced, yours).
|
|
11
11
|
|
|
12
12
|
```
|
|
13
13
|
land discover plan build ship close
|
|
@@ -195,4 +195,8 @@ cd fdeops && git pull && node bin/install.js
|
|
|
195
195
|
|
|
196
196
|
Built and maintained by **[Subash Natarajan](https://www.linkedin.com/in/subashn/)**. Share your feedback via [Issues](https://github.com/suboss87/fdeops/issues) - see [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
197
197
|
|
|
198
|
-
|
|
198
|
+
Thanks to builders whose craft helped sharpen the thinking behind this kit, among them [Andrej Karpathy](https://karpathy.ai/)'s engineering guidelines and the [agentic engineering workflow](https://github.com/pawel-cell/micky-podcast-agentic-engineering) notes from David Ondrej / Michael Shimeles. FDEOps itself is handcrafted for field work; any resemblance is inspiration, not a fork.
|
|
199
|
+
|
|
200
|
+
**What we won't build:** SaaS sync or Slack/Notion connectors inside the CLI, CRM as core, hardware capture, or generic code-craft skill packs (TDD/review already exist elsewhere - FDEOps owns the engagement, not the keyboard). The `fde` CLI stays local-only.
|
|
201
|
+
|
|
202
|
+
[FDE Methodology](FDE-METHODOLOGY.md) - [SECURITY.md](SECURITY.md) - [PRIVACY.md](PRIVACY.md) - [Repo layout](docs/REPO_LAYOUT.md) - [Skills matrix](docs/skills.md) - MIT
|
package/bin/check.js
CHANGED
|
@@ -235,6 +235,19 @@ if (!skillBody.includes('fde prep')) {
|
|
|
235
235
|
if (!skillBody.includes('debrief --smart')) {
|
|
236
236
|
fail('SKILL.md must prefer fde debrief --smart for messy notes')
|
|
237
237
|
}
|
|
238
|
+
const debriefRef = read('skills/fde/references/debrief.md')
|
|
239
|
+
if (!/gate \+ writer|not a brain/i.test(debriefRef) || !/rewrite.*prefix/i.test(debriefRef)) {
|
|
240
|
+
fail('debrief.md must state --smart is a gate (agent rewrites propose with prefixes)')
|
|
241
|
+
} else ok('debrief --smart honesty contract')
|
|
242
|
+
if (!/existing.*## Next action|never append a second/i.test(skillBody)) {
|
|
243
|
+
fail('SKILL.md must warn against appending a second ## Next action')
|
|
244
|
+
} else ok('session-end Next action instruction')
|
|
245
|
+
if (!/session digest/i.test(skillBody) || !/Key decisions & why/i.test(skillBody)) {
|
|
246
|
+
fail('SKILL.md memory contract must define session digest (TL;DR / decisions & why → .fde/)')
|
|
247
|
+
} else ok('session digest in memory contract')
|
|
248
|
+
if (!/transcript/i.test(skillBody) || !/judgment/i.test(skillBody)) {
|
|
249
|
+
fail('SKILL.md must reject transcript dumps in favor of judgment in .fde/')
|
|
250
|
+
} else ok('session digest anti-transcript gate')
|
|
238
251
|
if (!/\btriage\b/.test(hook)) {
|
|
239
252
|
fail('session-start must still inject TRIAGE')
|
|
240
253
|
}
|
package/bin/fde.js
CHANGED
|
@@ -443,16 +443,56 @@ const {
|
|
|
443
443
|
} = createMemoryApi({ fs, path, gitBinOk, writeOwnerIfMissing, atomicWriteFile })
|
|
444
444
|
|
|
445
445
|
// Pull the body under a "## Heading" up to the next "##" (or EOF).
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
const
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
446
|
+
// opts.lastNonEmpty: when duplicate headings exist (common skill trap: template
|
|
447
|
+
// "## Next action" left empty, agent appends a second), prefer the last filled
|
|
448
|
+
// body so triage/resume do not silently report "(none set)".
|
|
449
|
+
function sectionBody(md, heading, opts) {
|
|
450
|
+
const preferLast = opts && opts.lastNonEmpty
|
|
451
|
+
const lines = String(md || '').split('\n')
|
|
452
|
+
const re = new RegExp('^#{1,6}\\s+' + heading + '\\b', 'i')
|
|
453
|
+
let first = ''
|
|
454
|
+
let lastFilled = ''
|
|
455
|
+
let seen = false
|
|
456
|
+
for (let i = 0; i < lines.length; i++) {
|
|
457
|
+
if (!re.test(lines[i].trim())) continue
|
|
458
|
+
const body = []
|
|
459
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
460
|
+
if (/^#{1,6}\s/.test(lines[j].trim())) break
|
|
461
|
+
body.push(lines[j])
|
|
462
|
+
}
|
|
463
|
+
const text = body.join('\n').trim()
|
|
464
|
+
if (!seen) { first = text; seen = true }
|
|
465
|
+
if (text) lastFilled = text
|
|
466
|
+
}
|
|
467
|
+
if (!seen) return ''
|
|
468
|
+
return preferLast ? (lastFilled || first) : first
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
function countSections(md, heading) {
|
|
472
|
+
const re = new RegExp('^#{1,6}\\s+' + heading + '\\b', 'i')
|
|
473
|
+
let n = 0
|
|
474
|
+
for (const raw of String(md || '').split('\n')) {
|
|
475
|
+
if (re.test(raw.trim())) n++
|
|
476
|
+
}
|
|
477
|
+
return n
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// Remove every "## Heading" section (heading line + body). Used to collapse
|
|
481
|
+
// duplicate Next action blocks before writing a single canonical one.
|
|
482
|
+
function stripAllSections(md, heading) {
|
|
483
|
+
const lines = String(md || '').split('\n')
|
|
484
|
+
const re = new RegExp('^#{1,6}\\s+' + heading + '\\b', 'i')
|
|
485
|
+
const out = []
|
|
486
|
+
for (let i = 0; i < lines.length; i++) {
|
|
487
|
+
if (re.test(lines[i].trim())) {
|
|
488
|
+
i++
|
|
489
|
+
while (i < lines.length && !/^#{1,6}\s/.test(lines[i].trim())) i++
|
|
490
|
+
i--
|
|
491
|
+
continue
|
|
492
|
+
}
|
|
493
|
+
out.push(lines[i])
|
|
454
494
|
}
|
|
455
|
-
return
|
|
495
|
+
return out.join('\n').replace(/\n{3,}/g, '\n\n').replace(/^\n+/, '').replace(/\n*$/, '\n')
|
|
456
496
|
}
|
|
457
497
|
|
|
458
498
|
// Append `entry` as the last line of a "## Heading" section, creating the
|
|
@@ -1106,11 +1146,12 @@ function setContextPhase(eng, phase) {
|
|
|
1106
1146
|
|
|
1107
1147
|
|
|
1108
1148
|
// Meeting notes → structured memory. Deterministic routing, zero AI: lines that
|
|
1109
|
-
// start with decision:/risk:/delivery:/contact: (case-insensitive) go to
|
|
1110
|
-
// LOG_FILES target as dated bullets; everything else lands in context.md
|
|
1111
|
-
// dated debrief block. contact: lines may carry an inline [signal:x]
|
|
1112
|
-
// anywhere in the text - preserved verbatim so computeSignals can trust it.
|
|
1113
|
-
// --smart: heuristic propose
|
|
1149
|
+
// start with decision:/risk:/delivery:/contact:/next: (case-insensitive) go to
|
|
1150
|
+
// their LOG_FILES target as dated bullets; everything else lands in context.md
|
|
1151
|
+
// as one dated debrief block. contact: lines may carry an inline [signal:x]
|
|
1152
|
+
// token anywhere in the text - preserved verbatim so computeSignals can trust it.
|
|
1153
|
+
// --smart: thin heuristic propose (existing prefixes + light keywords). Not a
|
|
1154
|
+
// brain — the agent rewrites .debrief-propose with prefixes; --apply commits.
|
|
1114
1155
|
// --dry-run prints the routing without writing anything.
|
|
1115
1156
|
function inferContactSignal(text) {
|
|
1116
1157
|
const t = String(text)
|
|
@@ -1178,8 +1219,13 @@ function setNextAction(eng, text) {
|
|
|
1178
1219
|
const p = path.join(eng, 'context.md')
|
|
1179
1220
|
let md = readEng(eng, 'context.md')
|
|
1180
1221
|
if (!md) md = '# Engagement context\n\n'
|
|
1181
|
-
|
|
1182
|
-
|
|
1222
|
+
// Collapse duplicate ## Next action headings (skill-append trap) into one.
|
|
1223
|
+
md = stripAllSections(md, 'Next action')
|
|
1224
|
+
if (/^##\s+Current state\b/im.test(md)) {
|
|
1225
|
+
md = md.replace(
|
|
1226
|
+
/(^##\s+Current state\b[^\n]*\n)([\s\S]*?)(?=^##\s|\s*$)/im,
|
|
1227
|
+
(_, h, body) => `${h}${String(body).replace(/\n*$/, '\n')}\n## Next action\n\n${bullet}\n\n`
|
|
1228
|
+
)
|
|
1183
1229
|
} else {
|
|
1184
1230
|
md = md.replace(/\n*$/, `\n\n## Next action\n\n${bullet}\n`)
|
|
1185
1231
|
}
|
|
@@ -1593,8 +1639,13 @@ function collectDoctorIssues(eng) {
|
|
|
1593
1639
|
}
|
|
1594
1640
|
const success = readClean(eng, 'success.md')
|
|
1595
1641
|
if (!firstLine(success, 80)) issues.push('success.md has no stated done-definition - fill before plan/build')
|
|
1596
|
-
|
|
1642
|
+
const ctxMd = readClean(eng, 'context.md')
|
|
1643
|
+
if (!sectionBody(ctxMd, 'Next action', { lastNonEmpty: true })) {
|
|
1597
1644
|
issues.push('no ## Next action in context.md - Monday morning has nothing to drive')
|
|
1645
|
+
} else if (countSections(ctxMd, 'Next action') > 1) {
|
|
1646
|
+
issues.push(
|
|
1647
|
+
'duplicate ## Next action headings in context.md - fill the first (template) section and remove extras; triage reads the last non-empty'
|
|
1648
|
+
)
|
|
1598
1649
|
}
|
|
1599
1650
|
if ((s.phase === 'close' || s.phase === 'ship') && s.openRisks > 0) {
|
|
1600
1651
|
issues.push(
|
|
@@ -2090,7 +2141,7 @@ function cmdDashboard(args) {
|
|
|
2090
2141
|
// one-liners, sector/overlay, days elapsed, and the four structured widgets.
|
|
2091
2142
|
engagements.forEach(e => {
|
|
2092
2143
|
const ctx = readClean(e.dir, 'context.md')
|
|
2093
|
-
e.next = (sectionBody(ctx, 'Next action').split('\n').find(l => l.trim()) || '').trim()
|
|
2144
|
+
e.next = (sectionBody(ctx, 'Next action', { lastNonEmpty: true }).split('\n').find(l => l.trim()) || '').trim()
|
|
2094
2145
|
e.hasNext = !!e.next
|
|
2095
2146
|
e.lastSession = firstLine(sectionBody(ctx, 'Current state'), 240)
|
|
2096
2147
|
// 220, not 140 - now that brief/reality each get their own full-width
|
|
@@ -2158,7 +2209,7 @@ function printUsage() {
|
|
|
2158
2209
|
fde log phase <phase> set engagement phase (land|discover|plan|build|ship|close)
|
|
2159
2210
|
fde log --undo remove the last CLI log/debrief entry from memory
|
|
2160
2211
|
fde debrief [file] meeting notes → memory (prefixed lines; --dry-run; --force)
|
|
2161
|
-
fde debrief --smart propose
|
|
2212
|
+
fde debrief --smart heuristic propose (prefix + light keywords); agent routes, CLI gates → --apply
|
|
2162
2213
|
fde prep [label] grounded walk-in brief from existing .fde/ only
|
|
2163
2214
|
fde doctor lint engagement memory (stale signals, gaps)
|
|
2164
2215
|
fde redact <term> preview/remove lines containing a buried term (pass --apply to commit)
|
package/bin/lib/trust.js
CHANGED
|
@@ -85,7 +85,9 @@ function createTrustApi(deps) {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
function nextActionLine(ctx) {
|
|
88
|
-
|
|
88
|
+
// lastNonEmpty: template ships an empty ## Next action; agents often append a
|
|
89
|
+
// second heading with the real bullet — first-match would report "(none set)".
|
|
90
|
+
const body = sectionBody(ctx, 'Next action', { lastNonEmpty: true })
|
|
89
91
|
for (const raw of body.split('\n')) {
|
|
90
92
|
const t = raw.trim().replace(/^[-*]\s+/, '')
|
|
91
93
|
if (t) return t.slice(0, 120)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fdeops",
|
|
3
|
-
"version": "3.9.
|
|
3
|
+
"version": "3.9.17",
|
|
4
4
|
"description": "Field kit for engineers embedded in client work - a real CLI (recon, memory, portfolio), one @fde skill with field judgment on top, and hooks that make it automatic. Claude Code plugin and any agent that loads skills.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"fdeops": "bin/install.js",
|
package/skills/fde/SKILL.md
CHANGED
|
@@ -35,7 +35,18 @@ This is what makes fdeops a second brain instead of a chat window.
|
|
|
35
35
|
2. **Deliverable = memory.** The output of every phase IS a `.fde/` file. You never ask the FDE to "update their notes" - producing the work and writing the memory are one action. The phase reference tells you which file.
|
|
36
36
|
3. **Evidence rule.** Every claim in an artifact carries its source: `(validated with: ops lead, Day 5)`, `(churn: 47 commits/90d)`, `(stated, unverified)`. The FDE defends these files in front of skeptical clients - traceable beats plausible.
|
|
37
37
|
4. **No invented facts - ever.** People, names, quotes, meetings, and numbers exist only if the FDE said them or the repo shows them. Never invent a stakeholder, a conversation, or a source to make the narrative richer - one fabricated name poisons every real citation around it. A missing fact is written as `unknown - ask: <the question>`, nothing else.
|
|
38
|
-
5. **On exit:** before the session ends
|
|
38
|
+
5. **On exit (session digest):** before the session ends — and again before opening a PR — capture the *thinking*, not the chat. Propose this digest in plain language; on FDE confirm, write into existing `.fde/` files (never a transcript dump, never a product-repo history folder):
|
|
39
|
+
|
|
40
|
+
| Digest beat | Lands in |
|
|
41
|
+
|-------------|----------|
|
|
42
|
+
| **TL;DR** (1–2 sentences: what moved) | `context.md` current state / short dated note |
|
|
43
|
+
| **Key decisions & why** (only real ones) | `decisions.md` dated lines — skip if none |
|
|
44
|
+
| **Pivot / aha** (course correction that mattered) | one line in `context.md`, or `decisions.md` if it changed the plan |
|
|
45
|
+
| **Scope + verification** (files/slice + how you checked) | `delivery.md` when code or a PR is in play; else skip |
|
|
46
|
+
| **Gotchas for the next reader** | `context.md` (teammate / Monday-you) |
|
|
47
|
+
| **Next action** | existing `## Next action` — **replace** the bullet; never append a second heading |
|
|
48
|
+
|
|
49
|
+
The `session-stop` hook backstops a thin snapshot; **you** write the meaningful digest. Raw agent transcripts stay on the machine — judgment is what ships in the fieldbook.
|
|
39
50
|
6. **One customer, one folder.** Never merge two engagements into one `.fde/`. Confirm which engagement applies when multiple exist.
|
|
40
51
|
7. **Never delete a code-read section when rewriting an artifact.** `stakeholders.md`'s `## Signal history` holds dated `[signal:...]` tokens that `fde status`/`fde receipts`/the dashboard read verbatim; `risks.md`'s `## Retired` is read the same way. Rewriting either file as an artifact (land, audit, stakeholder-radar) is fine - dropping one of these sections is not. Carry existing entries forward untouched.
|
|
41
52
|
|
|
@@ -51,6 +62,7 @@ These stop confident fiction. They are not optional soft tips.
|
|
|
51
62
|
| Fill `success.md` / `terrain.md` with plausible defaults when the brief is thin | **Stop.** Run **brief interrogation** in land/discover (one Q + GUESS + confidence) until you can write without guessing, or leave gaps explicit. |
|
|
52
63
|
| Ship / go-live / irreversible change with "probably fine" | **Stop.** Run **intent vs diff** (KEEP/JUSTIFY/SPLIT/DROP) then **pre-blast challenge** in ship (or red-team) — CLAIM → CHALLENGE → VERDICT — and log both. |
|
|
53
64
|
| Grill the FDE with a checklist when they're mid-flow | **Stop.** Playback rule wins. Probe only when a missing fact changes the next move. |
|
|
65
|
+
| Sync chat transcripts / agent brain folders into the product git repo for "team share" | **Stop.** Run **session digest** into `.fde/` (judgment only). Transcripts stay local. |
|
|
54
66
|
|
|
55
67
|
When NOT to interrogate or challenge: unambiguous one-liners, mechanical ops, FDE explicitly asked for speed, answer already in `.fde/`.
|
|
56
68
|
|
|
@@ -70,7 +82,7 @@ When NOT to interrogate or challenge: unambiguous one-liners, mechanical ops, FD
|
|
|
70
82
|
|-----------------------------|---------|
|
|
71
83
|
| (session entry / where are we) | `fde resume` or use injected TRIAGE; `fde resume --init <name>` only if unbound |
|
|
72
84
|
| Day-1 look at the repo | `fde scan` - then you interpret against the brief |
|
|
73
|
-
| "Debrief these notes" / pastes meeting notes | Prefer `fde debrief --smart <notes>` →
|
|
85
|
+
| "Debrief these notes" / pastes meeting notes | Prefer `fde debrief --smart <notes>` → **you** (the agent) rewrite `.debrief-propose` with `decision:`/`risk:`/`delivery:`/`contact:`/`next:` prefixes where needed → show FDE → on confirm `fde debrief --apply`. `--smart` is a prefix/keyword gate, not a brain. Fallback: structure prefixed lines yourself, show FDE, then `fde debrief` |
|
|
74
86
|
| "Prep me for the meeting with …" / walk-in brief | `fde prep "<short label>"` - present the brief in plain language; do not invent facts missing from `.fde/` |
|
|
75
87
|
| "When did we agree…?" / scope dispute | `fde receipts <term>` - answer with dates; no hit = gap, not proof |
|
|
76
88
|
| "Draft the sponsor update" / how are we doing | `fde status` then follow `references/status.md` for the narrative |
|
|
@@ -79,7 +91,7 @@ When NOT to interrogate or challenge: unambiguous one-liners, mechanical ops, FD
|
|
|
79
91
|
| "Clean up the fieldbook" / hygiene / memory feels messy | `fde doctor` - walk issues in plain language; propose fixes; never auto-rewrite without confirm. Contradictions need judgment (brief vs reality) - doctor is structural; you handle meaning. |
|
|
80
92
|
| "Scrub this secret / redact that token" (buried line, not just last write) | `fde redact <term>` preview, then `fde redact <term> --apply` after confirm. Undo is last-write only; redact is for buried lines. Remind them to rotate the real credential. |
|
|
81
93
|
|
|
82
|
-
**The debrief verb.** Highest-frequency loop. When the FDE shares notes or says "debrief": **you** run the smart path (write notes to a temp file if needed). Show the proposed routing in plain language. Only `--apply` (or pipe prefixed lines) after they confirm. Never ask them to run the CLI. Detail: `references/debrief.md`.
|
|
94
|
+
**The debrief verb.** Highest-frequency loop. When the FDE shares notes or says "debrief": **you** run the smart path (write notes to a temp file if needed). `--smart` writes a propose file via deterministic heuristics (existing prefixes + light keywords); authentic rambling notes often land mostly in context until **you** rewrite lines with type prefixes. Show the proposed routing in plain language. Only `--apply` (or pipe prefixed lines) after they confirm. Never ask them to run the CLI. Detail: `references/debrief.md`.
|
|
83
95
|
|
|
84
96
|
CLI missing → use the manual fallbacks inside each reference (still you write files; still never ask the FDE to run setup).
|
|
85
97
|
|
|
@@ -244,6 +256,7 @@ Getting to production without surprises.
|
|
|
244
256
|
| Ready to deploy, going live, pre-flight check | ship | `references/ship.md` |
|
|
245
257
|
| Review this change, is it safe, does it match what we agreed | review | `references/review.md` |
|
|
246
258
|
| Diff grew / scope creep in the PR / "did we only build what we said" / KEEP JUSTIFY SPLIT DROP | review (+ ship if going live) | `references/review.md` Stage 1 · `references/ship.md` Intent vs diff |
|
|
259
|
+
| Wrap the session / share the thinking / catch teammates up / before I open the PR | (memory contract — session digest) | SKILL.md **On exit** — write TL;DR + decisions/why into `.fde/`; no transcript sync |
|
|
247
260
|
| "We can always revert" - need to actually test the escape route | rollback-drill | `references/rollback-drill.md` |
|
|
248
261
|
| Need to test from user perspective, "works on my machine" | qa-live | `references/qa-live.md` |
|
|
249
262
|
|
|
@@ -58,7 +58,7 @@ The spec becomes the test list - every line is something to verify after build.
|
|
|
58
58
|
- `[DEFERRED]` intentionally left for a later task (state which one)
|
|
59
59
|
Surface the results to the FDE. If any scenario fails, fix it before cleanup. This is not optional - the spec is the contract.
|
|
60
60
|
9. **Cleanup pass after it works.** Dedupe repeated mechanics into the smallest service module; behavior unchanged; re-run the same tests. If you wrote 200 lines and 50 would do, rewrite before review.
|
|
61
|
-
10. **Review gate (before merge):**
|
|
61
|
+
10. **Review gate (before merge):** three beats, in order - (a) **session digest**: TL;DR + decisions/why + scope/verification into `.fde/` so the PR carries thinking, not just code (memory contract On exit; see `review.md`); (b) **intent vs diff**: every path KEEP / JUSTIFY / SPLIT / DROP against the stated slice in `decisions.md` (see `review.md` Stage 1); (c) **safety**: blast radius honest, tests meaningful, rollback real, secrets absent. Fix real findings, re-verify, repeat until clean or blocked on a human decision.
|
|
62
62
|
11. **Log and deliver.** Update the artifacts (below). Visible progress beats invisible perfection - every 2–3 tasks something shown to a stakeholder.
|
|
63
63
|
|
|
64
64
|
**Touching existing code - classify before changing:**
|
|
@@ -6,21 +6,34 @@
|
|
|
6
6
|
|
|
7
7
|
**Who runs the CLI:** you (the agent). Never tell the FDE to type `fde debrief …`.
|
|
8
8
|
|
|
9
|
+
## Honest contract (read once)
|
|
10
|
+
|
|
11
|
+
- The `fde` CLI is **local, deterministic, no AI**. `--smart` is a **gate + writer**, not a brain.
|
|
12
|
+
- It keeps lines that already have `decision:` / `risk:` / `delivery:` / `contact:` / `next:` prefixes, plus a thin keyword pass (e.g. "we agreed", person+verb lines, "open question").
|
|
13
|
+
- Real messy notes without prefixes often route **0 useful lines** — everything else lands as a context dump. That is expected. **You are the router:** rewrite `.debrief-propose` with type prefixes, then `--apply`.
|
|
14
|
+
- `.debrief-propose` is raw lines only (no routing annotations). "Edit if mis-routed" means **rewrite the line with the right prefix**, not leave a comment in the file.
|
|
15
|
+
|
|
9
16
|
## Method (you do this work)
|
|
10
17
|
|
|
11
18
|
### Preferred path - smart debrief (messy notes)
|
|
12
19
|
|
|
13
20
|
1. Save the FDE's notes to a temp `.md` file in the workspace (or pipe stdin).
|
|
14
21
|
2. Run `fde debrief --smart <notes.md>` (or `npx fdeops debrief --smart …`).
|
|
15
|
-
3.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
3. Open `.debrief-propose`. If lines lack type prefixes, **rewrite them** before showing the FDE, e.g.:
|
|
23
|
+
- `decision: agreed chargebacks stay phase 2 — Priya`
|
|
24
|
+
- `risk: legal may reopen scope if we slip the SOW date`
|
|
25
|
+
- `contact: Priya pushed hard on Friday deck [signal:amber]`
|
|
26
|
+
- `next: send one-pager before Thursday 9am`
|
|
27
|
+
- unprefixed lines stay context color only
|
|
28
|
+
4. Show the **proposed** routing in plain language (what would become decisions, risks, contacts, next).
|
|
29
|
+
5. On FDE confirm → run `fde debrief --apply`.
|
|
30
|
+
6. On reject → stop; ask what to change; do not apply.
|
|
31
|
+
|
|
32
|
+
No invented names or quotes. If the propose looks wrong, fix prefixes with judgment then re-apply or use the fallback path.
|
|
20
33
|
|
|
21
34
|
### Fallback - you structure, then route
|
|
22
35
|
|
|
23
|
-
If `--smart` is unavailable or
|
|
36
|
+
If `--smart` is unavailable or you already have clean prefixes:
|
|
24
37
|
|
|
25
38
|
1. Extract into buckets - **only what was actually said**:
|
|
26
39
|
- **Decisions** - agreed, by whom, in their words where possible
|
|
@@ -28,7 +41,7 @@ If `--smart` is unavailable or the notes are already cleanly prefixed:
|
|
|
28
41
|
- **Stakeholder signals** - tone shifts with evidence → green/amber/red
|
|
29
42
|
- **Risks** - new / confirmed / retired
|
|
30
43
|
- **Open questions** - what to chase next
|
|
31
|
-
2. Format lines as `decision:` / `risk:` / `delivery:` / `contact:` (contacts may end with `[signal:green|amber|red]`).
|
|
44
|
+
2. Format lines as `decision:` / `risk:` / `delivery:` / `contact:` / `next:` (contacts may end with `[signal:green|amber|red]`).
|
|
32
45
|
3. Show that structured version to the FDE for confirmation.
|
|
33
46
|
4. Pipe to `fde debrief` (or write a file and run it).
|
|
34
47
|
|
|
@@ -37,7 +50,8 @@ One clarifying question max if the dump is ambiguous - then write. Never stall c
|
|
|
37
50
|
## Artifact
|
|
38
51
|
|
|
39
52
|
- Smart apply / debrief CLI writes the dated routes into the right `.fde/` files.
|
|
40
|
-
-
|
|
53
|
+
- `next:` updates the existing `## Next action` in `context.md` (collapses duplicates). Do not append a second `## Next action` heading by hand.
|
|
54
|
+
- If you must write directly: decisions → `decisions.md`; signals → `stakeholders.md` Signal history; risks → `risks.md`; next actions → fill under the template `## Next action` in `context.md`. Prefer the CLI.
|
|
41
55
|
|
|
42
56
|
## Checkpoint
|
|
43
57
|
|
|
@@ -57,9 +57,15 @@ Five dimensions, line-specific ("line 47 fails under concurrent writes - no lock
|
|
|
57
57
|
5. Re-run tests/typechecks - state what ran.
|
|
58
58
|
6. Re-review. Repeat until Pass/Pass or a human must decide scope/product.
|
|
59
59
|
|
|
60
|
+
## Before the PR - thinking for the next reader
|
|
61
|
+
|
|
62
|
+
Code alone loses the "why." Before you call the change reviewable, run the **session digest** from the memory contract (SKILL.md On exit): TL;DR, key decisions & rationale, scope + how you verified, gotchas. Confirm with the FDE, then write into `.fde/` — `decisions.md` / `delivery.md` / `context.md`. Reviewers (or Monday-you) should answer "why this approach?" from the fieldbook, not from a chat transcript. Do **not** dump agent logs into the product repo.
|
|
63
|
+
|
|
60
64
|
## Artifact
|
|
61
65
|
|
|
62
|
-
**`decisions.md`** - each cycle logged: what was reviewed, flagged, fixed, verified. Stage 1 failures recorded with the specific mismatch.
|
|
66
|
+
**`decisions.md`** - each cycle logged: what was reviewed, flagged, fixed, verified. Stage 1 failures recorded with the specific mismatch. Digest decisions (with *why*) land here too when the slice ships.
|
|
67
|
+
|
|
68
|
+
**`delivery.md`** - scope + verification from the digest when a PR is opening; intent-vs-diff receipt stays the ship gate.
|
|
63
69
|
|
|
64
70
|
## Principles
|
|
65
71
|
|
|
@@ -68,3 +74,4 @@ Five dimensions, line-specific ("line 47 fails under concurrent writes - no lock
|
|
|
68
74
|
- Specific or silent - vague concerns waste everyone's time.
|
|
69
75
|
- No rollback path = first finding.
|
|
70
76
|
- A clean review proves this diff is safe as agreed - not that the feature was right.
|
|
77
|
+
- Judgment in `.fde/` beats transcript in git.
|