fdeops 3.10.0 → 3.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
8
8
  [![Node](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org)
9
9
 
10
- **Memory + methodology + skills, in one kit.** Skill packs - BMAD, Spec-Kit, [mattpocock/skills](https://github.com/mattpocock/skills) - teach your AI agent how to *build*. None of them remember who the client is, what you promised them, or who agreed it was delivered. FDEOps adds the missing layer: a private fieldbook per engagement (`.fde/`), a field methodology (land → close), and one `@fde` skill that routes it all.
10
+ **Memory + methodology + skills, in one kit.** Skill packs - BMAD, Spec-Kit, [mattpocock/skills](https://github.com/mattpocock/skills) - teach your AI coding agent how to *build*. None of them remember who the client is, what you promised them, or who agreed it was delivered. FDEOps adds the missing layer: a private fieldbook per engagement (`.fde/`), a field methodology (land → close), and one `@fde` skill that routes it all.
11
11
 
12
12
  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).
13
13
 
@@ -19,87 +19,82 @@ Built for Forward Deployed Engineers, and anyone embedded in client work: consul
19
19
  written as a side effect of the work
20
20
  ```
21
21
 
22
- **You talk in plain language with `@fde`.** The agent (and an optional CLI) handles the boring memory work. You still confirm anything that goes into the record.
22
+ Talk in plain language with `@fde`. The AI coding agent runs the plumbing. You confirm anything that enters the record.
23
23
 
24
24
  ---
25
25
 
26
26
  ## The week
27
27
 
28
- Day to day you only need `@fde` and normal English. No command cheat sheet.
28
+ `@fde` plus English. No cheat sheet.
29
29
 
30
30
  | When | What you say | What you get |
31
31
  |------|--------------|--------------|
32
- | **Start of week** | Open your AI coding agent (nothing to paste) | It already knows where you left off - trust, phase, what's next |
33
- | **After a meeting** | `@fde` debrief these notes *(paste or attach them)* | Proposed updates to the record - you review, then confirm |
34
- | **Pull from tools** | `@fde` connect Granola *(once)* · then `@fde` pull today's Acme transcript | Wire any source MCP you choose; FDEOps stages proposes you confirm. Recipes: [mcp/recipes/](mcp/recipes/) |
35
- | **Before a stakeholder meeting** | `@fde` prep me for tomorrow's meeting with the sponsor | A short brief from what you already logged - not a blank chat |
36
- | **Someone disputes scope** | `@fde` when did we agree to drop that feature? | Dated answers from the record (or a clear gap if nothing was logged) |
37
- | **End of week** | `@fde` draft the sponsor update from the record | Status grounded in what actually happened |
32
+ | **Start of week** | `@fde` or just open Claude Code | Fieldbook on disk either way. **Claude Code** injects trust, phase, next before you type. **Cursor / Codex / others:** say `@fde` or `resume` — nothing auto-loads. |
33
+ | **After a meeting** | `@fde` debrief these notes *(paste or attach)* | Proposed updates. You review, then confirm. |
34
+ | **Optional: pull** | `@fde` connect Granola *(once)* · `@fde` pull today's Acme transcript | You add that source MCP. We **pull** on request no push, no sync. [mcp/recipes/](mcp/recipes/) |
35
+ | **Before a stakeholder meeting** | `@fde` prep me for tomorrow with the sponsor | Brief from what you already logged. |
36
+ | **Scope dispute** | `@fde` when did we agree to drop that? | Dated answers, or a clear gap. |
37
+ | **End of week** | `@fde` draft the sponsor update from the record | Status grounded in what happened. |
38
38
 
39
- Same client folder every time (`~/fde-engagements/<client>/.fde/`). Your AI coding agent reads it on every session.
39
+ Same folder every time: `~/fde-engagements/<client>/.fde/`.
40
40
 
41
41
  ---
42
42
 
43
- ## See it in 60 seconds (no client, no install)
43
+ ## See it
44
44
 
45
45
  ```bash
46
46
  npx fdeops demo
47
47
  ```
48
48
 
49
- Walks one fake engagement end to end with the **real** commands: messy kickoff notes → proposed updates → you confirm → cold session reload → meeting prep → dated receipts → the fieldbook page. Nothing of yours is read, nothing leaves the machine, and it lives in a throwaway `~/fde-engagements/.demo/` that never appears in your portfolio. Remove it with `npx fdeops demo --clean`.
49
+ Real commands on a fake client: messy notes → you confirm → cold reload → prep → receipts → fieldbook page. Nothing of yours is read. Lives in `~/fde-engagements/.demo/`. Remove with `npx fdeops demo --clean`.
50
50
 
51
- Or watch it first. One real session below - day 1 kickoff notes, the next morning's cold start, and "when did we agree to that?" six weeks later. Every line is the CLI's own output; only the typing pace is staged, and you can re-record it yourself with [`media/record-session.sh`](media/record-session.sh):
51
+ One recorded session kickoff notes, next morning, when did we agree?” weeks later. CLI output; typing pace is staged. Re-record: [`media/record-session.sh`](media/record-session.sh).
52
52
 
53
53
  <p align="center"><img alt="A real fdeops session: messy kickoff notes routed into dated memory after you confirm, then a cold session that already knows the client, a grounded sponsor-meeting brief, and dated receipts" src="media/session.gif" width="900" /></p>
54
54
 
55
- Note the two things a chat window cannot do: **nothing is written until you confirm the routing**, and the `<private>` block in those notes lands sealed on disk as `(private - redacted)` - it never appears in `resume`, `prep`, `receipts`, or the dashboard.
55
+ Two things a chat window cannot do: **nothing is written until you confirm**, and `<private>` lands sealed as `(private - redacted)` never in `resume`, `prep`, `receipts`, or the dashboard.
56
56
 
57
57
  ---
58
58
 
59
59
  ## Quickstart
60
60
 
61
- **1. Install.** Claude Code gets session hooks (context loads before you type); everywhere else the same fieldbook loads when you ask.
61
+ **1. Install.** Claude Code: session hooks (context before you type). Everywhere else: the same fieldbook, loaded when you ask.
62
62
 
63
63
  ```text
64
- /plugin marketplace add suboss87/fdeops # Claude Code
64
+ /plugin marketplace add suboss87/fdeops
65
65
  /plugin install fdeops@fdeops
66
66
  ```
67
67
 
68
68
  ```bash
69
- npx skills add suboss87/fdeops # Cursor, Codex, and skills-compatible agents
69
+ npx skills add suboss87/fdeops # Cursor, Codex, skills-compatible hosts
70
70
  ```
71
71
 
72
- **2. Bind once** - inside the client workspace (setup only; not a daily habit):
72
+ **2. Bind once** in the client workspace:
73
73
 
74
74
  ```bash
75
- npx fdeops resume --init garvey # creates ~/fde-engagements/garvey engagement + binds workspace
75
+ npx fdeops resume --init garvey # ~/fde-engagements/garvey + bind this checkout
76
+ npx fdeops resume # where we are
76
77
  ```
77
78
 
78
- **Check it worked:**
79
-
80
- ```bash
81
- npx fdeops resume # prints a short "where we are" for this client
82
- ```
83
-
84
- **3. Work** - talk normally:
79
+ **3. Work**
85
80
 
86
81
  ```text
87
- @fde I just got the brief. New client, payments platform, they want it live before their Q3 audit.
82
+ @fde New client. Payments platform. They want it live before the Q3 audit.
88
83
  ```
89
84
 
90
- `@fde` routes and updates the fieldbook - you confirm judgment. Full workflow: [docs/USAGE.md](docs/USAGE.md).
85
+ `@fde` routes and drafts; you confirm judgment. Workflow: [docs/USAGE.md](docs/USAGE.md).
91
86
 
92
- **It's working if** `npx fdeops resume` prints this client's phase, trust signal, and next action - and tomorrow's session starts from that instead of a blank chat.
87
+ Working: `npx fdeops resume` prints this client's phase, trust, and next action. Tomorrow that file is still there. Auto-load at session start is Claude Code; elsewhere you invoke `@fde`.
93
88
 
94
89
  <details>
95
- <summary><strong>Other install paths</strong> · scan · env</summary>
90
+ <summary>Other install paths · scan · env</summary>
96
91
 
97
- - **Cursor / Codex / Copilot / Gemini CLI:** `npx fdeops adapters .` - [adapters/](adapters/README.md)
98
- - **Local LLMs (Ollama, LM Studio, llama.cpp):** load `skills/fde/SKILL.md` as the system prompt - [guide](adapters/LOCAL-LLM.md)
99
- - **Manual / air-gapped:** `git clone https://github.com/suboss87/fdeops.git && cd fdeops && node bin/install.js`
100
- - **Try without install:** `npx fdeops demo` - the whole loop on a fake client · `npx fdeops scan` - day-1 recon of this repo (heuristic leads, not findings)
101
- - **Requires:** [Node.js](https://nodejs.org) >= 18 for the CLI and adapters
102
- - **Advanced:** `FDEOPS_ENGAGEMENT` overrides the workspace registry. Full matrix: [docs/install.md](docs/install.md)
92
+ - **Adapters:** `npx fdeops adapters .` [adapters/](adapters/README.md)
93
+ - **Local LLMs:** load `skills/fde/SKILL.md` [guide](adapters/LOCAL-LLM.md)
94
+ - **Air-gapped:** `git clone https://github.com/suboss87/fdeops.git && cd fdeops && node bin/install.js`
95
+ - **No install:** `npx fdeops demo` · `npx fdeops scan` (heuristic recon, not findings)
96
+ - **Requires:** Node.js >= 18
97
+ - **Override:** `FDEOPS_ENGAGEMENT` [docs/install.md](docs/install.md)
103
98
 
104
99
  </details>
105
100
 
@@ -107,38 +102,26 @@ npx fdeops resume # prints a short "where we are" for this clien
107
102
 
108
103
  ## How it works
109
104
 
110
- - **You** describe the situation with `@fde` (or plain language once the skill is loaded)
111
- - **Session start / end** - small hooks load where you left off and capture what changed (no re-paste)
112
- - **Local CLI** - memory writes, search, and status with no model tokens; the agent runs it. You do not need to learn it for daily use ([docs/USAGE.md](docs/USAGE.md))
113
- - **Pluggable pull (ingest)** - FDEOps is the **sink**, not a connector pack. You add any source MCP (Granola, Notion, Drive, …) in Cursor/Claude; say `@fde connect …` for a guided config + recipe, then pull in plain language. Raw text → `.inbox/` → propose → you confirm → `.fde/`. No ambient sync; nothing unreviewed enters the fieldbook. See [mcp/recipes/](mcp/recipes/).
114
-
115
- fdeops complements repo memory: CLAUDE.md holds how the *code* works; the fieldbook holds how the *client engagement* works.
116
-
117
- ### Switch coding agents anytime
118
-
119
- The fieldbook lives on disk at `~/fde-engagements/<client>/.fde/` - not inside Claude, Cursor, or any other tool. Change AI coding agents and the **same client record** is still there.
105
+ - **You** describe the situation with `@fde` (or plain language once the skill is loaded).
106
+ - **Hooks (Claude Code)** load where you left off and snapshot on the way out. Other hosts: same CLI and files; you call `@fde` / `resume`.
107
+ - **Local CLI** writes, receipts, status. Zero model tokens. The AI coding agent runs it; you do not live in the CLI. [docs/USAGE.md](docs/USAGE.md)
108
+ - **Pull (optional)** FDEOps is the sink. Paste is the daily path. A source MCP you add (Granola, Slack, Notion, …) can fetch text; `@fde connect …` walks config. No push, no sync, no tokens in `.fde/`. [mcp/recipes/](mcp/recipes/)
120
109
 
121
- On the new tool:
122
-
123
- 1. Install `@fde` for that tool (plugin, `npx skills add suboss87/fdeops`, or `npx fdeops adapters .` - see [adapters/](adapters/README.md))
124
- 2. Open a workspace already bound with `npx fdeops resume --init <client>` (or bind once if this checkout is new)
125
- 3. Talk with `@fde` or run `npx fdeops resume`
126
-
127
- Same fieldbook. **Claude Code** gets the fullest ride (session start/stop hooks). Elsewhere the memory and CLI are the same; context usually loads when you ask `@fde` / `resume`, not automatically. Details: [docs/install.md](docs/install.md).
110
+ `CLAUDE.md` is how the *code* works. The fieldbook is how the *engagement* works. 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.
128
111
 
129
112
  <details>
130
- <summary><strong>Phase verbs</strong> (land → close)</summary>
113
+ <summary>Phase verbs (land → close)</summary>
131
114
 
132
115
  | Verb | When |
133
116
  |------|------|
134
- | **land** | First days at a new client - interrogate the brief, map stakeholders, define success |
135
- | **discover** | The brief feels wrong - find the real problem, with evidence from the repo |
136
- | **plan** | Scope agreed - sequence it backwards from success, in PR-sized slices |
137
- | **build** | Ready to write code - declare blast radius, log deliveries as you ship |
138
- | **ship** | Going to production - pre-flight, canary, tested rollback |
139
- | **close** | Engagement ending - handoff doc, retrospective, receipts that survive you |
117
+ | **land** | First days brief, stakeholders, success |
118
+ | **discover** | The brief is wrong evidence from the repo |
119
+ | **plan** | Sequence backwards from done, PR-sized |
120
+ | **build** | Blast radius, log what shipped |
121
+ | **ship** | Pre-flight, canary, rollback |
122
+ | **close** | Handoff, retro, receipts that survive you |
140
123
 
141
- Overlays for regulated domains (AI, fintech, healthcare, government) activate on signal. Full matrix: [docs/skills.md](docs/skills.md).
124
+ Overlays (AI, fintech, healthcare, gov) fire on signal. [docs/skills.md](docs/skills.md)
142
125
 
143
126
  </details>
144
127
 
@@ -146,43 +129,46 @@ Overlays for regulated domains (AI, fintech, healthcare, government) activate on
146
129
 
147
130
  ## The field methods
148
131
 
149
- You never pick one - you describe the situation and `@fde` routes. They are listed here because the methodology is the product, and it should be readable before you install anything. **37 methods across 6 domains**, each one a method (the thinking, the artifact it drafts, the checkpoint with you), not advice:
132
+ You never pick one. You describe the situation; `@fde` routes. **37 methods**, six domains each a method (thinking, artifact, checkpoint), not a tip sheet. [docs/skills.md](docs/skills.md) · [docs/skills-reference.md](docs/skills-reference.md)
133
+
134
+ <details>
135
+ <summary>All 37 methods</summary>
150
136
 
151
137
  | Domain | Methods |
152
138
  |--------|---------|
153
- | **1. Embed & Trust** - first days, access, credibility | [land](skills/fde/references/land.md) · [audit](skills/fde/references/audit.md) · [stakeholder-radar](skills/fde/references/stakeholder-radar.md) · [trust-engineering](skills/fde/references/trust-engineering.md) · [scope-defense](skills/fde/references/scope-defense.md) |
154
- | **2. Discover & Diagnose** - find the real problem | [discover](skills/fde/references/discover.md) · [assumption-audit](skills/fde/references/assumption-audit.md) · [use-case-scoring](skills/fde/references/use-case-scoring.md) · [sketch](skills/fde/references/sketch.md) |
155
- | **3. Plan & Align** - sequence it, sell it | [plan](skills/fde/references/plan.md) · [business-case](skills/fde/references/business-case.md) · [options-analysis](skills/fde/references/options-analysis.md) · [initiative-triage](skills/fde/references/initiative-triage.md) |
156
- | **4. Build & Guard** - the work, and not breaking their business | [build](skills/fde/references/build.md) · [incremental-build](skills/fde/references/incremental-build.md) · [test-on-legacy](skills/fde/references/test-on-legacy.md) · [blast-radius](skills/fde/references/blast-radius.md) · [debug](skills/fde/references/debug.md) · [rescue](skills/fde/references/rescue.md) · [security-audit](skills/fde/references/security-audit.md) · [observability](skills/fde/references/observability.md) |
157
- | **5. Ship & Verify** - production, with a way back | [ship](skills/fde/references/ship.md) · [review](skills/fde/references/review.md) · [rollback-drill](skills/fde/references/rollback-drill.md) · [qa-live](skills/fde/references/qa-live.md) |
158
- | **6. Operate & Close** - the part that decides renewals | [status](skills/fde/references/status.md) · [demo-prep](skills/fde/references/demo-prep.md) · [debrief](skills/fde/references/debrief.md) · [exec-narrative](skills/fde/references/exec-narrative.md) · [dashboard](skills/fde/references/dashboard.md) · [multi-customer-ops](skills/fde/references/multi-customer-ops.md) · [close](skills/fde/references/close.md) · [handoff-engineering](skills/fde/references/handoff-engineering.md) · [pattern-extract](skills/fde/references/pattern-extract.md) · [red-team](skills/fde/references/red-team.md) · [ingest](skills/fde/references/ingest.md) · [ingest-connect](skills/fde/references/ingest-connect.md) |
139
+ | **1. Embed & Trust** | [land](skills/fde/references/land.md) · [audit](skills/fde/references/audit.md) · [stakeholder-radar](skills/fde/references/stakeholder-radar.md) · [trust-engineering](skills/fde/references/trust-engineering.md) · [scope-defense](skills/fde/references/scope-defense.md) |
140
+ | **2. Discover & Diagnose** | [discover](skills/fde/references/discover.md) · [assumption-audit](skills/fde/references/assumption-audit.md) · [use-case-scoring](skills/fde/references/use-case-scoring.md) · [sketch](skills/fde/references/sketch.md) |
141
+ | **3. Plan & Align** | [plan](skills/fde/references/plan.md) · [business-case](skills/fde/references/business-case.md) · [options-analysis](skills/fde/references/options-analysis.md) · [initiative-triage](skills/fde/references/initiative-triage.md) |
142
+ | **4. Build & Guard** | [build](skills/fde/references/build.md) · [incremental-build](skills/fde/references/incremental-build.md) · [test-on-legacy](skills/fde/references/test-on-legacy.md) · [blast-radius](skills/fde/references/blast-radius.md) · [debug](skills/fde/references/debug.md) · [rescue](skills/fde/references/rescue.md) · [security-audit](skills/fde/references/security-audit.md) · [observability](skills/fde/references/observability.md) |
143
+ | **5. Ship & Verify** | [ship](skills/fde/references/ship.md) · [review](skills/fde/references/review.md) · [rollback-drill](skills/fde/references/rollback-drill.md) · [qa-live](skills/fde/references/qa-live.md) |
144
+ | **6. Operate & Close** | [status](skills/fde/references/status.md) · [demo-prep](skills/fde/references/demo-prep.md) · [debrief](skills/fde/references/debrief.md) · [exec-narrative](skills/fde/references/exec-narrative.md) · [dashboard](skills/fde/references/dashboard.md) · [multi-customer-ops](skills/fde/references/multi-customer-ops.md) · [close](skills/fde/references/close.md) · [handoff-engineering](skills/fde/references/handoff-engineering.md) · [pattern-extract](skills/fde/references/pattern-extract.md) · [red-team](skills/fde/references/red-team.md) · [ingest](skills/fde/references/ingest.md) · [ingest-connect](skills/fde/references/ingest-connect.md) |
159
145
 
160
- Plus five overlays that activate on signal rather than being chosen - [ai](skills/fde/references/ai.md) · [artifacts](skills/fde/references/artifacts.md) · [fintech](skills/fde/references/fintech.md) · [healthcare](skills/fde/references/healthcare.md) · [gov](skills/fde/references/gov.md) - which add the checks that domain demands to whatever method is already running.
146
+ Overlays: [ai](skills/fde/references/ai.md) · [artifacts](skills/fde/references/artifacts.md) · [fintech](skills/fde/references/fintech.md) · [healthcare](skills/fde/references/healthcare.md) · [gov](skills/fde/references/gov.md)
161
147
 
162
- Every method, with the exact phrases that route to it: **[docs/skills-reference.md](docs/skills-reference.md)**.
148
+ </details>
163
149
 
164
150
  ---
165
151
 
166
152
  ## Engagement memory (`.fde/`)
167
153
 
168
- The **fieldbook** is the system of record for the embed - one folder per client, plain markdown you can read, grep, and take with you:
154
+ One folder per client. Plain markdown. Grep it, copy it, defend it.
169
155
 
170
156
  | File | Holds |
171
157
  |------|-------|
172
- | `context.md` | Where you are - loaded first every session |
173
- | `brief.md` / `success.md` | What they asked for; what "done" means and who signs it off |
174
- | `reality.md` / `terrain.md` | The real problem; the codebase map |
175
- | `stakeholders.md` | Champions, resistance, `[signal:green\|amber\|red]` trust tokens |
158
+ | `context.md` | Where you are |
159
+ | `brief.md` / `success.md` | What they asked; what done is and who signs |
160
+ | `reality.md` / `terrain.md` | The real problem; the map |
161
+ | `stakeholders.md` | `[signal:green\|amber\|red]` |
176
162
  | `trust-profile.md` | Sacred data, AI policy, approval chain |
177
- | `decisions.md` / `risks.md` / `delivery.md` | Choices with dates; live risk register; what shipped and its rollback |
163
+ | `decisions.md` / `risks.md` / `delivery.md` | Dated choices; live risks; what shipped and how it rolls back |
178
164
 
179
- Every entry is dated and sourced, so you can defend it in front of skeptical stakeholders. Schema: [docs/schema.md](docs/schema.md).
165
+ Schema: [docs/schema.md](docs/schema.md).
180
166
 
181
167
  ---
182
168
 
183
169
  ## Fieldbook UI
184
170
 
185
- Open the system of record in a browser - trust, phase, next action, and the full record in one local page. Ask `@fde` for the dashboard, or run `npx fdeops dashboard` (current engagement by default; `--all` for the portfolio).
171
+ Local HTML: trust, phase, next, the record. `@fde` dashboard, or `npx fdeops dashboard` (`--all` for the portfolio).
186
172
 
187
173
  <p align="center"><img width="1336" height="624" alt="fdeops Fieldbook in the browser" src="https://github.com/user-attachments/assets/5683614c-7730-4a3a-860d-185053a377eb" /></p>
188
174
 
@@ -190,54 +176,50 @@ Open the system of record in a browser - trust, phase, next action, and the full
190
176
 
191
177
  ## Who this is for
192
178
 
193
- | You are... | What fdeops does for you |
194
- |----------|-------------------|
195
- | **Forward Deployed Engineer** | The role this was built for - the full lifecycle, first meeting to final handoff |
196
- | **Consultant or contractor at a client site** | Remembers the engagement so you stop re-explaining it |
197
- | **Solutions architect / engineer** | Methods for the politics as well as the architecture |
198
- | **Agency developer running 3-5 clients** | One `.fde/` per client - details stop blurring |
199
- | **Fractional CTO doing client work** | The fieldbook is your system of record for the embed - and your audit trail for billable work |
179
+ | You are | What this is |
180
+ |---------|----------------|
181
+ | **Forward Deployed Engineer** | The job this was built for first meeting through handoff |
182
+ | **Consultant / contractor on site** | The engagement stops resetting every morning |
183
+ | **Solutions architect** | Politics and architecture in the same record |
184
+ | **Agency, 35 clients** | One `.fde/` each they stop blurring |
185
+ | **Fractional CTO on client work** | System of record for the embed, and the billable trail |
200
186
 
201
187
  ---
202
188
 
203
189
  ## Your data stays yours
204
190
 
205
- - **Local only.** Pure `git` + file reads - no network calls, no telemetry, no account. Works air-gapped.
206
- - **Plain markdown.** No database, no lock-in.
207
- - **No new data path.** The AI sees client code only when *you* point your agent at it. `<private>` tags are redacted from CLI/dashboard/hook output; do not feed raw private blocks into the model (file tools bypass that redaction).
208
- - **Nothing enters the record unreviewed.** The model drafts, you confirm (`fde debrief --dry-run` shows the routing first); the hooks record only git facts. Your fieldbook stays yours to defend.
209
- - **Know your sync surface.** `~/fde-engagements` lives in your home directory - your backup and cloud-sync setup now covers client notes. `fde resume --init` warns if the folder sits in a synced path. Read [PRIVACY.md](PRIVACY.md) before your first NDA'd engagement.
191
+ - **Local only.** `git` + files. No network, no telemetry, no account. Air-gapped is fine.
192
+ - **Plain markdown.** No database.
193
+ - **No new data path.** The model sees client code only when you point the AI coding agent at it. `<private>` is redacted from CLI, dashboard, and hooks — do not open raw private blocks with file tools.
194
+ - **Nothing unreviewed.** Draft you confirm. `fde debrief --dry-run` shows routing first.
195
+ - **Know the sync surface.** `~/fde-engagements` is in `$HOME`. iCloud/Dropbox is an NDA incident waiting. `resume --init` warns. [PRIVACY.md](PRIVACY.md) before the first NDA.
210
196
 
211
- Details: [PRIVACY.md](PRIVACY.md) · [SECURITY.md](SECURITY.md)
197
+ [PRIVACY.md](PRIVACY.md) · [SECURITY.md](SECURITY.md)
212
198
 
213
199
  ---
214
200
 
215
201
  ## Principles
216
202
 
217
- - **The artifact is the memory** - producing work and recording it are one action
218
- - **Methods, not autonomy** - each skill tells you what to check; the judgment, the trust, and the consequences stay yours
219
- - **Brief is a hypothesis** - discover before building the wrong thing
220
- - **Evidence on every claim** - these files get defended in front of skeptical clients
221
- - **One customer, one folder** - context never bleeds
203
+ - **The artifact is the memory** producing the work and recording it are one action
204
+ - **Methods, not autonomy** the kit says what to check; judgment stays yours
205
+ - **Brief is a hypothesis** discover before building the wrong thing
206
+ - **Evidence on every claim** these files get defended in the room
207
+ - **One customer, one folder** context never bleeds
222
208
 
223
209
  ---
224
210
 
225
211
  ## Updating
226
212
 
227
- ```bash
228
- # Plugin / skills install: re-run the install command from Quickstart
229
- # From a git clone:
230
- cd fdeops && git pull && node bin/install.js
231
- ```
213
+ Re-run the Quickstart install, or from a clone: `git pull && node bin/install.js`
232
214
 
233
215
  ---
234
216
 
235
217
  ## Contributing
236
218
 
237
- 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).
219
+ **[Subash Natarajan](https://www.linkedin.com/in/subashn/)**. [Issues](https://github.com/suboss87/fdeops/issues) · [CONTRIBUTING.md](CONTRIBUTING.md)
238
220
 
239
- 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.
221
+ Thanks to builders whose craft sharpened the thinking, 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 is handcrafted for field work; resemblance is craft, not a fork.
240
222
 
241
- **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.
223
+ **What we won't build:** SaaS sync; Slack/Notion/Granola connectors or **push** inside the CLI; CRM as core; hardware capture; generic code-craft packs (TDD/review live elsewhere). You may **pull** via *your* MCP. The `fde` CLI stays local-only.
242
224
 
243
- [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
225
+ [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
@@ -499,7 +499,7 @@ if (!fs.existsSync(path.join(root, 'mcp', 'fdeops-ingest', 'server.js'))) {
499
499
  } else if (!fs.existsSync(path.join(root, 'skills', 'fde', 'references', 'ingest-connect.md'))) {
500
500
  fail('skills/fde/references/ingest-connect.md missing')
501
501
  } else {
502
- for (const recipe of ['file.md', 'granola.md', 'notion.md']) {
502
+ for (const recipe of ['file.md', 'granola.md', 'slack.md', 'notion.md']) {
503
503
  if (!fs.existsSync(path.join(root, 'mcp', 'recipes', recipe))) fail(`mcp/recipes/${recipe} missing`)
504
504
  }
505
505
  if (!read('README.md').includes('mcp/recipes')) fail('README must point at mcp/recipes for connect clarity')
package/mcp/README.md CHANGED
@@ -6,7 +6,7 @@ FDEOps MCP servers follow a **pluggable source model**: core owns the **sink**,
6
6
 
7
7
  | Role | Owner | Examples |
8
8
  |------|-------|----------|
9
- | **Source** | FDE configures separately | Granola, Gmail, Notion, custom scrapers |
9
+ | **Source** | FDE configures separately | Granola, Slack, Notion, Gmail, file |
10
10
  | **Sink** | FDEOps (`fdeops-ingest`) | stage → propose → apply into engagement memory |
11
11
 
12
12
  Source MCPs fetch raw text from SaaS APIs using credentials the FDE manages. The ingest MCP never stores OAuth tokens or calls external services — it only shells out to the local `fde` CLI.
@@ -2,7 +2,9 @@
2
2
 
3
3
  Thin stdio MCP server for the FDEOps **ingest sink** only: **stage → propose → apply**.
4
4
 
5
- This package shells out to the local `fde` CLI. It never calls SaaS APIs. Source MCPs (Granola, Gmail, Notion, etc.) are **separate** — you add those in your own `mcp.json`.
5
+ This package shells out to the local `fde` CLI. It never calls SaaS APIs. Source MCPs (Granola, Slack, Notion, etc.) are **separate** — you add those in your own `mcp.json`.
6
+
7
+ **Prefer the CLI when this workspace is bound:** `fde ingest stage|list|propose|apply`. Use this MCP when the host did not start in a bound workspace — then pass `engagement` (path to `.fde/` from `fde resume --bind`) on every tool call.
6
8
 
7
9
  ## Tools
8
10
 
@@ -89,4 +91,4 @@ Sources are pluggable and user-configured. This MCP owns the sink only.
89
91
 
90
92
  ## Zero dependencies
91
93
 
92
- Hand-rolled MCP over stdio (Content-Length framed JSON-RPC). No `@modelcontextprotocol/sdk` required at runtime.
94
+ Hand-rolled MCP over stdio (newline-delimited JSON-RPC). No `@modelcontextprotocol/sdk` required at runtime.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fdeops-ingest-mcp",
3
- "version": "3.10.0",
3
+ "version": "3.10.2",
4
4
  "private": true,
5
5
  "description": "Thin stdio MCP sink for FDEOps ingest (stage → propose → apply). Zero runtime dependencies.",
6
6
  "bin": {
@@ -4,7 +4,8 @@
4
4
  /**
5
5
  * fdeops-ingest MCP — thin stdio sink for FDEOps ingest.
6
6
  * Shells out to local `fde` CLI only. Never calls SaaS.
7
- * MCP stdio transport: Content-Length framed JSON-RPC 2.0.
7
+ * MCP stdio transport: newline-delimited JSON-RPC 2.0
8
+ * (Content-Length frames are accepted on input).
8
9
  */
9
10
 
10
11
  const fs = require('fs')
@@ -15,11 +16,17 @@ const PROTOCOL_VERSION = '2024-11-05'
15
16
  const SERVER_NAME = 'fdeops-ingest'
16
17
  const SERVER_VERSION = require('./package.json').version
17
18
 
19
+ const ENGAGEMENT_PROP = {
20
+ type: 'string',
21
+ description:
22
+ 'Path to this client\'s .fde/ folder (from `fde resume --bind`). Optional if FDEOPS_ENGAGEMENT is set or the process cwd is already bound.',
23
+ }
24
+
18
25
  const TOOLS = [
19
26
  {
20
27
  name: 'ingest_stage',
21
28
  description:
22
- 'Stage raw content into the engagement inbox (.inbox/). Does not write .fde/.',
29
+ 'Stage raw content into the engagement inbox (.inbox/). Does not write .fde/. Prefer the fde ingest CLI when the workspace is already bound.',
23
30
  inputSchema: {
24
31
  type: 'object',
25
32
  properties: {
@@ -29,12 +36,13 @@ const TOOLS = [
29
36
  },
30
37
  source: {
31
38
  type: 'string',
32
- description: 'Provenance label (e.g. granola, gmail, manual). Default: manual.',
39
+ description: 'Provenance label (e.g. granola, slack, notion, file, manual). Default: manual.',
33
40
  },
34
41
  title: {
35
42
  type: 'string',
36
43
  description: 'Optional human-readable title for the staged item.',
37
44
  },
45
+ engagement: ENGAGEMENT_PROP,
38
46
  },
39
47
  required: ['content'],
40
48
  },
@@ -42,7 +50,10 @@ const TOOLS = [
42
50
  {
43
51
  name: 'ingest_list',
44
52
  description: 'List staged items in the current engagement inbox.',
45
- inputSchema: { type: 'object', properties: {} },
53
+ inputSchema: {
54
+ type: 'object',
55
+ properties: { engagement: ENGAGEMENT_PROP },
56
+ },
46
57
  },
47
58
  {
48
59
  name: 'ingest_propose',
@@ -55,6 +66,7 @@ const TOOLS = [
55
66
  type: 'string',
56
67
  description: 'Staged filename or id from ingest_list.',
57
68
  },
69
+ engagement: ENGAGEMENT_PROP,
58
70
  },
59
71
  required: ['id'],
60
72
  },
@@ -63,7 +75,10 @@ const TOOLS = [
63
75
  name: 'ingest_apply',
64
76
  description:
65
77
  'Apply the current debrief proposal into .fde/ memory (requires prior FDE confirm).',
66
- inputSchema: { type: 'object', properties: {} },
78
+ inputSchema: {
79
+ type: 'object',
80
+ properties: { engagement: ENGAGEMENT_PROP },
81
+ },
67
82
  },
68
83
  ]
69
84
 
@@ -128,10 +143,10 @@ function fdeEnv() {
128
143
  return env
129
144
  }
130
145
 
131
- function runFde(args, stdin) {
146
+ function runFde(args, stdin, extraEnv) {
132
147
  const { cmd, prefix } = resolveFde()
133
148
  const result = spawnSync(cmd, [...prefix, ...args], {
134
- env: fdeEnv(),
149
+ env: { ...fdeEnv(), ...(extraEnv || {}) },
135
150
  input: stdin ?? undefined,
136
151
  encoding: 'utf8',
137
152
  maxBuffer: 16 * 1024 * 1024,
@@ -144,6 +159,11 @@ function runFde(args, stdin) {
144
159
  }
145
160
  }
146
161
 
162
+ function engagementEnv(args) {
163
+ const p = args && typeof args.engagement === 'string' ? args.engagement.trim() : ''
164
+ return p ? { FDEOPS_ENGAGEMENT: p } : {}
165
+ }
166
+
147
167
  function cliPayload(out) {
148
168
  const payload = { stdout: out.stdout, stderr: out.stderr, status: out.status }
149
169
  if (out.error) payload.spawnError = out.error
@@ -163,6 +183,7 @@ function toolError(payload) {
163
183
 
164
184
  function handleToolCall(name, args) {
165
185
  args = args || {}
186
+ const extraEnv = engagementEnv(args)
166
187
 
167
188
  switch (name) {
168
189
  case 'ingest_stage': {
@@ -172,23 +193,23 @@ function handleToolCall(name, args) {
172
193
  const source = args.source || 'manual'
173
194
  const cliArgs = ['ingest', 'stage', '--source', source]
174
195
  if (args.title) cliArgs.push('--title', args.title)
175
- const out = runFde(cliArgs, args.content)
196
+ const out = runFde(cliArgs, args.content, extraEnv)
176
197
  const payload = cliPayload(out)
177
198
  return out.status === 0 ? toolResult(payload) : toolError(payload)
178
199
  }
179
200
  case 'ingest_list': {
180
- const out = runFde(['ingest', 'list'])
201
+ const out = runFde(['ingest', 'list'], undefined, extraEnv)
181
202
  const payload = cliPayload(out)
182
203
  return out.status === 0 ? toolResult(payload) : toolError(payload)
183
204
  }
184
205
  case 'ingest_propose': {
185
206
  if (!args.id) return toolError('Missing required argument: id')
186
- const out = runFde(['ingest', 'propose', String(args.id)])
207
+ const out = runFde(['ingest', 'propose', String(args.id)], undefined, extraEnv)
187
208
  const payload = cliPayload(out)
188
209
  return out.status === 0 ? toolResult(payload) : toolError(payload)
189
210
  }
190
211
  case 'ingest_apply': {
191
- const out = runFde(['ingest', 'apply'])
212
+ const out = runFde(['ingest', 'apply'], undefined, extraEnv)
192
213
  const payload = cliPayload(out)
193
214
  return out.status === 0 ? toolResult(payload) : toolError(payload)
194
215
  }
@@ -1,15 +1,16 @@
1
1
  # Ingest source recipes
2
2
 
3
- FDEOps does **not** bundle Granola / Notion / Drive OAuth. These recipes show how an FDE wires a **source MCP** (or file drop) into the FDEOps **sink**.
3
+ FDEOps does **not** bundle Granola / Slack / Notion OAuth and does **not** push to those tools.
4
4
 
5
- **Contract every source must satisfy:** fetch text `fde ingest stage` (or MCP `ingest_stage`) with `{ source, title, content }` → propose → FDE confirms → apply.
5
+ **Daily (no MCP):** paste notes to `@fde debrief`, or drop a file ([file.md](./file.md)).
6
+
7
+ **Pull (optional):** you add a **source** MCP. The agent fetches text, then runs `fde ingest` in this bound workspace (stage → propose → you confirm → apply). The `fdeops-ingest` MCP is optional — only if you are not using the CLI from a bound workspace.
6
8
 
7
9
  | Recipe | When |
8
10
  |--------|------|
9
- | [file.md](./file.md) | Local transcript / export already on disk (no source MCP) |
10
- | [granola.md](./granola.md) | Meeting transcripts via a Granola-shaped MCP (or export) |
11
- | [notion.md](./notion.md) | Notion pages / meeting notes via a Notion MCP |
12
-
13
- Also wire the sink once: [fdeops-ingest/README.md](../fdeops-ingest/README.md).
11
+ | [file.md](./file.md) | Transcript / export already on disk, or paste |
12
+ | [granola.md](./granola.md) | Meeting transcripts via a notes MCP (or export) |
13
+ | [slack.md](./slack.md) | Pull a thread/channel as text never post |
14
+ | [notion.md](./notion.md) | Read a Notion page (or export markdown) |
14
15
 
15
- **Natural language:** `@fde I want to connect Granola` agent follows `skills/fde/references/ingest-connect.md` and this recipe.
16
+ **Natural language:** `@fde I want to connect Granola` (or Slack / Notion) → `skills/fde/references/ingest-connect.md`.
@@ -1,10 +1,10 @@
1
1
  # Recipe: local file / paste (no source MCP)
2
2
 
3
- **Use when:** you already have a transcript, `.eml`, or export on disk — or you paste into chat.
3
+ **Use when:** you already have a transcript, `.eml`, or export on disk — or you paste into chat. This is the default FDE path.
4
4
 
5
5
  ## Setup
6
6
 
7
- None beyond the FDEOps sink (`fde` CLI and optionally `fdeops-ingest` MCP).
7
+ None. Bound workspace + `fde ingest` (or `@fde debrief` for short notes).
8
8
 
9
9
  ## Pull phrase
10
10
 
@@ -12,14 +12,14 @@ None beyond the FDEOps sink (`fde` CLI and optionally `fdeops-ingest` MCP).
12
12
  @fde stage this transcript into the fieldbook and propose updates
13
13
  ```
14
14
 
15
- (or attach / point at a path)
15
+ (or attach / point at a path, or paste and say debrief)
16
16
 
17
17
  ## Agent steps
18
18
 
19
- 1. Bind engagement.
20
- 2. `fde ingest stage --source file --title "<short>" <path>` (or stdin).
21
- 3. `fde ingest propose <id>` → rewrite prefixes → show FDE → on confirm `fde ingest apply`.
19
+ 1. Bind engagement (`fde resume`).
20
+ 2. Short paste → debrief verb. Long file → `fde ingest stage --source file --title "<short>" <path>`.
21
+ 3. Propose → rewrite prefixes → show FDE → on confirm apply.
22
22
 
23
23
  ## mcp.json
24
24
 
25
- Not required for the source. Optional sink only — see [../fdeops-ingest/README.md](../fdeops-ingest/README.md).
25
+ Not required.
@@ -2,16 +2,19 @@
2
2
 
3
3
  **Use when:** meeting notes live in Granola (or a similar notes MCP). FDEOps does not ship a Granola server — you add whichever MCP/export path you trust.
4
4
 
5
+ Daily path if the notes are already in chat or on disk: paste to `@fde debrief` or [file.md](./file.md). This recipe is only for **pull**.
6
+
5
7
  ## Setup (once)
6
8
 
7
- 1. Install / enable a **Granola (or notes) MCP** in Cursor/Claude per that product’s docs.
8
- 2. Add the FDEOps **sink** MCP (`fdeops-ingest`) — [../fdeops-ingest/README.md](../fdeops-ingest/README.md).
9
- 3. Reload MCP / restart the agent host.
10
- 4. Test: `@fde what can you pull?` — agent should see both sink tools and the notes source tools.
9
+ 1. Enable a **Granola (or notes) MCP** in Cursor/Claude per that product’s docs.
10
+ 2. Reload MCP / restart the host.
11
+ 3. Test: `@fde what can you pull?` — notes-source tools should appear.
12
+
13
+ The sink is **`fde ingest` in this bound workspace.** You do not need `fdeops-ingest` MCP for daily pull.
11
14
 
12
15
  ### Example mcp.json shape (illustrative)
13
16
 
14
- Replace `granola-mcp` command/args with whatever the real server documents. FDEOps only needs *some* tool that returns transcript text.
17
+ Replace command/args with whatever the real Granola MCP documents. FDEOps only needs *some* tool that returns transcript text.
15
18
 
16
19
  ```json
17
20
  {
@@ -22,19 +25,12 @@ Replace `granola-mcp` command/args with whatever the real server documents. FDEO
22
25
  "env": {
23
26
  "GRANOLA_API_KEY": "from-your-secrets"
24
27
  }
25
- },
26
- "fdeops-ingest": {
27
- "command": "node",
28
- "args": ["/absolute/path/to/fdeops/mcp/fdeops-ingest/server.js"],
29
- "env": {
30
- "FDEOPS_ENGAGEMENT": "/Users/you/fde-engagements/acme/.fde"
31
- }
32
28
  }
33
29
  }
34
30
  }
35
31
  ```
36
32
 
37
- **No Granola MCP available?** Export transcript to a file → follow [file.md](./file.md).
33
+ **No Granola MCP available?** Export transcript to a file → [file.md](./file.md).
38
34
 
39
35
  ## Pull phrase
40
36
 
@@ -44,15 +40,15 @@ Replace `granola-mcp` command/args with whatever the real server documents. FDEO
44
40
 
45
41
  ## Agent steps
46
42
 
47
- 1. Capability check — if no notes/Granola tools, run connect flow (`ingest-connect.md`).
48
- 2. Fetch transcript via source MCP (or ask which meeting).
49
- 3. `ingest_stage` / `fde ingest stage --source granola --title ""`.
50
- 4. Propose confirm apply. Never auto-apply.
43
+ 1. Capability check — notes-source tools present?
44
+ 2. Fetch transcript text (ask which meeting if ambiguous).
45
+ 3. `fde ingest stage --source granola --title "<short>"` then propose → confirm → apply.
46
+ 4. Extract decisions/risks/next do not dump the raw transcript into `.fde/`.
51
47
 
52
48
  ## Common fails
53
49
 
54
50
  | Symptom | Fix |
55
51
  |---------|-----|
56
- | Agent says it can’t reach Granola | MCP not saved / host not reloaded / wrong env key |
57
- | Wrong client inbox | Set `FDEOPS_ENGAGEMENT` or bind workspace (`fde resume --init`) |
58
- | Empty propose | Agent must rewrite `.debrief-propose` with type prefixes |
52
+ | No Granola tools | Source MCP not loaded they save + reload |
53
+ | Wrong meeting | One clarifying question, then fetch |
54
+ | Wrong engagement | `fde resume` in this workspace before staging |
@@ -1,13 +1,14 @@
1
1
  # Recipe: Notion docs / meeting notes
2
2
 
3
- **Use when:** useful engagement notes live in Notion. FDEOps does not ship a Notion server — use a Notion MCP (or export markdown).
3
+ **Use when:** useful engagement notes live in Notion. FDEOps does not ship a Notion server — use a Notion MCP (or export markdown). We do not write back to Notion.
4
4
 
5
5
  ## Setup (once)
6
6
 
7
- 1. Enable a **Notion MCP** (official or community) with a token that can read the pages you need.
8
- 2. Add **fdeops-ingest** sink [../fdeops-ingest/README.md](../fdeops-ingest/README.md).
9
- 3. Reload MCP / restart host.
10
- 4. Test: `@fde what can you pull?`
7
+ 1. Enable a **Notion MCP** (official or community) with a token that can **read** the pages you need.
8
+ 2. Reload MCP / restart host.
9
+ 3. Test: `@fde what can you pull?`
10
+
11
+ The sink is **`fde ingest` in this bound workspace.** `fdeops-ingest` MCP is optional.
11
12
 
12
13
  ### Example mcp.json shape (illustrative)
13
14
 
@@ -20,13 +21,6 @@
20
21
  "env": {
21
22
  "NOTION_TOKEN": "from-your-secrets"
22
23
  }
23
- },
24
- "fdeops-ingest": {
25
- "command": "node",
26
- "args": ["/absolute/path/to/fdeops/mcp/fdeops-ingest/server.js"],
27
- "env": {
28
- "FDEOPS_ENGAGEMENT": "/Users/you/fde-engagements/acme/.fde"
29
- }
30
24
  }
31
25
  }
32
26
  }
@@ -42,15 +36,19 @@
42
36
 
43
37
  ## Agent steps
44
38
 
45
- 1. Capability check — Notion tools present?
46
- 2. Fetch page/block text via Notion MCP (ask which page if ambiguous).
47
- 3. Stage with `--source notion`.
48
- 4. Propose → confirm → apply.
39
+ 1. Capability check — Notion read tools present?
40
+ 2. Fetch page/block text (ask which page if ambiguous).
41
+ 3. `fde ingest stage --source notion --title "<short>"` → propose → confirm → apply.
42
+
43
+ ## Never
44
+
45
+ - Create or edit Notion pages from FDEOps.
46
+ - Ambient-sync a database.
49
47
 
50
48
  ## Common fails
51
49
 
52
50
  | Symptom | Fix |
53
51
  |---------|-----|
54
52
  | 401 / forbidden | Token lacks access to that workspace/page |
55
- | Huge page dump | Stage full text in `.inbox/`; propose only short dated facts |
56
- | Wrong engagement | Bind / `FDEOPS_ENGAGEMENT` |
53
+ | Huge page dump | Stage full text in `.inbox/`; apply only short dated facts |
54
+ | Wrong engagement | Bind this workspace before staging |
@@ -0,0 +1,61 @@
1
+ # Recipe: Slack (pull only)
2
+
3
+ **Use when:** useful context lives in a Slack thread or channel. FDEOps does **not** ship a Slack server, does **not** post messages, and does **not** sync channels.
4
+
5
+ You add whatever Slack MCP your host already supports. We only accept **text you pulled**, then the same confirm loop as a debrief.
6
+
7
+ ## Setup (once)
8
+
9
+ 1. Enable a **Slack MCP** (official or community) with read access to the threads you need.
10
+ 2. Reload MCP / restart the host.
11
+ 3. Test: `@fde what can you pull?` — Slack fetch tools should appear. The FDEOps **CLI** (`fde ingest`) is the sink if this workspace is bound; you do not need `fdeops-ingest` MCP for daily use.
12
+
13
+ ### Example mcp.json shape (illustrative)
14
+
15
+ Replace the Slack server with whatever that MCP actually documents. Do not invent a package name.
16
+
17
+ ```json
18
+ {
19
+ "mcpServers": {
20
+ "slack": {
21
+ "command": "npx",
22
+ "args": ["-y", "YOUR-SLACK-MCP-PACKAGE"],
23
+ "env": {
24
+ "SLACK_BOT_TOKEN": "from-your-secrets"
25
+ }
26
+ }
27
+ }
28
+ }
29
+ ```
30
+
31
+ Optional sink MCP (only if you are not running `fde ingest` from this workspace): see [../fdeops-ingest/README.md](../fdeops-ingest/README.md). Pass `engagement` as the path to this client's `.fde/` (from `fde resume --bind`).
32
+
33
+ **No Slack MCP?** Copy the thread to a file or paste into chat → [file.md](./file.md) or `@fde debrief`.
34
+
35
+ ## Pull phrase
36
+
37
+ ```text
38
+ @fde pull yesterday's #acme-launch thread into the fieldbook
39
+ ```
40
+
41
+ ## Agent steps
42
+
43
+ 1. Capability check — Slack **read** tools present? If not → this recipe, then stop.
44
+ 2. Fetch the thread/channel as **text** (ask which channel/thread if ambiguous).
45
+ 3. `fde ingest stage --source slack --title "<short>"` (CLI in this bound workspace).
46
+ 4. Propose → FDE confirms → apply. Extract decisions/risks/asks — do not dump the thread into `.fde/`.
47
+
48
+ ## Never
49
+
50
+ - Post, reply, or react in Slack from FDEOps.
51
+ - Background-sync a channel.
52
+ - Auto-apply.
53
+
54
+ ## Common fails
55
+
56
+ | Symptom | Fix |
57
+ |---------|-----|
58
+ | No Slack tools | Source MCP not loaded — they save + reload; we cannot silent-install |
59
+ | Missing channel | Token/scopes cannot read that workspace — their Slack admin, not FDEOps |
60
+ | Huge dump | Stage full text in `.inbox/`; apply only short dated facts |
61
+ | Wrong client | Bind this workspace (`fde resume`) before staging |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fdeops",
3
- "version": "3.10.0",
3
+ "version": "3.10.2",
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/plugin.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
3
3
  "name": "fdeops",
4
- "version": "3.10.0",
4
+ "version": "3.10.2",
5
5
  "description": "Engagement fieldbook for Forward Deployed Engineers: per-client memory in local .fde/ files, one @fde skill, land to close methodology. Local-only, no network.",
6
6
  "author": {
7
7
  "name": "Subash Natarajan",
@@ -83,8 +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; **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. |
86
+ | "Make sure we're up to date" / "pull relevant info" / "pull from Granola/Slack/transcript" | Bind engagement; **capability check** (which *source* MCPs exist — never pretend). If missing → connect flow. Else fetch text → `fde ingest stage` **in this workspace** propose → rewrite prefixes → show FDE → on confirm `fde ingest apply`. MCP sink is optional; if used, pass `engagement` from `fde resume --bind`. **Never auto-apply. Never push. Never ambient sync.** Detail: `references/ingest.md` |
87
+ | "Connect a new MCP" / "connect Granola/Slack/Notion" / "what can you pull?" | Follow `references/ingest-connect.md`: source MCP only; sink is `fde ingest` here. They save/reload; you cannot silent-install. Paste still works with no MCP. |
88
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/` |
89
89
  | "When did we agree…?" / scope dispute | `fde receipts <term>` - answer with dates; no hit = gap, not proof |
90
90
  | "Draft the sponsor update" / how are we doing | `fde status` then follow `references/status.md` for the narrative |
@@ -271,8 +271,8 @@ Running the engagement and ending it well.
271
271
  | Weekly update due, "need to send the sponsor something" | status | `references/status.md` |
272
272
  | Demo coming up, show-and-tell, exec walkthrough | demo-prep | `references/demo-prep.md` |
273
273
  | Just out of a meeting, raw notes, "they said…", "debrief" | debrief | the debrief verb (above) + `references/debrief.md` |
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
+ | Make sure we're up to date, pull what's relevant, fetch from Granola/Slack/Gmail/transcript | ingest | `references/ingest.md` (capability check → stage → propose → confirm → apply) |
275
+ | Connect a new MCP / connect Granola Slack or Notion / what can you pull | ingest-connect | `references/ingest-connect.md` (+ `mcp/recipes/`) |
276
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 |
277
277
  | Sponsor's boss needs a summary, board update, justify continued investment | exec-narrative | `references/exec-narrative.md` |
278
278
  | Status across all my customers | dashboard | `references/dashboard.md` |
@@ -1,36 +1,34 @@
1
1
  # ingest-connect - wire a source MCP in plain language
2
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.
3
+ **Enter when:** the FDE says "I want to connect a new MCP", "connect Granola / Slack / Notion", "how do I pull from …", or a pull request fails because no source tools exist.
4
4
 
5
- **Read first:** `references/ingest.md` (sink contract). Recipe pack: `mcp/recipes/` in the fdeops install (file, granola, notion).
5
+ **Read first:** `references/ingest.md` (sink contract). Recipes: `mcp/recipes/` (file, granola, slack, notion).
6
6
 
7
7
  **Who runs setup:** you guide; the **host** (Cursor/Claude) must save MCP config. You cannot silently install servers into the host.
8
8
 
9
9
  ## Honest contract
10
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/`.
11
+ - **Daily work does not need a source MCP.** Paste notes → debrief. File on disk `fde ingest`.
12
+ - **Connect means a source**, not FDEOps. Granola/Slack/Notion credentials stay with that MCP. FDEOps never pushes, never ambient-syncs, never stores their tokens.
13
+ - **Sink is the CLI in this bound workspace** (`fde ingest`). `fdeops-ingest` MCP is optional. If you use it, pass `engagement` as the `.fde/` path from `fde resume --bind` (MCP servers often do not inherit the workspace bind).
14
+ - Never invent that Granola/Slack is available if tools are missing. Never auto-apply to `.fde/`.
14
15
 
15
16
  ## Method
16
17
 
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
+ 1. **Ask one question** — which source? (`file` / `granola` / `slack` / `notion` / other). If "other", ask for the MCP they intend to use. If they just want paste → send them to debrief and stop.
18
19
  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)
20
+ - Sink: `fde ingest` CLI (preferred) and/or `ingest_stage`
21
+ - Source: anything that can **fetch** that system's content (not post)
21
22
  - 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`.
23
+ 3. **Emit config for the source only** open `mcp/recipes/<source>.md`. Fill placeholders from *that product's* docs. Tell them to paste secrets into host env — never into `.fde/`.
24
+ 4. **Tell them where to paste** — Cursor MCP settings / `mcp.json`. Claude Code: their MCP config. Save → reload MCP / restart session.
25
+ 5. **Verify** — after reload: re-run capability check. If source tools appear, offer a **test pull** staged to `.inbox/` only. Stop before apply unless they ask to propose.
26
+ 6. **Handoff phrase** e.g. `@fde pull today's Acme Granola into the fieldbook`.
29
27
 
30
- ## If they only want the sink
28
+ ## If they only want paste / files
31
29
 
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.
30
+ Do not add MCP. Use debrief or [mcp/recipes/file.md](../../../mcp/recipes/file.md).
33
31
 
34
32
  ## Checkpoint
35
33
 
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.
34
+ Before ending connect: (1) they know paste still works, (2) source reachable or honest gap, (3) they know the pull phrase. Do not write `.fde/` during connect.
@@ -2,7 +2,7 @@
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).
5
+ **Connect / capability (different entry):** "connect a new MCP", "connect Granola/Slack/Notion", "what can you pull?" → `references/ingest-connect.md` first. Recipes: `mcp/recipes/` (file, granola, slack, notion).
6
6
 
7
7
  **Read first:** `context.md` (what's already logged, what's stale). Bind the engagement before staging anything.
8
8
 
@@ -11,7 +11,8 @@
11
11
  ## Honest contract (read once)
12
12
 
13
13
  - FDEOps owns the **sink only**: stage raw pulls → propose → confirm → apply. Nothing writes `.fde/` unreviewed.
14
- - **Source MCPs are the FDE's.** Granola, Gmail, Notion, custom — whatever they configured in Cursor/Claude. fdeops does not bundle OAuth, connectors, or ambient sync.
14
+ - **Source MCPs are the FDE's.** Granola, Slack, Notion, Gmail, custom — whatever they configured in Cursor/Claude. fdeops does not bundle OAuth, connectors, or ambient sync, and **does not push** to those tools.
15
+ - Prefer **`fde ingest` in this bound workspace.** Optional `fdeops-ingest` MCP: pass `engagement` (path to `.fde/` from `fde resume --bind`) because MCP cwd often is not the client workspace.
15
16
  - The core `fde` CLI stays local (git + file reads). Source credentials live with that MCP; fdeops never stores them.
16
17
  - After apply, raw stays in `.inbox/`; the system of record (`.fde/`) stays thin dated facts.
17
18
 
@@ -20,7 +21,7 @@
20
21
  List what you can actually call **this session**:
21
22
 
22
23
  1. **Sink** — `ingest_stage` / `fde ingest` available?
23
- 2. **Sources** — which fetch tools exist (Granola-shaped, Notion, Drive, file-only)?
24
+ 2. **Sources** — which fetch tools exist (Granola-shaped, Slack, Notion, Drive, file-only)?
24
25
  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
26
 
26
27
  ## Ground loop (you do this work)
@@ -67,6 +68,6 @@ Before apply, read back the 2–3 most consequential captures in one breath —
67
68
 
68
69
  ## Principles
69
70
 
70
- - Pull on request, not on a schedule. No auto-poll, no vacuum of inbox or Slack.
71
+ - Pull on request, not on a schedule. No auto-poll, no vacuum of inbox or Slack. No posting back.
71
72
  - Staging is not memory. Only `--apply` after confirm writes `.fde/`.
72
73
  - Large artifact → ingest stage first; pasted short notes → debrief verb directly (`references/debrief.md`).