fdeops 3.9.19 → 3.10.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 +45 -7
- package/adapters/LOCAL-LLM.md +1 -1
- package/adapters/README.md +1 -1
- package/bin/check.js +219 -4
- package/bin/fde.js +379 -26
- package/bin/install.js +223 -20
- package/bin/lib/memory.js +2 -2
- package/bin/lib/render.js +2 -0
- package/mcp/README.md +5 -3
- package/mcp/fdeops-ingest/README.md +3 -1
- package/mcp/fdeops-ingest/package.json +1 -1
- package/mcp/fdeops-ingest/server.js +27 -17
- package/mcp/recipes/README.md +15 -0
- package/mcp/recipes/file.md +25 -0
- package/mcp/recipes/granola.md +58 -0
- package/mcp/recipes/notion.md +56 -0
- package/mcp.json +10 -0
- package/package.json +4 -2
- package/plugin.json +21 -0
- package/skills/fde/SKILL.md +4 -2
- package/skills/fde/references/assumption-audit.md +10 -0
- package/skills/fde/references/build.md +13 -1
- package/skills/fde/references/business-case.md +10 -0
- package/skills/fde/references/close.md +11 -1
- package/skills/fde/references/discover.md +10 -0
- package/skills/fde/references/ingest-connect.md +36 -0
- package/skills/fde/references/ingest.md +13 -3
- package/skills/fde/references/land.md +20 -0
- package/skills/fde/references/options-analysis.md +10 -0
- package/skills/fde/references/plan.md +10 -0
- package/skills/fde/references/scope-defense.md +10 -0
- package/skills/fde/references/ship.md +10 -0
- package/skills/fde/references/stakeholder-radar.md +21 -0
- package/skills/fde/references/status.md +12 -2
- package/templates/.fde/delivery.md +3 -3
package/skills/fde/SKILL.md
CHANGED
|
@@ -83,7 +83,8 @@ When NOT to interrogate or challenge: unambiguous one-liners, mechanical ops, FD
|
|
|
83
83
|
| (session entry / where are we) | `fde resume` or use injected TRIAGE; `fde resume --init <name>` only if unbound |
|
|
84
84
|
| Day-1 look at the repo | `fde scan` - then you interpret against the brief |
|
|
85
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` |
|
|
86
|
-
| "Make sure we're up to date" / "pull relevant info" / "pull from Granola/email/transcript" | Bind engagement;
|
|
86
|
+
| "Make sure we're up to date" / "pull relevant info" / "pull from Granola/email/transcript" | Bind engagement; **capability check** (which source MCPs exist this session — never pretend). If missing → connect flow. Else fetch → `fde ingest stage` → `fde ingest propose` → rewrite prefixes → show FDE → on confirm `fde ingest apply`. **Never auto-apply. Never ambient sync.** Detail: `references/ingest.md` |
|
|
87
|
+
| "Connect a new MCP" / "connect Granola/Notion" / "what can you pull?" | Follow `references/ingest-connect.md`: ask which source → emit `mcp.json` from `mcp/recipes/` + sink block → they save/reload in Cursor/Claude → verify tools → optional test stage to `.inbox/` only. You cannot silently install host MCPs. |
|
|
87
88
|
| "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/` |
|
|
88
89
|
| "When did we agree…?" / scope dispute | `fde receipts <term>` - answer with dates; no hit = gap, not proof |
|
|
89
90
|
| "Draft the sponsor update" / how are we doing | `fde status` then follow `references/status.md` for the narrative |
|
|
@@ -270,7 +271,8 @@ Running the engagement and ending it well.
|
|
|
270
271
|
| Weekly update due, "need to send the sponsor something" | status | `references/status.md` |
|
|
271
272
|
| Demo coming up, show-and-tell, exec walkthrough | demo-prep | `references/demo-prep.md` |
|
|
272
273
|
| Just out of a meeting, raw notes, "they said…", "debrief" | debrief | the debrief verb (above) + `references/debrief.md` |
|
|
273
|
-
| Make sure we're up to date, pull what's relevant, fetch from Granola/Gmail/transcript | ingest | `references/ingest.md` (stage → propose → confirm → apply
|
|
274
|
+
| Make sure we're up to date, pull what's relevant, fetch from Granola/Gmail/transcript | ingest | `references/ingest.md` (capability check → stage → propose → confirm → apply) |
|
|
275
|
+
| Connect a new MCP / connect Granola or Notion / what can you pull | ingest-connect | `references/ingest-connect.md` (+ `mcp/recipes/`) |
|
|
274
276
|
| Prep me for a meeting / walk-in brief / "what should I know before I talk to…" | - | run `fde prep "<label>"`, present in plain language |
|
|
275
277
|
| Sponsor's boss needs a summary, board update, justify continued investment | exec-narrative | `references/exec-narrative.md` |
|
|
276
278
|
| Status across all my customers | dashboard | `references/dashboard.md` |
|
|
@@ -72,6 +72,16 @@ Status values: `OPEN` · `TESTING` · `CONFIRMED` · `DISPROVED` · `PARKED`. A
|
|
|
72
72
|
|
|
73
73
|
Tell the FDE: how many assumptions extracted, how many critical, which ones were tested, which changed the direction. If a critical assumption is disproved: recommend the next move (rescope, pivot, or the conversation with the sponsor) before the FDE asks. If any CRITICAL remains OPEN: do not route to plan.
|
|
74
74
|
|
|
75
|
+
## Worked example
|
|
76
|
+
|
|
77
|
+
Acme's brief reads cleanly, which is the signal.
|
|
78
|
+
|
|
79
|
+
Extracted assumptions include one nobody said aloud: *finance would act on an alert*. The whole plan rests on it, and the evidence behind it is a sentence in a kickoff. Blast radius CRITICAL — if false, alerting changes nothing and the engagement delivers a page nobody answers.
|
|
80
|
+
|
|
81
|
+
Validation is a test, not a discussion, and it is cheap: send one real failure notification to the finance channel and watch what happens. It goes first because highest blast radius × cheapest test is the killer test.
|
|
82
|
+
|
|
83
|
+
Result: acked in 40 minutes, by Marco, not finance. Assumption DISPROVED, and the plan changes before six weeks are spent on it — the alert needs a rota with an owner, which is a different piece of work than the one that was funded. `assumptions.md` records the status, the evidence, and the date; the finding is presented to the FDE as a fact base, not as "the brief was wrong".
|
|
84
|
+
|
|
75
85
|
## Principles
|
|
76
86
|
|
|
77
87
|
- Every "just" is an assumption. Every "should" is an assumption.
|
|
@@ -127,12 +127,24 @@ The FDE's job is to make themselves replaceable. Not at handoff - every day. A c
|
|
|
127
127
|
|
|
128
128
|
- **`decisions.md`** - each significant choice: what, alternatives considered, why this one. For non-trivial architecture decisions, present three options to the FDE (safe / pragmatic / aggressive) with costs and a recommendation - three options is a real decision; one option is a request for trust. Integration contracts go here too.
|
|
129
129
|
- **`risks.md`** - new risks discovered while building.
|
|
130
|
-
- **`delivery.md`** - append a **value ledger** row for every ship: Date | Slice | Bucket | Promised | Measured | Evidence | Rollback. Bucket is `cost-save` / `risk-mitigation` / `revenue-uplift`. "Measured" may be `pending` until the pulse exists - never skip the promised column. Narrative under Shipped is optional color; the ledger is the record status and close read.
|
|
130
|
+
- **`delivery.md`** - append a **value ledger** row for every ship: Date | Slice | Bucket | Promised | Measured | Accepted by | Evidence | Rollback. Bucket is `cost-save` / `risk-mitigation` / `revenue-uplift`. "Measured" may be `pending` until the pulse exists - never skip the promised column. Narrative under Shipped is optional color; the ledger is the record status and close read.
|
|
131
|
+
|
|
132
|
+
**Measured is not the same as accepted.** A number the FDE calculated is `claimed` until a named customer-side owner agrees it is real - their finance lead, their ops manager, the person whose budget it moves. Write the name and the date in **Accepted by**; leave it empty and the row reads `claimed`, never "delivered". This is the difference between a benefit that survives the renewal conversation and one the sponsor's CFO deletes in the review.
|
|
131
133
|
|
|
132
134
|
## Checkpoint
|
|
133
135
|
|
|
134
136
|
Before merge: the two-stage review (scope, then safety) has run clean, verification evidence is stated, and the slice is demonstrable. If `trust-profile.md` requires human sign-off on AI-generated code, that sign-off exists.
|
|
135
137
|
|
|
138
|
+
## Worked example
|
|
139
|
+
|
|
140
|
+
Acme task 1: route reconciliation failures to a named on-call.
|
|
141
|
+
|
|
142
|
+
Characterisation first — a test that captures what the job does *today* when it exits non-zero (silently succeeds from the caller's perspective). That test fails after the fix, which is the point: it documents the behaviour being changed rather than trusting the diff.
|
|
143
|
+
|
|
144
|
+
Mid-build, Tom asks to "just also fix the retry logic while you're in there." That is a scope decision, not a request: logged in `decisions.md` with the blast radius (retry touches the settlement path — not in this slice's declared radius) and routed to the plan's Next lane.
|
|
145
|
+
|
|
146
|
+
Ledger row on ship: `Jun 18 | failure routing | risk-mitigation | 4h → 15min detection | pending | — | staging kill test, PR #212 | disable alert route`. **Accepted by** stays empty until Marco confirms from a real incident — until then the number is claimed, and the status update says so.
|
|
147
|
+
|
|
136
148
|
## Principles
|
|
137
149
|
|
|
138
150
|
- Characterisation tests before modification. Every time.
|
|
@@ -69,6 +69,16 @@ The sponsor who sees you've identified where the case could break trusts the cas
|
|
|
69
69
|
|
|
70
70
|
Walk the FDE through: the cost of doing nothing (anchor), the investment, the return, and the one sensitivity that matters most. If the FDE says "the sponsor won't buy the ROI number" - ask what number they would believe and work backwards from there.
|
|
71
71
|
|
|
72
|
+
## Worked example
|
|
73
|
+
|
|
74
|
+
Acme phase 2 needs funding. The case starts with the cost of doing nothing, not the cost of building.
|
|
75
|
+
|
|
76
|
+
Anchor: two silent failures since March, each one day of finance reconciliation by hand plus a late close (`reality.md`, Marco's sheet). That is the number the sponsor already believes because her own team reported it.
|
|
77
|
+
|
|
78
|
+
Driver model the sponsor can trace: incidents/quarter × hours of manual reconciliation × loaded cost, plus the tail risk of a late regulatory close — stated separately, because mixing a certain small number with an uncertain large one is how a case loses credibility.
|
|
79
|
+
|
|
80
|
+
Sensitivity names the two drivers that swing it: incident frequency (2/quarter → 1/quarter and the case halves) and whether the manual re-run continues in parallel (if Marco keeps re-running every morning, the saving is theoretical). The second one is the honest weakness, so it is in the case rather than waiting to be found in the room — with the condition that makes it hold: the morning re-run stops after two clean cycles, agreed with Marco.
|
|
81
|
+
|
|
72
82
|
## Principles
|
|
73
83
|
|
|
74
84
|
- The cost of doing nothing is always the opening move. Anchor before proposing.
|
|
@@ -18,7 +18,7 @@ The engagement doesn't end at ship. It ends when the customer can maintain what
|
|
|
18
18
|
- AI components: did they behave in production? What failure modes did the prototype hide? Is the team equipped to maintain them?
|
|
19
19
|
|
|
20
20
|
**1b. Value + receipts close gate (refuse green close if any fail):**
|
|
21
|
-
- Primary value bucket in `success.md` matches what the sponsor funded; at least one ledger row has **Measured** (not forever-`pending`) with evidence for that bucket — or the retrospective explicitly records “not measured; sponsor accepted pending.”
|
|
21
|
+
- Primary value bucket in `success.md` matches what the sponsor funded; at least one ledger row has **Measured** (not forever-`pending`) with evidence **and a named customer-side owner in Accepted by** for that bucket — or the retrospective explicitly records “not measured; sponsor accepted pending.” A measured-but-unaccepted number closes as `claimed`; say so in the retrospective rather than closing green on arithmetic nobody signed.
|
|
22
22
|
- Audit receipt exists for the final shipped path (exceptions/operating map walked; cite file).
|
|
23
23
|
- Eval receipt: **n/a if no AI**, else final golden/eval result + HITL owner recorded; kill switch / fallback named in `handoff.md`.
|
|
24
24
|
- One line in the retrospective: which bucket moved, by how much, vs baseline.
|
|
@@ -41,6 +41,16 @@ The engagement doesn't end at ship. It ends when the customer can maintain what
|
|
|
41
41
|
|
|
42
42
|
Direct assessment to the FDE: did the engagement achieve `success.md` · 2–3 lessons that matter · is the pattern worth encoding · is the handoff complete or where are the gaps. Also: value bucket + audit receipt green; eval **n/a or green**. Pending Measured without sponsor acceptance = gap, not green close. Honest - a gap named now is cheaper than a callback in six weeks.
|
|
43
43
|
|
|
44
|
+
## Worked example
|
|
45
|
+
|
|
46
|
+
Acme, twelve weeks in, the FDE is rolling off.
|
|
47
|
+
|
|
48
|
+
Retrospective against the receipts: `brief.md` asked for monitoring, `reality.md` proved it was ownership — and the delta is the most useful paragraph in the file, because it is exactly the argument the next engagement will need.
|
|
49
|
+
|
|
50
|
+
The close gate bites in a useful way. The ledger shows detection at 12 minutes measured across two real incidents, but **Accepted by** is empty — Marco confirmed it in Slack, Denise (finance) never did, and Denise is whose escalation started the engagement. So it closes as `claimed` with a one-line retrospective note and a named next step, rather than a green close on a number nobody with budget agreed to.
|
|
51
|
+
|
|
52
|
+
`handoff.md` is written for the person woken at 2am: the three things that break, what the page means, how to re-run manually the way Marco does, and who holds the tribal knowledge (Raj, who built the original job — credited, because he protects it now). `patterns.md` gets *"unowned job" presents as "unmonitored job"* — it has now happened twice.
|
|
53
|
+
|
|
44
54
|
## Principles
|
|
45
55
|
|
|
46
56
|
- Done = the customer operates without you.
|
|
@@ -192,6 +192,16 @@ If discovery revealed the problem is 3× the brief: the FDE tells the customer *
|
|
|
192
192
|
|
|
193
193
|
Stop. Don't form a fourth hypothesis. Three disproven reads means the brief is actively misleading - usually the person who briefed doesn't know, or knows and can't say. Change method: stop analysing the system, ask three people separately "if you had to bet on what's actually wrong here, what would you say?" The thing they all hesitate before saying is the real problem.
|
|
194
194
|
|
|
195
|
+
## Worked example
|
|
196
|
+
|
|
197
|
+
Acme's brief blamed missing monitoring. Discovery goes to the workaround first.
|
|
198
|
+
|
|
199
|
+
`git log` shows the reconciliation module at 47 commits/90d with no tests, all from one author who left in February. Marco (ops lead) turns out to keep a spreadsheet: every morning he re-runs the job manually and eyeballs the totals — a habit nobody mentioned because to him it is just the job. That spreadsheet is the system of record when the job fails, which is the actual finding.
|
|
200
|
+
|
|
201
|
+
`reality.md`: **Confirmed:** the job has no owner, and the manual re-run masks failures for a day (evidence: Marco's sheet, Day 5; two silent failures since March, finance escalation Mar 14). **Stated brief was wrong because:** alerting existed last year and was disabled — adding it again without an owner reproduces the same outcome. `terrain.md` gets the hotspot row and an operating-map row: `job fails silently → Marco notices next morning → re-runs by hand → spreadsheet is truth → LOAD-BEARING (Marco, Day 5)`.
|
|
202
|
+
|
|
203
|
+
Checkpoint to the FDE names the sponsor decision this creates: fund ownership, or fund alerting and accept the same failure in six months.
|
|
204
|
+
|
|
195
205
|
## Principles
|
|
196
206
|
|
|
197
207
|
- The brief is a hypothesis until evidence confirms it.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# ingest-connect - wire a source MCP in plain language
|
|
2
|
+
|
|
3
|
+
**Enter when:** the FDE says "I want to connect a new MCP", "connect Granola / Notion / Drive", "how do I pull from …", or a pull request fails because no source tools exist.
|
|
4
|
+
|
|
5
|
+
**Read first:** `references/ingest.md` (sink contract). Recipe pack: `mcp/recipes/` in the fdeops install (file, granola, notion).
|
|
6
|
+
|
|
7
|
+
**Who runs setup:** you guide; the **host** (Cursor/Claude) must save MCP config. You cannot silently install servers into the host.
|
|
8
|
+
|
|
9
|
+
## Honest contract
|
|
10
|
+
|
|
11
|
+
- FDEOps = **sink** (`fdeops-ingest` / `fde ingest`). Sources = **whatever MCP the FDE adds**.
|
|
12
|
+
- You produce a ready config snippet + steps. They save + reload. Then you verify with a capability check + optional test stage.
|
|
13
|
+
- Never invent that Granola/Notion is available if tools are missing. Never ambient sync. Never auto-apply to `.fde/`.
|
|
14
|
+
|
|
15
|
+
## Method
|
|
16
|
+
|
|
17
|
+
1. **Ask one question** — which source? (`file` / `granola` / `notion` / other name). If "other", ask for the MCP package or docs URL they intend to use.
|
|
18
|
+
2. **Capability check (current session)** — list MCP tools you can actually call:
|
|
19
|
+
- Sink present? (`ingest_stage` / `ingest_list` / or `fde ingest` CLI)
|
|
20
|
+
- Source present? (anything that can fetch that system's content)
|
|
21
|
+
- Say clearly: *available now* vs *needs config*.
|
|
22
|
+
3. **Emit config** — open the matching recipe under `mcp/recipes/<source>.md`. Fill absolute paths:
|
|
23
|
+
- path to `mcp/fdeops-ingest/server.js` (from this fdeops install)
|
|
24
|
+
- `FDEOPS_ENGAGEMENT` → this client's `…/<slug>/.fde`
|
|
25
|
+
- placeholders for source API keys (tell them to paste secrets into host env — do not commit keys into the fieldbook)
|
|
26
|
+
4. **Tell them where to paste** — Cursor: MCP settings / `~/.cursor/mcp.json` (or project MCP). Claude Code: MCP config per their docs. One sentence: save → reload MCP / restart session.
|
|
27
|
+
5. **Verify** — after they confirm reload: re-run capability check. If source tools appear, offer a **test pull** into `.inbox/` only (stage + show list). Stop before apply unless they ask to propose.
|
|
28
|
+
6. **Handoff phrase** — give them the daily line, e.g. `@fde pull today's Acme Granola into the fieldbook`.
|
|
29
|
+
|
|
30
|
+
## If they only want the sink
|
|
31
|
+
|
|
32
|
+
Still wire `fdeops-ingest` (or rely on CLI). File drops work with [mcp/recipes/file.md](../../../mcp/recipes/file.md) without any source MCP.
|
|
33
|
+
|
|
34
|
+
## Checkpoint
|
|
35
|
+
|
|
36
|
+
Before ending connect: (1) sink reachable, (2) source reachable or honest gap, (3) they know the pull phrase. Do not write `.fde/` during connect.
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
**Enter when:** the FDE wants to catch the engagement up from external sources — "make sure Acme is up to date," "pull what's relevant," "grab today's Granola and Denise's last email." Raw transcripts and long emails that are too big to paste usefully.
|
|
4
4
|
|
|
5
|
+
**Connect / capability (different entry):** "connect a new MCP", "connect Granola/Notion", "what can you pull?" → `references/ingest-connect.md` first. Recipes: `mcp/recipes/` (file, granola, notion).
|
|
6
|
+
|
|
5
7
|
**Read first:** `context.md` (what's already logged, what's stale). Bind the engagement before staging anything.
|
|
6
8
|
|
|
7
9
|
**Who runs the CLI:** you (the agent). Never tell the FDE to type `fde ingest …`. Never auto-apply. Never background-sync or poll sources on your own.
|
|
@@ -13,10 +15,18 @@
|
|
|
13
15
|
- The core `fde` CLI stays local (git + file reads). Source credentials live with that MCP; fdeops never stores them.
|
|
14
16
|
- After apply, raw stays in `.inbox/`; the system of record (`.fde/`) stays thin dated facts.
|
|
15
17
|
|
|
18
|
+
## Capability check (before every pull)
|
|
19
|
+
|
|
20
|
+
List what you can actually call **this session**:
|
|
21
|
+
|
|
22
|
+
1. **Sink** — `ingest_stage` / `fde ingest` available?
|
|
23
|
+
2. **Sources** — which fetch tools exist (Granola-shaped, Notion, Drive, file-only)?
|
|
24
|
+
3. Tell the FDE in one line: *I can pull from X; Y is not connected.* If they asked to pull Y and it is missing → switch to `ingest-connect.md`. Never pretend a source exists.
|
|
25
|
+
|
|
16
26
|
## Ground loop (you do this work)
|
|
17
27
|
|
|
18
28
|
1. **Bind** the engagement (`fde resume` / registry). If multiple meetings or threads could apply, ask **one** clarifying question — which meeting, which thread, which date range.
|
|
19
|
-
2. **
|
|
29
|
+
2. **Capability check** (above). Then **fetch** via available source MCP(s). You pull; the CLI does not reach the network.
|
|
20
30
|
3. **Stage** — `fde ingest stage [--source NAME] [--title TEXT] [file|-]` writes raw text into `<engagement>/.inbox/` (outside the memory git ledger).
|
|
21
31
|
4. **List** (optional) — `fde ingest list` shows staged items when you need an id or filename.
|
|
22
32
|
5. **Propose** — `fde ingest propose <id-or-filename>` runs the debrief `--smart` path on the staged body (+ provenance line). Opens `.debrief-propose`.
|
|
@@ -47,9 +57,9 @@ fde ingest apply
|
|
|
47
57
|
|
|
48
58
|
When a staged fact came from a named source, carry `via:<source>` on the applied line where useful (e.g. `via:granola`, `via:gmail`). Helps receipts and sponsor disputes later — not mandatory on every context line.
|
|
49
59
|
|
|
50
|
-
## MCP sink
|
|
60
|
+
## MCP sink + recipes
|
|
51
61
|
|
|
52
|
-
Optional `mcp/fdeops-ingest` wraps the same verbs over stdio. Source MCPs remain separate — the FDE adds whichever fetch tools they trust.
|
|
62
|
+
Optional `mcp/fdeops-ingest` wraps the same verbs over stdio. Source MCPs remain separate — the FDE adds whichever fetch tools they trust. Setup coach: `ingest-connect.md`. Copy-paste recipes: `mcp/recipes/`.
|
|
53
63
|
|
|
54
64
|
## Checkpoint
|
|
55
65
|
|
|
@@ -79,6 +79,16 @@ Before the end of day 1, ship one visible thing: a small bug fix, a cleanup the
|
|
|
79
79
|
|
|
80
80
|
**`success.md`** - what done looks like, **primary value bucket** (`cost-save` | `risk-mitigation` | `revenue-uplift`), baseline → target, who actually signs off, what is explicitly out of scope. Agreed with the customer, not assumed.
|
|
81
81
|
|
|
82
|
+
For every target number, run the **gaming check** before it is written down: *how could this metric hit its target without the customer being any better off?* There is always an answer, and the answer is what the org will drift toward under pressure. Write the guard next to the metric:
|
|
83
|
+
|
|
84
|
+
```markdown
|
|
85
|
+
| Metric | Baseline → target | Gamed by | Guard |
|
|
86
|
+
|--------|-------------------|----------|-------|
|
|
87
|
+
| reconciliation alert latency | 4h → 15min | alerting on everything, so nobody reads them | alerts acked by a named owner, ≤2/week |
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
A metric with no gaming check is a metric the FDE will be held to and cannot defend. If the customer resists the guard, that is the real conversation - they are attached to the number, not the outcome.
|
|
91
|
+
|
|
82
92
|
**`stakeholders.md`**:
|
|
83
93
|
```markdown
|
|
84
94
|
| Who | Role | Signal | Notes |
|
|
@@ -105,6 +115,16 @@ One page back to the FDE: success + value bucket + sign-off owner, out-of-scope
|
|
|
105
115
|
|
|
106
116
|
If remote: trust-building takes ~40% longer - push for a short video call before anything asynchronous.
|
|
107
117
|
|
|
118
|
+
## Worked example
|
|
119
|
+
|
|
120
|
+
Kickoff at Acme payments. Priya (VP Eng) sponsors; the brief says "add monitoring to the reconciliation service."
|
|
121
|
+
|
|
122
|
+
Asking what happens the week after a perfect delivery gets: "I stop hearing about it from finance." That is the real success statement — not monitoring. The previous attempt surfaces too: the platform team built alerting last year, it was turned off. Raj, who built it, is still there and was not in the kickoff — the passed-over team, found on day 1 rather than at the first standup.
|
|
123
|
+
|
|
124
|
+
What gets written: `success.md` with bucket `risk-mitigation`, `reconciliation failures reach a named owner within 15 min (baseline: 4h, found by finance)`, gaming check `alerting on everything so nobody reads them` → guard `≤2 alerts/week, acked by name`, sign-off Priya. `brief.md` carries the gap list and the hypothesis: *the job is not unmonitored, it is unowned*. `assumptions.md` seeds `"finance would act on an alert" — CRITICAL — OPEN — (stated, unverified)`. `trust-profile.md` records the sacred thing Priya hesitated before naming.
|
|
125
|
+
|
|
126
|
+
Day-1 deliverable: fix the log line that swallows the job's exit code. Small, visible, in their environment.
|
|
127
|
+
|
|
108
128
|
## Principles
|
|
109
129
|
|
|
110
130
|
- Never start technical work before `success.md` exists.
|
|
@@ -72,6 +72,16 @@ The full option details in the same entry or linked to a section in `reality.md`
|
|
|
72
72
|
|
|
73
73
|
Present the three options and the recommendation. One question to the FDE: "Which option matches what the sponsor can hear right now?" (A risk-averse sponsor after an incident → conservative. A founder pre-fundraise → ambitious.) If unsure: present all three and let the sponsor decide.
|
|
74
74
|
|
|
75
|
+
## Worked example
|
|
76
|
+
|
|
77
|
+
Acme: the reconciliation job needs to survive the FDE leaving. Priya asks "so what should we do?"
|
|
78
|
+
|
|
79
|
+
Three real paths, not a strawman set. **Safe:** keep the job, add the rota and runbook — two weeks, no new failure modes, does nothing about the 47-commits/90d hotspot. **Pragmatic:** extract the settlement-matching step behind a tested interface — six weeks, retires the untested hotspot, needs Raj's time and he currently opposes it. **Aggressive:** rewrite the service — a quarter, fixes everything, and the same team already abandoned this once.
|
|
80
|
+
|
|
81
|
+
Same dimensions on each, so comparison is instant, and every cost carries a source: the six-week figure is churn-based, not felt.
|
|
82
|
+
|
|
83
|
+
Recommendation: pragmatic, conditional — *if* Raj is on the design, otherwise safe, because the aggressive path failed here before for exactly the reason it would fail again. `decisions.md` records the decision, who chose it, and the condition, so week 10's "why aren't we rewriting it" has an answer with a date on it.
|
|
84
|
+
|
|
75
85
|
## Principles
|
|
76
86
|
|
|
77
87
|
- Three options, never one. One option is a request for trust; three is a real decision.
|
|
@@ -131,6 +131,16 @@ Write migration strategy to `decisions.md` under `## Migration`. Each service ge
|
|
|
131
131
|
|
|
132
132
|
Never quietly update tasks. Name the reset: update `reality.md` and `success.md`, one paragraph in `decisions.md` - what changed, why, new sequence. An undocumented reset looks like drift; a documented one looks like the FDE caught something important.
|
|
133
133
|
|
|
134
|
+
## Worked example
|
|
135
|
+
|
|
136
|
+
Acme, after discover: the reconciliation job is unowned, Marco's spreadsheet is the real fallback.
|
|
137
|
+
|
|
138
|
+
**Now** is three tasks, not eight. Task 1 is *failures reach a named human* — delivers a page to a rota, accepts "kill the job mid-run → the on-call is paged within 15 min", touches the job wrapper and the alert config, rollback is re-disable the route, verify by killing it in staging. Value promised: `risk-mitigation — a silent failure becomes a 15-minute one`.
|
|
139
|
+
|
|
140
|
+
The kill list in `decisions.md` is where the plan earns its keep: the rewrite of the reconciliation service that Tom keeps proposing goes there — *deferred, the failure mode is ownership not architecture (Priya accepted, Jun 12)* — along with the finance dashboard finance asked for directly. Both stay visible so the same argument is not re-litigated in week 4 without a receipt.
|
|
141
|
+
|
|
142
|
+
First visible slice goes to Marco, not Priya: he is the one whose morning changes, and his confirmation is what makes the sponsor update true.
|
|
143
|
+
|
|
134
144
|
## Principles
|
|
135
145
|
|
|
136
146
|
- Plan from success backwards, not from today forwards.
|
|
@@ -61,6 +61,16 @@ Evidence-based: point to `decisions.md` scope receipts with dates and requesters
|
|
|
61
61
|
|
|
62
62
|
Weekly check: count the scope receipts since last conversation. Three or more unaddressed → recommend the accumulation conversation to the FDE. Zero → "scope holding, `success.md` current."
|
|
63
63
|
|
|
64
|
+
## Worked example
|
|
65
|
+
|
|
66
|
+
Acme, week 5. Nothing has been formally added, and the slice is a week late.
|
|
67
|
+
|
|
68
|
+
The pattern shows in three receipts, not one argument: a "quick" finance CSV export (Jun 20, half a day, from Denise directly), retry-logic cleanup asked for mid-build (Jun 24, one day, Tom), and a dashboard tile "while you're in there" (Jun 27, half a day). Each was individually reasonable; together they are the slip.
|
|
69
|
+
|
|
70
|
+
Three-bucket response, applied at the moment of the third ask rather than in a retrospective: the CSV export goes to Next with an accepted trade (it displaces the runbook polish), the retry cleanup goes to the kill list in `decisions.md` with the blast-radius reason, and the tile is absorbed because it is genuinely twenty minutes — logged anyway, since an unlogged absorption is the one that gets forgotten in the accumulation conversation.
|
|
71
|
+
|
|
72
|
+
That conversation happens with Priya at three receipts, with the dates on screen: "these are the four asks, here is the two days, here is what moved." Not a complaint — a decision she gets to make, with evidence, before the deadline makes it for her.
|
|
73
|
+
|
|
64
74
|
## Principles
|
|
65
75
|
|
|
66
76
|
- "Let me place it" is the phrase. Not "no," not "sure."
|
|
@@ -186,6 +186,16 @@ Adoption isn't a handoff-stage problem - it starts during build. Software that l
|
|
|
186
186
|
|
|
187
187
|
Before 100%: canary clean, business metric verified, pulse written into `delivery.md`. Also green: value bucket named, audit receipt dated, eval receipt **n/a or pass**, **intent vs diff clean** (no unresolved SPLIT/DROP). Missing any of those → not green. For enterprise-scale: scale-readiness gate passed before broad rollout.
|
|
188
188
|
|
|
189
|
+
## Worked example
|
|
190
|
+
|
|
191
|
+
Acme, shipping the failure-routing slice into a payments environment on a Thursday.
|
|
192
|
+
|
|
193
|
+
Readiness scoring catches two things the diff does not. The audit receipt is missing: the operating map says Marco's manual re-run is the fallback, and nobody has checked whether the new page fires *before* his morning run or after — if after, the alert changes nothing. That gets walked and cited before deploy. Second, the intent-vs-diff read shows the PR also touches the settlement retry that was deferred in build; it comes out.
|
|
194
|
+
|
|
195
|
+
Pre-blast challenge: "what does this break if it fires at 3am and nobody acks?" Answer: nothing breaks, but the rota is not yet agreed — so the deploy waits on a name, not on code. That is a one-day slip that prevents a fake green.
|
|
196
|
+
|
|
197
|
+
After deploy: `delivery.md` ship receipt with the audit cite, the kill test evidence, and the rollback line. Eval receipt: n/a, no AI in this path.
|
|
198
|
+
|
|
189
199
|
## Principles
|
|
190
200
|
|
|
191
201
|
- A deployment without a tested rollback is reckless.
|
|
@@ -45,6 +45,17 @@ In every engagement where an external FDE was brought in, an internal team was p
|
|
|
45
45
|
- **Use their language.** In every meeting. They hear their words coming back and they feel consulted, not replaced.
|
|
46
46
|
- **Make them look right.** Credit their prior work in your artifacts. They protect you if they feel respected; they wait for your mistake if they don't.
|
|
47
47
|
|
|
48
|
+
**6. Before a decision meeting: pre-wire, then pre-mortem.**
|
|
49
|
+
|
|
50
|
+
A recommendation that needs several people to say yes is not won in the room; it is won in the week before it. When the FDE is heading into a go/no-go, a budget ask, or anything that visibly costs someone territory:
|
|
51
|
+
|
|
52
|
+
- **Sort by position, not by seniority.** Firm supporter / firm opponent / **swing**. Effort goes almost entirely to swings - supporters need reinforcement, not persuasion, and a firm opponent is rarely moved by a louder version of the argument that already failed.
|
|
53
|
+
- **Name what each swing is protecting.** The objection voiced in a meeting is usually a proxy: headcount, budget, credibility, control, or the reporting line that gets messier. Write the underlying motivation next to the stated objection - they are different sentences.
|
|
54
|
+
- **Sequence the conversations.** Whoever makes the others easier to win goes first; whoever is reassured by seeing names already on board goes last. One-on-one for anyone who would lose face conceding in a group.
|
|
55
|
+
- **Pre-mortem the meeting.** "It's Thursday, the meeting went badly - who sank it, and with what sentence?" That sentence is the pre-wire you are missing. If the answer is a specific person's objection, their conversation happens *before* the room convenes, not in it.
|
|
56
|
+
|
|
57
|
+
Log the sequence and the pre-mortem sentence in `context.md` as the plan for the week - a pre-wire plan that lives only in the FDE's head is not a plan.
|
|
58
|
+
|
|
48
59
|
## Artifact
|
|
49
60
|
|
|
50
61
|
**`stakeholders.md`** - updated with evidence-dated signal changes:
|
|
@@ -61,6 +72,16 @@ Signal changes get a dated evidence note. A signal that moved without evidence l
|
|
|
61
72
|
|
|
62
73
|
One line per stakeholder who changed signal this week. If nobody changed: "Map stable - next check <date>." If a ghost appeared or a resistor went quiet: name it, recommend the move, and update `context.md` with the action.
|
|
63
74
|
|
|
75
|
+
## Worked example
|
|
76
|
+
|
|
77
|
+
Acme, week 6. Priya's replies have gone from same-day to two days, and a phase-2 go/no-go is scheduled for Thursday.
|
|
78
|
+
|
|
79
|
+
Two signals, not one feeling: response time doubled *and* a finance analyst nobody introduced started asking when the work completes. That combination is an invisible escalation — someone above Priya is asking, and the meeting is already happening without the FDE.
|
|
80
|
+
|
|
81
|
+
Positions: Priya is a supporter under pressure. Marco is a supporter who does not vote. Denise (finance) is the swing, and what she is protecting is not the budget line she cites — it is that her team's escalation started this and she has nothing to show her own director. Raj is a firm opponent on the rewrite question, and no amount of the same argument moves him.
|
|
82
|
+
|
|
83
|
+
Sequence: Denise one-on-one Tuesday with the incident numbers in her units, then Priya Wednesday, so Priya walks in already knowing finance is not going to object. Pre-mortem sentence: *"Denise says 'we still don't know if this actually caught anything'"* — which is precisely why Tuesday exists. `stakeholders.md` records `Priya | sponsor | green→amber | reply latency 1d → 2d, unintroduced analyst (Jul 3)`; `context.md` carries the sequence.
|
|
84
|
+
|
|
64
85
|
## Principles
|
|
65
86
|
|
|
66
87
|
- Signals are evidence-based, not feeling-based. "Seemed distant" doesn't move a signal; "stopped responding to three messages" does.
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
| **A — Answer** | What you recommend / what happens next week (≤3 bullets) | plan Now lane, delivery promised→measured |
|
|
17
17
|
|
|
18
18
|
Then add, still on the same page:
|
|
19
|
-
1. **Value this week** - from the value ledger: promised → measured (or "pending") with evidence citation.
|
|
19
|
+
1. **Value this week** - from the value ledger: promised → measured (or "pending") → **accepted by whom**, with evidence citation. A measured number nobody on the customer side has agreed to is written as `claimed`, and the Ask never rests on it - if the whole case for the next phase is a claimed number, the real ask this week is "who signs off that this is real?".
|
|
20
20
|
2. **Kill / defer reminder** - one line from the plan kill list so scope fights stay visible.
|
|
21
21
|
3. **Hostile Q prep** - three questions a skeptical sponsor will ask, with one-line answers from memory.
|
|
22
22
|
|
|
@@ -34,7 +34,7 @@ Append the draft to `delivery.md` under `## Status - <date>` using the SCQA head
|
|
|
34
34
|
**C:** ...
|
|
35
35
|
**Q:** ...
|
|
36
36
|
**A:** ...
|
|
37
|
-
**Value ledger:** promised … / measured … (evidence)
|
|
37
|
+
**Value ledger:** promised … / measured … / accepted by … (evidence) — or `claimed, unaccepted`
|
|
38
38
|
**Kill list reminder:** …
|
|
39
39
|
**Hostile Qs:** 1) … 2) … 3) …
|
|
40
40
|
```
|
|
@@ -43,6 +43,16 @@ Append the draft to `delivery.md` under `## Status - <date>` using the SCQA head
|
|
|
43
43
|
|
|
44
44
|
Walk the FDE through the Complication and the Ask - confirm the framing matches what the sponsor can hear right now (check `stakeholders.md` signal first: a red-signal sponsor gets a different opening than a green one).
|
|
45
45
|
|
|
46
|
+
## Worked example
|
|
47
|
+
|
|
48
|
+
Acme, week 3, Priya's Friday update.
|
|
49
|
+
|
|
50
|
+
**S:** failure routing is live; detection is 12 min against the 4h baseline in `success.md`. **C** leads with the bad news, not the win: the second incident was acked 40 minutes late because the rota has one name on it, and that name was on leave. **Q:** one ask — a second name on the rota by Wednesday. **A:** three bullets, top of the Now lane.
|
|
51
|
+
|
|
52
|
+
Value ledger line: `promised 4h → 15min / measured 12min over 2 incidents / accepted by — (Marco confirmed operationally, finance not yet)` → written as `claimed, unaccepted`, which is what makes the Ask honest rather than a victory lap.
|
|
53
|
+
|
|
54
|
+
Hostile Q prep, from memory not imagination: "why did we pay for alerting we already had?" → the receipt from `decisions.md` and the disabled-alerting finding in `reality.md`. Kill list reminder: the service rewrite is still deferred, accepted by Priya on Jun 12.
|
|
55
|
+
|
|
46
56
|
## Principles
|
|
47
57
|
|
|
48
58
|
- SCQA every time. Situation → Complication → Ask → Answer.
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
## Value ledger
|
|
6
6
|
|
|
7
|
-
| Date | Slice | Bucket | Promised | Measured | Evidence | Rollback |
|
|
8
|
-
|
|
9
|
-
| | | *(cost-save / risk-mitigation / revenue-uplift)* | *(what we said it would change)* | *(what actually changed, or pending)* | *(who/when/metric)* | |
|
|
7
|
+
| Date | Slice | Bucket | Promised | Measured | Accepted by | Evidence | Rollback |
|
|
8
|
+
|------|-------|--------|----------|----------|-------------|----------|----------|
|
|
9
|
+
| | | *(cost-save / risk-mitigation / revenue-uplift)* | *(what we said it would change)* | *(what actually changed, or pending)* | *(customer-side name + date, or it stays claimed)* | *(who/when/metric)* | |
|
|
10
10
|
|
|
11
11
|
## Ship receipts
|
|
12
12
|
|