fdeops 3.15.1 → 3.15.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.
Files changed (50) hide show
  1. package/AGENTS.md +1 -1
  2. package/README.md +116 -78
  3. package/adapters/AGENTS.md +2 -2
  4. package/adapters/GEMINI.md +2 -2
  5. package/adapters/README.md +1 -1
  6. package/adapters/copilot-instructions.md +2 -2
  7. package/adapters/cursor.fde.mdc +3 -3
  8. package/bin/check.js +58 -6
  9. package/bin/fde.js +16 -16
  10. package/bin/lib/memory.js +1 -1
  11. package/bin/lib/render.js +1 -1
  12. package/bin/lib/trust.js +1 -1
  13. package/mcp/README.md +2 -2
  14. package/mcp/fdeops-ingest/README.md +8 -8
  15. package/mcp/fdeops-ingest/package.json +1 -1
  16. package/mcp/fdeops-ingest/server.js +1 -1
  17. package/mcp/recipes/README.md +2 -2
  18. package/mcp/recipes/file.md +1 -1
  19. package/mcp/recipes/granola.md +5 -5
  20. package/mcp/recipes/notion.md +2 -2
  21. package/mcp/recipes/slack.md +5 -5
  22. package/package.json +1 -1
  23. package/plugin.json +1 -1
  24. package/skills/fde/SKILL.md +36 -23
  25. package/skills/fde/references/ai.md +8 -8
  26. package/skills/fde/references/assumption-audit.md +2 -2
  27. package/skills/fde/references/blast-radius.md +1 -1
  28. package/skills/fde/references/business-case.md +3 -3
  29. package/skills/fde/references/close.md +5 -5
  30. package/skills/fde/references/debrief.md +2 -2
  31. package/skills/fde/references/discover.md +7 -7
  32. package/skills/fde/references/eval-pack.md +6 -6
  33. package/skills/fde/references/handoff-engineering.md +2 -2
  34. package/skills/fde/references/incremental-build.md +20 -11
  35. package/skills/fde/references/ingest-connect.md +6 -6
  36. package/skills/fde/references/ingest.md +14 -14
  37. package/skills/fde/references/initiative-triage.md +6 -6
  38. package/skills/fde/references/land.md +8 -8
  39. package/skills/fde/references/multi-customer-ops.md +1 -1
  40. package/skills/fde/references/options-analysis.md +2 -2
  41. package/skills/fde/references/plan.md +6 -6
  42. package/skills/fde/references/red-team.md +2 -2
  43. package/skills/fde/references/review.md +7 -7
  44. package/skills/fde/references/scope-defense.md +3 -3
  45. package/skills/fde/references/ship.md +16 -16
  46. package/skills/fde/references/sketch.md +3 -3
  47. package/skills/fde/references/stakeholder-radar.md +4 -4
  48. package/skills/fde/references/status.md +8 -8
  49. package/skills/fde/references/trust-engineering.md +1 -1
  50. package/skills/fde/references/use-case-scoring.md +1 -1
package/AGENTS.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # AGENTS.md - working in the fdeops repository
2
2
 
3
- This repository **is** fdeops the engagement record for Forward Deployed Engineers. One `@fde` skill, the `fde` CLI for deterministic work, and per-customer memory in `.fde/` as a side effect of the work (you still confirm judgment).
3
+ This repository **is** fdeops - the engagement record for Forward Deployed Engineers. One `@fde` skill, the `fde` CLI for deterministic work, and per-customer memory in `.fde/` as a side effect of the work (you still confirm judgment).
4
4
 
5
5
  ## If you are helping use fdeops in an engagement
6
6
 
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Forward deployed engineering skills for AI coding agents.**
4
4
 
5
- Skills encode the workflows, quality gates, and judgment Forward Deployed Engineers use on someone else's site. Packaged so an AI coding agent follows them consistently and writes a dated record you can defend. The host agent still writes the TypeScript.
5
+ Skills encode the workflows, quality gates, and judgment Forward Deployed Engineers use on someone else's site. Packaged so an AI coding agent can run the embed end-to-end: discovery, POC, slice, on-site proof, eval, signed outcome. The workspace still compiles and commits. `@fde` does not leave.
6
6
 
7
7
  ```text
8
8
  LAND DISCOVER PLAN SHIP PROVE CLOSE
@@ -10,27 +10,34 @@ Skills encode the workflows, quality gates, and judgment Forward Deployed Engine
10
10
  │ Brief │ ───▶ │ Reality│ ───▶ │ Sequence│───▶ │ Live │ ───▶ │ Signed │ ───▶ │ They │
11
11
  │ Trust │ │ Terrain│ │ Align │ │ slice │ │ off │ │ run │
12
12
  └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘
13
- /brief /discover /plan /ship /got /close
13
+ /brief /discover /plan /ship /outcome /close
14
14
  ```
15
15
 
16
16
  ---
17
17
 
18
18
  ## Commands
19
19
 
20
- 6 slash commands that map to the engagement. Each one activates `@fde`.
20
+ Each command loads the same `@fde` skill. You never pick from 31 names.
21
21
 
22
22
  | What you're doing | Command | Key principle |
23
23
  |-------------------|---------|-----------|
24
- | Land the embed | `/brief` | Brief and trust before code |
24
+ | Land the embed | `/brief` | Who signs done |
25
25
  | Find the real problem | `/discover` | Brief is a hypothesis |
26
26
  | Plan the sequence | `/plan` | Backwards from done |
27
- | Ship a slice | `/ship` | Pre-flight, then live |
28
- | Prove what they got | `/got` | Promised measured accepted |
29
- | Close the embed | `/close` | They can run it without you |
27
+ | Ship a slice | `/ship` | Live with a rollback |
28
+ | Prove the outcome | `/outcome` | Promised, measured, accepted |
29
+ | Close the embed | `/close` | They run it without you |
30
30
 
31
- Also: `/debrief` (after a meeting) · `/prep` (walk-in) · `/quiet` (sponsor silent) · `/agreed` (scope dispute) · `/status` (Friday readout).
31
+ Four tells the map does not cover:
32
32
 
33
- Skills also activate automatically based on what you're doing naming a client, debriefing a meeting, or asking what was agreed triggers `@fde`. Ordinary TypeScript, unit tests, and git commits stay in the host agent.
33
+ | What you're doing | Command | Key principle |
34
+ |-------------------|---------|-----------|
35
+ | Sponsor went silent | `/quiet` | Process or trust |
36
+ | Scope dispute | `/agreed` | Dated receipts, or a gap |
37
+ | After a meeting | `/debrief` | Notes into the record |
38
+ | Walk-in / Friday | `/prep` `/status` | One page, then the ledger |
39
+
40
+ Skills also activate on English: naming a client, running a POC, slicing a feature, asking what was agreed. A throwaway one-liner in an unbound repo can skip `@fde`. A client slice cannot.
34
41
 
35
42
  ---
36
43
 
@@ -67,7 +74,7 @@ Hooks load where you left off. Slash commands match the map above.
67
74
  npx skills add suboss87/fdeops --skill fde
68
75
  ```
69
76
 
70
- Or `npx fdeops adapters .` [adapters/](adapters/README.md).
77
+ Or `npx fdeops adapters .`. See [adapters/](adapters/README.md).
71
78
 
72
79
  </details>
73
80
 
@@ -86,7 +93,7 @@ Fallback if the agent cannot bind:
86
93
  npx fdeops resume --init acme # ~/fde-engagements/acme + bind this checkout
87
94
  ```
88
95
 
89
- Requires Node.js >= 18. Override: `FDEOPS_ENGAGEMENT` [docs/install.md](docs/install.md). Try the loop: `npx fdeops demo`.
96
+ Requires Node.js >= 18. Override: `FDEOPS_ENGAGEMENT`. See [docs/install.md](docs/install.md). Try the loop: `npx fdeops demo`.
90
97
 
91
98
  </details>
92
99
 
@@ -94,7 +101,7 @@ Requires Node.js >= 18. Override: `FDEOPS_ENGAGEMENT` — [docs/install.md](docs
94
101
 
95
102
  ## All 31 Skills
96
103
 
97
- The commands above are the entry points. Under the hood, `@fde` activates these 31 skills each a structured workflow with steps, an artifact, and a checkpoint. You never pick one by name. Full detail: [docs/skills-reference.md](docs/skills-reference.md).
104
+ The commands above are the entry points. Under the hood, `@fde` activates these 31 skills, each a structured workflow with steps, an artifact, and a checkpoint. You never pick one by name. Full detail: [docs/skills-reference.md](docs/skills-reference.md).
98
105
 
99
106
  ### Land - Brief and trust
100
107
 
@@ -113,7 +120,7 @@ The commands above are the entry points. Under the hood, `@fde` activates these
113
120
  | [discover](skills/fde/references/discover.md) | Repo + workaround + the real problem | Brief feels wrong, shadow processes |
114
121
  | [assumption-audit](skills/fde/references/assumption-audit.md) | Untested assumptions by blast radius | Brief feels too neat |
115
122
  | [use-case-scoring](skills/fde/references/use-case-scoring.md) | Value × urgency × alignment / complexity | Everything is P0 |
116
- | [sketch](skills/fde/references/sketch.md) | Kill the killer assumption in a day | Need to de-risk a direction |
123
+ | [sketch](skills/fde/references/sketch.md) | Kill the killer assumption in a day | POC, spike, need to de-risk |
117
124
 
118
125
  ### Plan - Sequence the work
119
126
 
@@ -128,14 +135,14 @@ The commands above are the entry points. Under the hood, `@fde` activates these
128
135
 
129
136
  | Skill | What It Does | Use When |
130
137
  |--------|--------------|----------|
131
- | [incremental-build](skills/fde/references/incremental-build.md) | Vertical slices, visible every 2–3 days | Large feature on their codebase |
138
+ | [incremental-build](skills/fde/references/incremental-build.md) | Vertical slices, on-site proof | Building on their codebase |
132
139
  | [blast-radius](skills/fde/references/blast-radius.md) | Impact from contained → irreversible | Touching shared infrastructure |
133
140
  | [rescue](skills/fde/references/rescue.md) | Production fire or trust fire | Down, or they went quiet |
134
141
  | [ship](skills/fde/references/ship.md) | Intent vs diff, pre-flight, rollback | Going live |
135
142
  | [review](skills/fde/references/review.md) | Did we only build what we agreed | Before merge, scope creep |
136
143
  | [rollback-drill](skills/fde/references/rollback-drill.md) | Test the escape route before 2am | "We can always revert" |
137
144
 
138
- ### Prove - What they got
145
+ ### Prove - Outcome
139
146
 
140
147
  | Skill | What It Does | Use When |
141
148
  |--------|--------------|----------|
@@ -165,32 +172,31 @@ Optional pull: you add the source MCP; we **pull** on request. [mcp/recipes/](mc
165
172
 
166
173
  ## How Skills Work
167
174
 
168
- Every skill follows a consistent anatomy:
175
+ One skill. One reference file per situation. One folder per client.
169
176
 
170
177
  ```
171
- ┌─────────────────────────────────────────────┐
172
- @fde (one skill) │
173
- │ │
174
- ┌─ Frontmatter ─────────────────────────┐ │
175
- name: fde │ │
176
- │ │ description: Use when [client work] │ │
177
- └───────────────────────────────────────┘ │
178
-
179
- │ Commands load it. English loads it. │
180
- You confirm. Then .fde/ is written. │
181
- └─────────────────────────────────────────────┘
182
-
183
-
184
- references/<skill>.md fde CLI (local)
185
- one file, then stop dating, gates, redaction
178
+ /brief or "@fde this is Acme"
179
+
180
+
181
+ skills/fde/SKILL.md hosts load this one file
182
+ routes. you never pick a skill by name
183
+
184
+ references/land.md one workflow, then stop
185
+
186
+
187
+ fde CLI (local) dates, gates, redacts. no network
188
+ │ after you confirm
189
+
190
+ ~/fde-engagements/<client>/.fde/
186
191
  ```
187
192
 
188
- - **Process, not prose.** Skills are workflows with an artifact and a checkpoint, not tip sheets.
193
+ - **Process, not prose.** Each reference is a workflow with an artifact and a checkpoint, not a tip sheet.
194
+ - **Ground loop.** Name → characterise → prove where they live → log. The workspace compiles; `@fde` stays.
189
195
  - **You confirm.** Nothing is written until you say so.
190
- - **Progressive disclosure.** The `SKILL.md` is the entry point. One `references/*.md` loads when routed.
191
- - **Local CLI.** Writes, status, dated agreements. Zero model tokens. The AI coding agent runs it.
196
+ - **Progressive disclosure.** `SKILL.md` is the entry point. One `references/*.md` loads when routed.
197
+ - **Local CLI.** Writes and status cost zero model tokens. The AI coding agent runs it.
192
198
 
193
- The record lives at `~/fde-engagements/<client>/.fde/` — not inside any vendor. Change hosts, install `@fde` on the new one, bind if needed, keep talking.
199
+ Change hosts, install `@fde` on the new one, bind if needed, keep talking. The record is not inside any vendor.
194
200
 
195
201
  ---
196
202
 
@@ -198,41 +204,76 @@ The record lives at `~/fde-engagements/<client>/.fde/` — not inside any vendor
198
204
 
199
205
  ```
200
206
  fdeops/
201
- ├── skills/fde/ # the one skill
202
- │ ├── SKILL.md # router
203
- │ └── references/ # 31 skills + overlays
204
- ├── .claude/commands/ # slash commands (each loads @fde)
205
- ├── .claude-plugin/ # Claude Code marketplace
206
- ├── bin/ # local CLI — git + files, no network
207
- ├── hooks/ # session-start / session-stop / pre-compact
208
- ├── adapters/ # Cursor, Gemini, Copilot, Codex pointers
209
- ├── templates/.fde/ # memory files created on bind
210
- ├── examples/ # fictional walkthroughs
211
- ├── mcp/ # optional ingest + source recipes
212
- ├── evals/ # routing checks + CLI attack notes
213
- ├── media/ # recorded session (docs/USAGE.md)
214
- └── docs/ # usage, schema, install, methodology
207
+ ├── skills/fde/ # the one skill hosts load
208
+ │ ├── SKILL.md # router
209
+ │ └── references/ # 31 skills + overlays (you never pick)
210
+ ├── land.md # Land
211
+ ├── audit.md
212
+ ├── stakeholder-radar.md
213
+ ├── trust-engineering.md
214
+ ├── scope-defense.md
215
+ ├── discover.md # Discover
216
+ ├── assumption-audit.md
217
+ ├── use-case-scoring.md
218
+ ├── sketch.md
219
+ ├── plan.md # Plan
220
+ │ ├── business-case.md
221
+ │ ├── options-analysis.md
222
+ │ ├── initiative-triage.md
223
+ │ ├── incremental-build.md # Ship
224
+ │ ├── blast-radius.md
225
+ │ ├── rescue.md
226
+ │ ├── ship.md
227
+ │ ├── review.md
228
+ │ ├── rollback-drill.md
229
+ │ ├── status.md # Prove
230
+ │ ├── demo-prep.md
231
+ │ ├── debrief.md
232
+ │ ├── exec-narrative.md
233
+ │ ├── dashboard.md
234
+ │ ├── ingest.md
235
+ │ ├── ingest-connect.md
236
+ │ ├── close.md # Close
237
+ │ ├── handoff-engineering.md
238
+ │ ├── multi-customer-ops.md
239
+ │ ├── pattern-extract.md
240
+ │ ├── red-team.md
241
+ │ ├── ai.md # overlays (on signal)
242
+ │ ├── artifacts.md
243
+ │ ├── eval-pack.md
244
+ │ ├── fintech.md
245
+ │ ├── healthcare.md
246
+ │ └── gov.md
247
+ ├── .claude/commands/ # slash commands (each loads @fde)
248
+ │ ├── brief.md
249
+ │ ├── discover.md
250
+ │ ├── plan.md
251
+ │ ├── ship.md
252
+ │ ├── outcome.md
253
+ │ ├── close.md
254
+ │ ├── quiet.md
255
+ │ ├── agreed.md
256
+ │ ├── debrief.md
257
+ │ ├── prep.md
258
+ │ └── status.md
259
+ ├── .claude-plugin/ # Claude Code marketplace
260
+ ├── bin/ # local CLI: git + files, no network
261
+ ├── hooks/ # session-start / session-stop / pre-compact
262
+ ├── adapters/ # Cursor, Gemini, Copilot, Codex pointers
263
+ ├── templates/.fde/ # memory files created on bind
264
+ ├── examples/ # fictional walkthroughs
265
+ ├── mcp/ # optional ingest + source recipes
266
+ ├── evals/ # routing checks
267
+ └── docs/ # usage, schema, install
215
268
  ```
216
269
 
217
270
  ---
218
271
 
219
272
  ## Why FDEOps?
220
273
 
221
- ### 1. The brief is wrong
222
-
223
- The most common failure on an embed is building the portal they asked for. Ops has been running a spreadsheet for two years. `/brief` then `/discover` — who in their company would have to agree it worked?
224
-
225
- ### 2. They went quiet
274
+ AI coding agents are built for a repo, not for a client. They forget the sponsor, the promise, who can say yes, and whether anyone accepted the number. Monday morning they start from the ticket again.
226
275
 
227
- A sponsor who stops answering is not a Jira gap. It is a trust color. `/quiet` process vs trust, then a dated signal in the record.
228
-
229
- ### 3. When did we agree?
230
-
231
- Arguments from memory lose. `/agreed` searches dated receipts. No hit is a gap, not proof.
232
-
233
- ### 4. What did they get?
234
-
235
- A number only you agree with is claimed, not delivered. `/got` reads promised → measured → accepted out loud.
276
+ FDEOps is what you take on site. One `@fde` skill runs the embed from discovery to signed outcome: POC, slice, on-site proof, eval when a model judges, promised → measured → accepted. A local CLI dates every decision. `.fde/` is markdown on your laptop. You confirm; then it is on the record.
236
277
 
237
278
  ---
238
279
 
@@ -255,19 +296,15 @@ Schema: [docs/schema.md](docs/schema.md). Local HTML: `npx fdeops dashboard`.
255
296
 
256
297
  ## Who this is for
257
298
 
258
- | You are | What this is |
259
- |---------|----------------|
260
- | **Forward Deployed Engineer** | Client work that has to survive Monday morning |
261
- | **Consultant / contractor on site** | The engagement stops resetting every morning |
262
- | **Solutions architect** | Politics and architecture in the same record |
263
- | **Agency, 3–5 clients** | One `.fde/` each — they stop blurring |
264
- | **Fractional CTO on client work** | System of record for the embed, and the billable trail |
299
+ You embed with a customer and an AI coding agent. Take this on the ground. Discovery through signed outcome lives in `@fde`. One `.fde/` per client so they do not blur.
300
+
301
+ If you only write code in your own repo with no client record to defend, you do not need this kit.
265
302
 
266
303
  ---
267
304
 
268
305
  ## Your data stays yours
269
306
 
270
- Local only `git` + files, no network, no telemetry. Plain markdown. The model sees client code only when you point the AI coding agent at it. `<private>` is redacted from CLI, dashboard, and hooks. Nothing is written until you confirm. `~/fde-engagements` is in `$HOME`; iCloud/Dropbox is an NDA incident waiting.
307
+ Local only - `git` + files, no network, no telemetry. Plain markdown. The model sees client code only when you point the AI coding agent at it. `<private>` is redacted from CLI, dashboard, and hooks. Nothing is written until you confirm. `~/fde-engagements` is in `$HOME`; iCloud/Dropbox is an NDA incident waiting.
271
308
 
272
309
  [PRIVACY.md](PRIVACY.md) · [SECURITY.md](SECURITY.md)
273
310
 
@@ -275,20 +312,21 @@ Local only — `git` + files, no network, no telemetry. Plain markdown. The mode
275
312
 
276
313
  ## Principles
277
314
 
278
- - **The artifact is the memory** producing the work and recording it are one action
279
- - **Skills, not autonomy** the kit says what to check; judgment stays yours
280
- - **Brief is a hypothesis** discover before building the wrong thing
281
- - **Evidence on every claim** these files get defended in the room
282
- - **One customer, one folder** context never bleeds
315
+ - **The artifact is the memory** - producing the work and recording it are one action
316
+ - **Ground loop** - name the slice, characterise their code, prove it where they live, log the outcome
317
+ - **Skills, not autonomy** - the kit says what to check; judgment stays yours
318
+ - **Brief is a hypothesis** - discover before building the wrong thing
319
+ - **Evidence on every claim** - these files get defended in the room
320
+ - **One customer, one folder** - context never bleeds
283
321
 
284
322
  ---
285
323
 
286
324
  ## Contributing
287
325
 
288
- **[Subash Natarajan](https://www.linkedin.com/in/subashn/)**. [Issues](https://github.com/suboss87/fdeops/issues) · [CONTRIBUTING.md](CONTRIBUTING.md)
326
+ **[Subash Natarajan](https://www.linkedin.com/in/subashn/)**. [Issues](https://github.com/suboss87/fdeops/issues) · [Discussions](https://github.com/suboss87/fdeops/discussions) · [CONTRIBUTING.md](CONTRIBUTING.md) · [Code of Conduct](CODE_OF_CONDUCT.md)
289
327
 
290
328
  Skills should be **specific** (actionable steps), **verifiable** (an artifact in `.fde/`), and **minimal**. The `fde` CLI stays local-only.
291
329
 
292
330
  ## License
293
331
 
294
- MIT use these skills on client work.
332
+ MIT - use these skills on client work.
@@ -4,9 +4,9 @@ You are the AI coding agent for a **Forward Deployed Engineer (FDE)** - the huma
4
4
 
5
5
  ## Entry
6
6
 
7
- When the FDE types **`@fde`**, names a client, pastes meeting notes, asks what was agreed, or describes embed work (quiet sponsor, brief feels wrong, Friday update) load the skill. If `fde resume` says NO ENGAGEMENT: ask the client name once, then **you** run `fde resume --init <slug>`. Never tell them to type it.
7
+ When the FDE types **`@fde`**, names a client, pastes meeting notes, asks what was agreed, or describes embed work (quiet sponsor, brief feels wrong, Friday update) - load the skill. If `fde resume` says NO ENGAGEMENT: ask the client name once, then **you** run `fde resume --init <slug>`. Never tell them to type it.
8
8
 
9
- Do **not** load `@fde` for ordinary code edits, TypeScript, unit tests, refactors, or git commits.
9
+ Do **not** load `@fde` for a one-line typo in an unbound repo. On a bound client, stay on `@fde` for POC, slices, characterisation, on-site proof, eval, and go-live.
10
10
 
11
11
  - Skill (single source of truth): `~/.claude/skills/fde/SKILL.md`
12
12
  - **Never ask the FDE to pick a skill.** Read the situation, route silently, do the work.
@@ -4,9 +4,9 @@ Context for Gemini CLI when assisting a **Forward Deployed Engineer (FDE)** - th
4
4
 
5
5
  ## Entry
6
6
 
7
- When the FDE types **`@fde`**, names a client, pastes meeting notes, asks what was agreed, or describes embed work (quiet sponsor, brief feels wrong, Friday update) load the skill. If `fde resume` says NO ENGAGEMENT: ask the client name once, then **you** run `fde resume --init <slug>`. Never tell them to type it.
7
+ When the FDE types **`@fde`**, names a client, pastes meeting notes, asks what was agreed, or describes embed work (quiet sponsor, brief feels wrong, Friday update) - load the skill. If `fde resume` says NO ENGAGEMENT: ask the client name once, then **you** run `fde resume --init <slug>`. Never tell them to type it.
8
8
 
9
- Do **not** load `@fde` for ordinary code edits, TypeScript, unit tests, refactors, or git commits.
9
+ Do **not** load `@fde` for a one-line typo in an unbound repo. On a bound client, stay on `@fde` for POC, slices, characterisation, on-site proof, eval, and go-live.
10
10
 
11
11
  - Skill (single source of truth): `~/.claude/skills/fde/SKILL.md`
12
12
  - **Never ask the FDE to pick a skill.** Read the situation, route silently, do the work.
@@ -2,7 +2,7 @@
2
2
 
3
3
  **One brain, thin adapters.** fdeops has a single source of truth - the `@fde` skill at `skills/fde/SKILL.md` and the `fde` CLI. Each AI coding tool discovers it through a small pointer file in the place that tool already looks. No forked logic, no five copies to maintain - every adapter says the same thing: *route via `@fde`, read/write `.fde/` memory, talk like a peer, never touch what isn't yours.*
4
4
 
5
- **Switching tools:** the fieldbook does not live in the agent. It lives at `~/fde-engagements/<client>/.fde/`. Point a new tool at a bound workspace, drop adapters (or install the skill/plugin for that tool), and the same client record opens. Auto session hooks are Claude Codefirst; elsewhere load via `@fde` / `fde resume`. See [README § How it works](../README.md#how-it-works).
5
+ **Switching tools:** the fieldbook does not live in the agent. It lives at `~/fde-engagements/<client>/.fde/`. Point a new tool at a bound workspace, drop adapters (or install the skill/plugin for that tool), and the same client record opens. Auto session hooks are Claude Code-first; elsewhere load via `@fde` / `fde resume`. See [README § How it works](../README.md#how-it-works).
6
6
 
7
7
  ## What goes where
8
8
 
@@ -4,9 +4,9 @@ You are the AI coding agent for a **Forward Deployed Engineer (FDE)** - the huma
4
4
 
5
5
  ## Entry
6
6
 
7
- When the FDE types **`@fde`**, names a client, pastes meeting notes, asks what was agreed, or describes embed work (quiet sponsor, brief feels wrong, Friday update) load the skill. If `fde resume` says NO ENGAGEMENT: ask the client name once, then **you** run `fde resume --init <slug>`. Never tell them to type it.
7
+ When the FDE types **`@fde`**, names a client, pastes meeting notes, asks what was agreed, or describes embed work (quiet sponsor, brief feels wrong, Friday update) - load the skill. If `fde resume` says NO ENGAGEMENT: ask the client name once, then **you** run `fde resume --init <slug>`. Never tell them to type it.
8
8
 
9
- Do **not** load `@fde` for ordinary code edits, TypeScript, unit tests, refactors, or git commits.
9
+ Do **not** load `@fde` for a one-line typo in an unbound repo. On a bound client, stay on `@fde` for POC, slices, characterisation, on-site proof, eval, and go-live.
10
10
 
11
11
  - Skill (single source of truth): `~/.claude/skills/fde/SKILL.md`
12
12
  - **Never ask the FDE to pick a skill.** Read the situation, route silently, do the work.
@@ -9,9 +9,9 @@ You are the AI coding agent for a **Forward Deployed Engineer (FDE)** - the huma
9
9
 
10
10
  ## Entry
11
11
 
12
- When the FDE types **`@fde`**, names a client, pastes meeting notes, asks what was agreed, or describes embed work (quiet sponsor, brief feels wrong, Friday update) load `@fde`. If `fde resume` says NO ENGAGEMENT: ask the client name once, then **you** run `fde resume --init <slug>`. Never tell them to type it.
12
+ When the FDE types **`@fde`**, names a client, pastes meeting notes, asks what was agreed, or describes embed work (quiet sponsor, brief feels wrong, Friday update) - load `@fde`. If `fde resume` says NO ENGAGEMENT: ask the client name once, then **you** run `fde resume --init <slug>`. Never tell them to type it.
13
13
 
14
- Do **not** load `@fde` for ordinary code edits, unit tests, refactors, or git commits.
14
+ Do **not** load `@fde` for a one-line typo in an unbound repo. On a bound client, stay on `@fde` for POC, slices, characterisation, on-site proof, eval, and go-live.
15
15
 
16
16
  - Skill (single source of truth): `~/.claude/skills/fde/SKILL.md` (or the copy this install placed)
17
17
  - **Never ask the FDE to pick a skill.** Read the situation, route silently, do the work.
@@ -21,7 +21,7 @@ Do **not** load `@fde` for ordinary code edits, unit tests, refactors, or git co
21
21
 
22
22
  Read and write engagement files under the workspace's bound engagement: run `fde resume` to resolve it (binding created once with `fde resume --init <name>`; default `~/fde-engagements/<name>/.fde/`). `FDEOPS_ENGAGEMENT` (expand `~`) overrides when set. Use `./.fde/` only when the engagement approves it and it is gitignored.
23
23
 
24
- **On every session entry (before other work):** run `fde triage` (fallback `node ~/.claude/fdeops/fde.js triage`, then `fde resume`). Lead with that TRIAGE block trust, phase, open risks, next action, record owner/hash. Do not invent stakeholders or status.
24
+ **On every session entry (before other work):** run `fde triage` (fallback `node ~/.claude/fdeops/fde.js triage`, then `fde resume`). Lead with that TRIAGE block - trust, phase, open risks, next action, record owner/hash. Do not invent stakeholders or status.
25
25
 
26
26
  You run the CLI for deterministic work - `fde scan | log | debrief | prep | doctor | receipts | status | dashboard` - instead of improvising shell or handing commands to the human.
27
27
 
package/bin/check.js CHANGED
@@ -43,7 +43,7 @@ for (const f of requiredTemplates) {
43
43
 
44
44
  const deadMedia = ['demo.gif', 'demo.sh', 'demo.tape', 'terminal-demo.svg', 'fieldbook-dashboard.png', 'fieldbook-detail.png', 'fieldbook-walkthrough.gif']
45
45
  for (const name of deadMedia) {
46
- if (fs.existsSync(path.join(root, 'media', name))) fail(`dead media/${name} must not ship the recorded session is session.gif`)
46
+ if (fs.existsSync(path.join(root, 'media', name))) fail(`dead media/${name} must not ship - the recorded session is session.gif`)
47
47
  }
48
48
  ok('no staged mock media')
49
49
 
@@ -57,7 +57,7 @@ for (const dir of fs.readdirSync(path.join(root, 'skills'))) {
57
57
  ok('skills structure')
58
58
 
59
59
  if (fs.existsSync(path.join(root, 'skills', 'fde', 'archive'))) {
60
- fail('skills/fde/archive must not exist unrouted methods are dead code')
60
+ fail('skills/fde/archive must not exist - unrouted methods are dead code')
61
61
  } else ok('no archived skill dump')
62
62
 
63
63
  // v3: one skill + phase references (progressive disclosure)
@@ -201,7 +201,7 @@ ok(`router dispatch (${mentioned.length} reference targets verified) + memory co
201
201
 
202
202
  const refDir = path.join(root, 'skills', 'fde', 'references')
203
203
  const extra = fs.readdirSync(refDir).filter(f => f.endsWith('.md') && !mentioned.includes(f))
204
- if (extra.length) fail(`unrouted reference file(s) dead method: ${extra.join(', ')}`)
204
+ if (extra.length) fail(`unrouted reference file(s) - dead method: ${extra.join(', ')}`)
205
205
  else ok('no unrouted reference files')
206
206
  }
207
207
 
@@ -222,7 +222,7 @@ if (read('package.json').includes('postinstall')) {
222
222
 
223
223
  const readme = read('README.md')
224
224
  if (/session\.gif|demo\.gif|<img /i.test(readme)) {
225
- fail('README must not embed images front door is text; the recording lives in docs/USAGE.md')
225
+ fail('README must not embed images - front door is text; the recording lives in docs/USAGE.md')
226
226
  } else ok('README is text (no gif)')
227
227
 
228
228
  const usage = read('docs/USAGE.md')
@@ -262,9 +262,10 @@ if (!readme.includes('AI coding agent')) {
262
262
  }
263
263
  ok('README clarity sections')
264
264
 
265
- for (const cmd of ['/brief', '/discover', '/plan', '/ship', '/got', '/close', '/debrief', '/prep', '/quiet', '/agreed', '/status']) {
265
+ for (const cmd of ['/brief', '/discover', '/plan', '/ship', '/outcome', '/close', '/debrief', '/prep', '/quiet', '/agreed', '/status']) {
266
266
  if (!readme.includes(cmd)) fail(`README must document slash command ${cmd}`)
267
267
  }
268
+ if (/(^|[^\w/])\/got\b/.test(readme)) fail('README must use /outcome, not /got')
268
269
  ok('README slash commands documented')
269
270
 
270
271
  // Front-door map is the embed left-to-right (LAND → CLOSE), not a pile of situations.
@@ -535,7 +536,7 @@ if (pkg.version !== plugin.version) {
535
536
  if (plugin.commands !== './.claude/commands' || plugin.skills !== './skills') {
536
537
  fail('.claude-plugin/plugin.json must declare skills and commands')
537
538
  } else {
538
- for (const cmd of ['brief', 'discover', 'plan', 'ship', 'got', 'close', 'debrief', 'prep', 'quiet', 'agreed', 'status']) {
539
+ for (const cmd of ['brief', 'discover', 'plan', 'ship', 'outcome', 'close', 'debrief', 'prep', 'quiet', 'agreed', 'status']) {
539
540
  const rel = `.claude/commands/${cmd}.md`
540
541
  if (!fs.existsSync(path.join(root, rel))) fail(`${rel} missing`)
541
542
  else if (!read(rel).includes('@fde')) fail(`${rel} must load @fde`)
@@ -647,4 +648,55 @@ if (!fs.existsSync(path.join(root, '.github', 'ISSUE_TEMPLATE', 'bug_report.yml'
647
648
  fail('GitHub issue template missing')
648
649
  } else ok('issue templates')
649
650
 
651
+ function findUnicodeDashes(dir, acc = []) {
652
+ for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
653
+ if (e.name === '.git' || e.name === 'node_modules' || e.name === '.agents') continue
654
+ const p = path.join(dir, e.name)
655
+ if (e.isDirectory()) findUnicodeDashes(p, acc)
656
+ else if (e.name === 'session.cast' || e.name === 'session.gif') continue
657
+ else {
658
+ let t
659
+ try { t = fs.readFileSync(p, 'utf8') } catch { continue }
660
+ if (t.includes('\u2014') || t.includes('\u2013')) acc.push(path.relative(root, p))
661
+ }
662
+ }
663
+ return acc
664
+ }
665
+ {
666
+ const dashed = findUnicodeDashes(root)
667
+ if (dashed.length) fail(`em/en dashes must be ASCII hyphen: ${dashed.join(', ')}`)
668
+ else ok('no em/en dashes')
669
+ }
670
+
671
+ if (!fs.existsSync(path.join(root, 'CODE_OF_CONDUCT.md'))) {
672
+ fail('CODE_OF_CONDUCT.md missing - GitHub community profile needs it')
673
+ } else ok('CODE_OF_CONDUCT.md')
674
+
675
+ if (!fs.existsSync(path.join(root, '.github', 'PULL_REQUEST_TEMPLATE.md'))) {
676
+ fail('.github/PULL_REQUEST_TEMPLATE.md missing - GitHub community profile needs it')
677
+ } else ok('pull request template')
678
+
679
+ if (!fs.existsSync(path.join(root, '.github', 'ISSUE_TEMPLATE', 'question.md'))) {
680
+ fail('.github/ISSUE_TEMPLATE/question.md missing - community profile needs a markdown template with name/about')
681
+ } else {
682
+ const q = read('.github/ISSUE_TEMPLATE/question.md')
683
+ if (!/^---[\s\S]*\nname:/m.test(q) || !/^---[\s\S]*\nabout:/m.test(q)) {
684
+ fail('question.md must have YAML name: and about: so GitHub ticks issue templates')
685
+ } else ok('markdown issue template (name + about)')
686
+ }
687
+
688
+ {
689
+ const mktPath = path.join(root, '.claude-plugin', 'marketplace.json')
690
+ if (!fs.existsSync(mktPath)) fail('.claude-plugin/marketplace.json missing - /plugin marketplace add needs it')
691
+ else {
692
+ const mkt = JSON.parse(read('.claude-plugin/marketplace.json'))
693
+ const plug = (mkt.plugins || [])[0]
694
+ if (mkt.name !== 'fdeops' || !plug || plug.source !== './') {
695
+ fail('marketplace.json must name fdeops and list source ./')
696
+ } else if (!mkt.description && !(mkt.metadata && mkt.metadata.description)) {
697
+ fail('marketplace.json needs a description for the plugin directory')
698
+ } else ok('claude marketplace.json')
699
+ }
700
+ }
701
+
650
702
  process.exit(failed)