diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index b63bf21..e159ca9 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "fdeops", "description": "Second brain for Forward Deployed Engineers. One @fde skill - enter at day one, mid-project, or mid-fire; it routes and does the phase work; engagement memory lands in .fde/ as you confirm judgment.", - "version": "3.11.0", + "version": "3.11.1", "category": "productivity", "tags": [ "community-managed" diff --git a/CHANGELOG.md b/CHANGELOG.md index 662fed4..d348a76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 3.11.1 — 2026-08-27 + +Adoption: one skill, and the CLI is never missing. + +### Fixed +- **A skill-only install had no hands.** `npx skills add` copies the method but not the CLI, and the router's only fallback was `~/.claude/fdeops/fde.js` - absent on Cursor/Codex/anything that is not a Claude Code install - so the agent dropped to writing `.fde/` by hand and lost the dating, gates and `` redaction the CLI enforces. It now reaches for `npx --yes fdeops ` before any manual path; "CLI unavailable" means no Node or no network, not "not installed". +- **The advertised install pulled a contributor skill.** A bare `npx skills add suboss87/fdeops` also installs `testing-fieldbook`, which is for people working on this repo. The documented command is `--skill fde`, and a gate keeps it that way. + ## 3.11.0 — 2026-08-27 One window over every client, without a second memory to maintain. diff --git a/README.md b/README.md index 0d10809..da2f050 100644 --- a/README.md +++ b/README.md @@ -41,9 +41,11 @@ Nothing to install to see it on a fake client: `npx fdeops demo`. ``` ```bash -npx skills add suboss87/fdeops # Cursor, Codex, skills-compatible hosts +npx skills add suboss87/fdeops --skill fde # Cursor, Codex, skills-compatible hosts ``` +That is one skill, not a catalogue - `@fde` routes the whole method. The CLI needs no install either: the skill reaches for `npx fdeops` when `fde` is not on the PATH. (Drop `--skill fde` and you also get `testing-fieldbook`, which is for people contributing to this repo, not for field work.) + Claude Code additionally gets session hooks, so context arrives before you type. Everywhere else it is the same fieldbook, loaded when you ask. **2. Bind once** in the client workspace: diff --git a/bin/check.js b/bin/check.js index e5a26fd..a0a83bb 100644 --- a/bin/check.js +++ b/bin/check.js @@ -270,6 +270,22 @@ if (!readme.includes('fde-engagements') || !/fdeops.*init.*engagement/i.test(rea fail('README must document fde-engagements + init flow') } else ok('README engagement path') +// The contributor-only testing skill lives in .agents/skills/, so a bare +// `skills add` installs it too. The advertised command must name the one skill +// a field user wants. +for (const m of readme.match(/^.*npx skills add .*$/gm) || []) { + if (!m.includes('--skill fde')) { + fail(`README skills-add command must pin --skill fde: ${m.trim()}`) + } +} +ok('README skills install is one skill') + +// A skill-only install has no fde on the PATH; the router must reach npx before +// falling back to writing memory by hand. +if (!read('skills/fde/SKILL.md').includes('npx --yes fdeops')) { + fail('skills/fde/SKILL.md must fall back to npx --yes fdeops when the CLI is not installed') +} else ok('SKILL.md npx CLI fallback') + if (!fs.existsSync(path.join(root, 'docs', 'USAGE.md'))) { fail('docs/USAGE.md missing') } else ok('docs/USAGE.md') diff --git a/mcp/fdeops-ingest/package.json b/mcp/fdeops-ingest/package.json index 86660b2..826a004 100644 --- a/mcp/fdeops-ingest/package.json +++ b/mcp/fdeops-ingest/package.json @@ -1,6 +1,6 @@ { "name": "fdeops-ingest-mcp", - "version": "3.11.0", + "version": "3.11.1", "private": true, "description": "Thin stdio MCP sink for FDEOps ingest (stage → propose → apply). Zero runtime dependencies.", "bin": { diff --git a/package.json b/package.json index 464ee5d..19d461a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fdeops", - "version": "3.11.0", + "version": "3.11.1", "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.", "bin": { "fdeops": "bin/install.js", diff --git a/plugin.json b/plugin.json index 9733c27..a8ce33f 100644 --- a/plugin.json +++ b/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "fdeops", - "version": "3.11.0", + "version": "3.11.1", "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.", "author": { "name": "Subash Natarajan", diff --git a/skills/fde/SKILL.md b/skills/fde/SKILL.md index b581f9b..dbf8572 100644 --- a/skills/fde/SKILL.md +++ b/skills/fde/SKILL.md @@ -74,7 +74,7 @@ When NOT to interrogate or challenge: unambiguous one-liners, mechanical ops, FD - Data tagged `` (sacred data, PHI, cardholder, classified) is **redacted from CLI, dashboard, and hook-injected context**. Do **not** open raw `` blocks with file tools (that bypasses redaction) or paste them into prompts/subagents - work around them, never with them. - Locked-down engagement (no AI on their code)? Use the CLI + the fieldbook only. The memory layer is the FDE's own notes, not customer code. -**Engagement path - zero ceremony.** Run `fde resume` (fallback: `node ~/.claude/fdeops/fde.js resume`). The **workspace registry** (written once by `fde resume --init `) is the normal path; resolution order is env var override → registry → pointer file → workspace-name match (read-only) → `./.fde`. Writes require a bind (or `FDEOPS_ENGAGEMENT`), not folder name alone. It prints a **bounded** view of `context.md` - the curated head (state, next action) plus the most recent activity, with the older session log collapsed (use `fde resume --full` when you genuinely need the whole history). If it reports NO ENGAGEMENT: confirm the client name in conversation (one question), then run `fde resume --init ` yourself - the one setup step; the FDE never runs setup commands. Never install fdeops on infrastructure the FDE does not control. +**Engagement path - zero ceremony.** Run `fde resume` (fallbacks, in order: `node ~/.claude/fdeops/fde.js resume`, then `npx --yes fdeops resume` - the CLI is one command away on any machine with Node, so reach for it before doing memory work by hand). The **workspace registry** (written once by `fde resume --init `) is the normal path; resolution order is env var override → registry → pointer file → workspace-name match (read-only) → `./.fde`. Writes require a bind (or `FDEOPS_ENGAGEMENT`), not folder name alone. It prints a **bounded** view of `context.md` - the curated head (state, next action) plus the most recent activity, with the older session log collapsed (use `fde resume --full` when you genuinely need the whole history). If it reports NO ENGAGEMENT: confirm the client name in conversation (one question), then run `fde resume --init ` yourself - the one setup step; the FDE never runs setup commands. Never install fdeops on infrastructure the FDE does not control. **You run the `fde` CLI for deterministic work - never improvise shell, never hand the command to the FDE:** @@ -96,7 +96,7 @@ When NOT to interrogate or challenge: unambiguous one-liners, mechanical ops, FD **The debrief verb.** Highest-frequency loop. When the FDE shares notes or says "debrief": **you** run the smart path (write notes to a temp file if needed). `--smart` writes a propose file via deterministic heuristics (existing prefixes + light keywords); authentic rambling notes often land mostly in context until **you** rewrite lines with type prefixes. Show the proposed routing in plain language. Only `--apply` (or pipe prefixed lines) after they confirm. Never ask them to run the CLI. Detail: `references/debrief.md`. -CLI missing → use the manual fallbacks inside each reference (still you write files; still never ask the FDE to run setup). +CLI genuinely unavailable (no Node, offline, npx blocked) → use the manual fallbacks inside each reference (still you write files; still never ask the FDE to run setup). A skill-only install is not "unavailable": run the verb through `npx --yes fdeops …` so the gates, dating and redaction still hold. **Token model - where the cost goes.** Deterministic work is the CLI's job and costs **zero model tokens**: memory writes, recon, receipts, status, dashboard, and the bounded `fde resume`. Session-start hooks inject **TRIAGE + bounded `context.md` + a one-line pointer** - never this full skill body (that loads only when `@fde` triggers). Spend tokens only on judgment - reading the situation, routing, running the phase method, writing the artifact. Three rules keep a full day of FDE work cheap: load the router first and pull **one** reference only when you route to it; never dump a whole `.fde/` file into context - read the bounded resume, or `fde receipts ` for a targeted slice; don't re-read files you already have. The expensive model should fire for real decisions, not for plumbing the CLI already does.