fdeops 5.0.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/AGENTS.md +1 -1
  2. package/README.md +22 -24
  3. package/bin/catalog-doc.js +38 -0
  4. package/bin/check.js +20 -49
  5. package/bin/fde.js +2 -2
  6. package/bin/generate-skills.js +9 -1
  7. package/bin/install.js +9 -3
  8. package/bin/skill-catalog.js +283 -16
  9. package/mcp/fdeops-ingest/package.json +1 -1
  10. package/package.json +2 -2
  11. package/plugin.json +1 -1
  12. package/skills/README.md +7 -0
  13. package/skills/audit/.fde-generated.json +10 -0
  14. package/skills/audit/SKILL.md +21 -0
  15. package/skills/audit/references/audit.md +71 -0
  16. package/skills/audit/references/discover.md +112 -0
  17. package/skills/audit/references/task-context.md +18 -0
  18. package/skills/board-memo/.fde-generated.json +10 -0
  19. package/skills/board-memo/SKILL.md +21 -0
  20. package/skills/board-memo/references/board-memo.md +108 -0
  21. package/skills/board-memo/references/business-case.md +90 -0
  22. package/skills/board-memo/references/task-context.md +18 -0
  23. package/skills/brief/.fde-generated.json +9 -0
  24. package/skills/brief/SKILL.md +21 -0
  25. package/skills/brief/references/land.md +136 -0
  26. package/skills/brief/references/task-context.md +18 -0
  27. package/skills/build/.fde-generated.json +1 -1
  28. package/skills/build/references/task-context.md +7 -1
  29. package/skills/business-case/.fde-generated.json +9 -0
  30. package/skills/business-case/SKILL.md +21 -0
  31. package/skills/business-case/references/business-case.md +90 -0
  32. package/skills/business-case/references/task-context.md +18 -0
  33. package/skills/connect/.fde-generated.json +12 -0
  34. package/skills/connect/SKILL.md +21 -0
  35. package/skills/connect/references/connect.md +24 -0
  36. package/skills/connect/references/debrief.md +91 -0
  37. package/skills/connect/references/ingest.md +75 -0
  38. package/skills/connect/references/source-setup.md +30 -0
  39. package/skills/connect/references/task-context.md +18 -0
  40. package/skills/dashboard/.fde-generated.json +9 -0
  41. package/skills/dashboard/SKILL.md +21 -0
  42. package/skills/dashboard/references/dashboard.md +40 -0
  43. package/skills/dashboard/references/task-context.md +18 -0
  44. package/skills/debrief/.fde-generated.json +12 -0
  45. package/skills/debrief/SKILL.md +21 -0
  46. package/skills/debrief/references/connect.md +24 -0
  47. package/skills/debrief/references/debrief.md +91 -0
  48. package/skills/debrief/references/ingest.md +75 -0
  49. package/skills/debrief/references/source-setup.md +30 -0
  50. package/skills/debrief/references/task-context.md +18 -0
  51. package/skills/debug/.fde-generated.json +1 -1
  52. package/skills/debug/references/task-context.md +7 -1
  53. package/skills/demo-prep/.fde-generated.json +9 -0
  54. package/skills/demo-prep/SKILL.md +21 -0
  55. package/skills/demo-prep/references/demo-prep.md +31 -0
  56. package/skills/demo-prep/references/task-context.md +18 -0
  57. package/skills/discover/.fde-generated.json +1 -1
  58. package/skills/discover/references/task-context.md +7 -1
  59. package/skills/earn-trust/.fde-generated.json +9 -0
  60. package/skills/earn-trust/SKILL.md +21 -0
  61. package/skills/earn-trust/references/earn-trust.md +100 -0
  62. package/skills/earn-trust/references/task-context.md +18 -0
  63. package/skills/evaluate/.fde-generated.json +1 -1
  64. package/skills/evaluate/references/task-context.md +7 -1
  65. package/skills/fde/SKILL.md +9 -8
  66. package/skills/fde/references/connect.md +14 -24
  67. package/skills/fde/references/debrief.md +2 -0
  68. package/skills/fde/references/ingest.md +4 -2
  69. package/skills/fde/references/plan.md +6 -6
  70. package/skills/fde/references/runbook.md +52 -120
  71. package/skills/fde/references/source-setup.md +30 -0
  72. package/skills/fde/references/task-context.md +7 -1
  73. package/skills/feedback/.fde-generated.json +1 -1
  74. package/skills/feedback/references/task-context.md +7 -1
  75. package/skills/handoff/.fde-generated.json +1 -1
  76. package/skills/handoff/references/task-context.md +7 -1
  77. package/skills/ingest/.fde-generated.json +12 -0
  78. package/skills/ingest/SKILL.md +21 -0
  79. package/skills/ingest/references/connect.md +24 -0
  80. package/skills/ingest/references/debrief.md +91 -0
  81. package/skills/ingest/references/ingest.md +75 -0
  82. package/skills/ingest/references/source-setup.md +30 -0
  83. package/skills/ingest/references/task-context.md +18 -0
  84. package/skills/integrate/.fde-generated.json +1 -1
  85. package/skills/integrate/references/task-context.md +7 -1
  86. package/skills/options/.fde-generated.json +1 -1
  87. package/skills/options/references/task-context.md +7 -1
  88. package/skills/plan/.fde-generated.json +10 -0
  89. package/skills/plan/SKILL.md +21 -0
  90. package/skills/plan/references/business-case.md +90 -0
  91. package/skills/plan/references/plan.md +167 -0
  92. package/skills/plan/references/task-context.md +18 -0
  93. package/skills/poc/.fde-generated.json +2 -2
  94. package/skills/poc/references/plan.md +6 -6
  95. package/skills/poc/references/task-context.md +7 -1
  96. package/skills/prioritize/.fde-generated.json +10 -0
  97. package/skills/prioritize/SKILL.md +21 -0
  98. package/skills/prioritize/references/business-case.md +90 -0
  99. package/skills/prioritize/references/pick-three.md +95 -0
  100. package/skills/prioritize/references/task-context.md +18 -0
  101. package/skills/qa/.fde-generated.json +1 -1
  102. package/skills/qa/references/task-context.md +7 -1
  103. package/skills/readout/.fde-generated.json +1 -1
  104. package/skills/readout/references/task-context.md +7 -1
  105. package/skills/red-team/.fde-generated.json +9 -0
  106. package/skills/red-team/SKILL.md +21 -0
  107. package/skills/red-team/references/red-team.md +105 -0
  108. package/skills/red-team/references/task-context.md +18 -0
  109. package/skills/rescue/.fde-generated.json +9 -0
  110. package/skills/rescue/SKILL.md +21 -0
  111. package/skills/rescue/references/rescue.md +82 -0
  112. package/skills/rescue/references/task-context.md +18 -0
  113. package/skills/review/.fde-generated.json +1 -1
  114. package/skills/review/references/task-context.md +7 -1
  115. package/skills/rollback/.fde-generated.json +9 -0
  116. package/skills/rollback/SKILL.md +21 -0
  117. package/skills/rollback/references/rollback.md +102 -0
  118. package/skills/rollback/references/task-context.md +18 -0
  119. package/skills/runbook/.fde-generated.json +11 -0
  120. package/skills/runbook/SKILL.md +21 -0
  121. package/skills/runbook/references/close.md +66 -0
  122. package/skills/runbook/references/encode-pattern.md +96 -0
  123. package/skills/runbook/references/runbook.md +73 -0
  124. package/skills/runbook/references/task-context.md +18 -0
  125. package/skills/scope/.fde-generated.json +1 -1
  126. package/skills/scope/references/task-context.md +7 -1
  127. package/skills/score-use-cases/.fde-generated.json +10 -0
  128. package/skills/score-use-cases/SKILL.md +21 -0
  129. package/skills/score-use-cases/references/business-case.md +90 -0
  130. package/skills/score-use-cases/references/score-use-cases.md +70 -0
  131. package/skills/score-use-cases/references/task-context.md +18 -0
  132. package/skills/ship/.fde-generated.json +1 -1
  133. package/skills/ship/references/task-context.md +7 -1
  134. package/skills/switch-clients/.fde-generated.json +9 -0
  135. package/skills/switch-clients/SKILL.md +21 -0
  136. package/skills/switch-clients/references/switch-clients.md +114 -0
  137. package/skills/switch-clients/references/task-context.md +18 -0
  138. package/skills/test-assumptions/.fde-generated.json +9 -0
  139. package/skills/test-assumptions/SKILL.md +21 -0
  140. package/skills/test-assumptions/references/task-context.md +18 -0
  141. package/skills/test-assumptions/references/test-assumptions.md +102 -0
  142. package/skills/what-breaks/.fde-generated.json +9 -0
  143. package/skills/what-breaks/SKILL.md +21 -0
  144. package/skills/what-breaks/references/task-context.md +18 -0
  145. package/skills/what-breaks/references/what-breaks.md +91 -0
  146. package/skills/who-decides/.fde-generated.json +9 -0
  147. package/skills/who-decides/SKILL.md +21 -0
  148. package/skills/who-decides/references/task-context.md +18 -0
  149. package/skills/who-decides/references/who-decides.md +91 -0
package/AGENTS.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # AGENTS.md - working in the fdeops repository
2
2
 
3
- This repository **is** FDEOps: skills for Forward Deployed Engineers. The `fde` coordinator selects the relevant instructions for customer work. Fourteen task skills also work individually. The local CLI manages customer records in `.fde/` files; users confirm consequential judgments.
3
+ This repository **is** FDEOps: skills for Forward Deployed Engineers. The `fde` coordinator selects the relevant instructions for customer work. All 35 task skills also work individually. The local CLI manages customer records in `.fde/` files; users confirm consequential judgments.
4
4
 
5
5
  ## If you are helping use fdeops in an engagement
6
6
 
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  Work through a customer project from the first conversation to a system their team can run. FDEOps helps your agent clarify the problem, compare solutions, write and test code, connect customer systems, and prepare delivery and handover evidence.
8
8
 
9
- A **skill** is a set of instructions your AI coding agent follows. FDEOps includes **14 task skills** you can use individually and **one `fde` coordinator** that chooses the right task as a customer project progresses.
9
+ A **skill** is a set of instructions your AI coding agent follows. FDEOps includes **35 task skills + one coordinator, `fde`**. Use any skill directly, or ask `fde` to select the relevant skills as a customer project progresses.
10
10
 
11
11
  Use it for a single integration, a small client project, or work within a larger enterprise team. You bring the customer context, repository tools and access. FDEOps supplies the working method; you and the responsible teams make the decisions.
12
12
 
@@ -54,32 +54,30 @@ an incoming request today, where time goes, and what we still need to ask.
54
54
 
55
55
  The agent works from your notes and returns its findings. You do not need to create a customer record for this task. Each task skill includes the instructions it needs and works without installing `fde` or another skill pack.
56
56
 
57
- **Want every task available by name?** Install the full pack using the [installation guide](docs/install.md#individual-skills-and-the-full-pack). Installing `fde` alone gives the coordinator all the underlying instructions; it does not add the 14 separate names to your agent's skill menu.
57
+ **Want every task available by name?** Install the full pack using the [installation guide](docs/install.md#individual-skills-and-the-full-pack). Installing `fde` alone gives the coordinator all the underlying instructions; it does not add the 35 separate names to your agent's skill menu.
58
58
 
59
59
  Skill invocation differs between agents. Ask for the FDEOps skill by name or select it in your agent's skill picker. For Claude Code plugin installs, use `/fdeops:fde` or `/fdeops:discover`. See [host setup and name conflicts](docs/install.md#individual-skills-and-the-full-pack).
60
60
 
61
- ## Task skills
62
-
63
- A customer **workflow** means the steps people and systems take to finish a job: receive a request, check its details, make a decision, and update the relevant system. These skills help with different parts of that work.
64
-
65
- | What you need to do | Skill | What you get |
66
- |---|---|---|
67
- | Find the real problem behind a customer request | `discover` | Current steps, delays, baseline and unanswered questions |
68
- | Decide what to do with an additional request | `scope` | Impact on agreed work and a recommended commitment |
69
- | Choose how to solve the problem | `options` | Feasible approaches, trade-offs and a recommendation |
70
- | Test an assumption before committing to a build | `poc` | A limited test, its evidence and the next decision |
71
- | Implement an agreed software change | `build` | Code, checks and a clear account of what changed |
72
- | Connect the customer's systems | `integrate` | An integration checked for mapping, permissions and failed or repeated requests |
73
- | Find and fix a failure | `debug` | A reproduced problem, repair and regression checks |
74
- | Check a proposed code change | `review` | Specific findings tied to code and expected behavior |
75
- | Check an AI system's answers or actions | `evaluate` | Evaluation cases, results and remaining limits |
76
- | Test what users actually experience | `qa` | Runtime or browser evidence, including failure cases |
77
- | Prepare and carry out an authorized release | `ship` | Release checks, recovery steps and deployment evidence |
78
- | Explain progress to the customer sponsor | `readout` | What was promised, what was measured and what was accepted |
79
- | Leave the team able to operate the system | `handoff` | Responsibilities, operating instructions and readiness gaps |
80
- | Turn a deployment lesson into reusable learning | `feedback` | A supported product recommendation or reusable pattern |
81
-
82
- These are entry points, not a required sequence. `fde` also handles meeting debriefs, stakeholder decisions, planning, incidents and other situations through its [full skill reference](docs/skills-reference.md). It loads the relevant instructions as needed.
61
+ ## Choose a skill
62
+
63
+ <a name="task-skills"></a>
64
+
65
+ Use the skill that matches the work in front of you. All skills are individually installable; the [complete catalog](docs/skills-reference.md) lists the input and result for each one.
66
+
67
+ | You need to… | Start with |
68
+ |---|---|
69
+ | Clarify a new customer request | `brief` or `discover` |
70
+ | Understand who can approve the change | `who-decides` |
71
+ | Decide what to build and what to leave out | `options`, `scope` or `plan` |
72
+ | Implement or connect customer systems | `build` or `integrate` |
73
+ | Find a failure or test the result | `debug`, `review`, `evaluate` or `qa` |
74
+ | Prepare an authorized release | `ship` |
75
+ | Review meeting notes or report progress | `debrief` or `readout` |
76
+ | Prepare the team to run the system | `runbook` or `handoff` |
77
+
78
+ These examples are starting points, not a required sequence. The catalog also covers inherited projects, business cases, incidents, recovery, source connections and multiple customer records. `fde` uses the same instructions and loads additional detail only when needed.
79
+
80
+ **Which mode should I choose?** Use an individual skill for a specific task. Use `fde` when you want help across several tasks and a continuing customer record. Installing a skill makes it available independently; it does not remove its real input requirements. For example, `dashboard` needs records to display, while `debrief` can review pasted notes without saving anything.
83
81
 
84
82
  <a name="how-skills-work"></a>
85
83
 
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env node
2
+ const fs = require('node:fs')
3
+ const path = require('node:path')
4
+ const catalog = require('./skill-catalog')
5
+ const root = path.resolve(__dirname, '..')
6
+ const inputs = {
7
+ context: 'Supplied notes, code or evidence',
8
+ records: 'Existing customer records + CLI',
9
+ source: 'Host source tools or setup documentation',
10
+ 'record-write': 'Notes or source tools; selected record for staging/saving',
11
+ }
12
+ const cell = value => value.replace(/\|/g, '\\|').replace(/\n/g, ' ')
13
+ function renderCatalog(items = catalog) {
14
+ const out = ['# FDEOps skills', '', `**${items.length} task skills + one coordinator, \`fde\` = ${items.length + 1} installable skills.**`, '',
15
+ 'Every task below can be installed and used directly. Ask `fde` to select the relevant skills when working across a customer project. The groups help you find a task; they are not required phases.', '',
16
+ 'Install a task with `npx skills add suboss87/fdeops --skill <name>`, replacing `<name>` with its catalog name. See [installation](install.md#individual-skills-and-the-full-pack) for the full pack and host-specific invocation.', '',
17
+ 'Customer records live at `~/fde-engagements/<customer>/.fde/`. A skill provides instructions, not customer credentials or infrastructure. Drafting from supplied notes does not need a customer record. Viewing records does; staging or saving requires the intended customer and applicable confirmation.', '']
18
+ for (const group of [...new Set(items.map(item => item.group))]) {
19
+ out.push(`## ${group}`, '', '| Skill | Use it when | Result | Input needed |', '|---|---|---|---|')
20
+ for (const item of items.filter(item => item.group === group)) {
21
+ out.push(`| [${item.name}](../skills/${item.name}/SKILL.md) | ${cell(item.description)} | ${cell(item.result)} | ${inputs[item.inputMode]} |`)
22
+ }
23
+ out.push('')
24
+ }
25
+ out.push('## Domain guidance', '', 'The skills can apply supporting guidance for AI systems, financial services, healthcare, government work and customer-facing artifacts when relevant. These references are included instructions, not additional installable skills or a substitute for the responsible specialists.', '', '[Starting examples](skills.md) · [Customer records](schema.md) · [Verification and limits](verification.md)', '')
26
+ return out.join('\n')
27
+ }
28
+ function checkCatalog(base = root) {
29
+ const file = path.join(base, 'docs/skills-reference.md')
30
+ if (fs.readFileSync(file, 'utf8') !== renderCatalog()) throw new Error('Public skill catalog is stale; run npm run generate:skills')
31
+ const readme = fs.readFileSync(path.join(base, 'README.md'), 'utf8')
32
+ if (!readme.includes(`**${catalog.length} task skills + one coordinator, \`fde\`**`)) throw new Error('README skill count differs from the catalog')
33
+ }
34
+ module.exports = { renderCatalog, checkCatalog }
35
+ if (require.main === module) {
36
+ if (process.argv.includes('--check')) checkCatalog()
37
+ else fs.writeFileSync(path.join(root, 'docs/skills-reference.md'), renderCatalog())
38
+ }
package/bin/check.js CHANGED
@@ -115,9 +115,8 @@ for (const refFile of mentioned) {
115
115
  }
116
116
  ok(`router dispatch (${mentioned.length} reference targets verified) + memory contract`)
117
117
 
118
- // Public claims must match the router. The docs advertise a method count and a
119
- // per-domain list; both drifted from SKILL.md once (ingest / connect
120
- // routed but undocumented), and a number nobody can verify is worse than none.
118
+ // Public names, routed instructions, installation entries and generated docs
119
+ // must agree. A task must never be advertised without a usable package.
121
120
  {
122
121
  // Every routing row must parse. A row this misses is a method that could go
123
122
  // undocumented for free, so an unparsed row is a hard failure, not a silent skip.
@@ -150,55 +149,23 @@ ok(`router dispatch (${mentioned.length} reference targets verified) + memory co
150
149
  fail(`check.js cannot read the method name in a SKILL.md routing row: ${line.trim().slice(0, 80)}`)
151
150
  continue
152
151
  }
152
+ const entry = catalog.find(item => item.name === method)
153
+ const target = (line.match(/references\/([a-z0-9-]+)\.md/) || [])[1]
154
+ if (entry && entry.method !== target) fail(`Router points ${method} at ${target}, expected ${entry.method}`)
153
155
  routed.add(method)
154
156
  }
155
157
  if (!routed.size) fail('check.js could not parse the SKILL.md routing table')
156
158
 
157
- // docs/skills-reference.md is the canonical per-skill list: one row per
158
- // skill inside the six stage tables, ending at the Overlays section.
159
- const reference = read('docs/skills-reference.md')
160
- const documented = new Set()
161
- let documentedRows = 0
162
- for (const line of reference.split('### Overlays')[0].split('\n')) {
163
- const m = line.match(/^\|\s*\[([a-z0-9-]+)\]\(\.\.\/skills\/fde\/references\/([a-z0-9-]+\.md)\)/)
164
- if (!m) continue
165
- documentedRows++
166
- documented.add(m[1])
167
- // A link nobody followed is the same unverifiable claim this gate exists for:
168
- // the target must exist, and it must be the skill the text names.
169
- if (m[2] !== `${m[1]}.md`) {
170
- fail(`docs/skills-reference.md links [${m[1]}] at references/${m[2]}`)
171
- } else if (!fs.existsSync(path.join(root, 'skills', 'fde', 'references', m[2]))) {
172
- fail(`docs/skills-reference.md links references/${m[2]}, which does not exist`)
173
- }
174
- }
175
- if (documented.size !== documentedRows) {
176
- fail(`docs/skills-reference.md lists ${documentedRows} skill rows for ${documented.size} skills - a duplicate row inflates the count`)
177
- }
178
- const undocumented = [...routed].filter(name => !documented.has(name))
179
- if (undocumented.length) {
180
- fail(`SKILL.md routes skill(s) missing from docs/skills-reference.md: ${undocumented.join(', ')}`)
181
- }
182
- // and the other direction: a documented skill nothing routes to is a skill
183
- // the agent can never reach, advertised anyway.
184
- const unrouted = [...documented].filter(name => !routed.has(name))
185
- if (unrouted.length) {
186
- fail(`docs/skills-reference.md documents skill(s) SKILL.md never routes to: ${unrouted.join(', ')}`)
187
- }
188
- for (const rel of ['docs/skills.md', 'docs/skills-reference.md']) {
189
- const body = read(rel)
190
- // `-` is a word boundary, so \bscore\b matches inside `score-use-cases`:
191
- // a skill could disappear from the docs behind a hyphenated sibling.
192
- const absent = [...documented].filter(name => !new RegExp(`(?<![\\w-])${name}(?![\\w-])`).test(body))
193
- if (absent.length) fail(`${rel} does not list skill(s): ${absent.join(', ')}`)
194
- const claims = [...body.matchAll(/(\d+)\s+workflows/g)].map(m => Number(m[1]))
195
- if (!claims.length) fail(`${rel} must state how many workflows it documents`)
196
- const wrong = [...new Set(claims.filter(n => n !== documented.size))]
197
- if (wrong.length) {
198
- fail(`${rel} claims ${wrong.join('/')} skills; ${documented.size} are documented`)
199
- }
159
+ // Every routed task is installable and every public entry is reachable.
160
+ const names = new Set(catalog.map(item => item.name))
161
+ for (const name of routed) if (!names.has(name)) fail(`Routed task has no installable skill: ${name}`)
162
+ for (const item of catalog) {
163
+ if (!routed.has(item.name)) fail(`Installable skill has no coordinator route: ${item.name}`)
164
+ if (!router.includes(`references/${item.method}.md`)) fail(`Missing canonical instruction for ${item.name}`)
200
165
  }
201
- ok(`public skill count is verifiable (${documented.size} documented, ${routed.size} routed)`)
166
+ if (names.size !== catalog.length || new Set(catalog.map(item => item.method)).size !== catalog.length) fail('Duplicate public skill name or method')
167
+ try { require('./catalog-doc').checkCatalog(); ok('Public catalog matches installable skills') }
168
+ catch (error) { fail(error.message) }
202
169
 
203
170
  const refDir = path.join(root, 'skills', 'fde', 'references')
204
171
  const extra = fs.readdirSync(refDir).filter(f => f.endsWith('.md') && !mentioned.includes(f))
@@ -560,10 +527,14 @@ if (plugin.commands !== './.claude/commands' || plugin.skills !== './skills') {
560
527
  } else {
561
528
  for (const cmd of ['brief', 'discover', 'plan', 'ship', 'outcome', 'close', 'debrief', 'prep', 'trust', 'receipts', 'readout']) {
562
529
  const rel = `.claude/commands/${cmd}.md`
563
- if (!fs.existsSync(path.join(root, rel))) fail(`${rel} missing`)
530
+ const task = catalog.find(item => item.name === cmd)
531
+ if (task) {
532
+ if (!fs.existsSync(path.join(root, 'skills', cmd, 'SKILL.md'))) fail(`Missing command skill: ${cmd}`)
533
+ if (fs.existsSync(path.join(root, rel))) fail(`Duplicate command and task skill: ${cmd}`)
534
+ } else if (!fs.existsSync(path.join(root, rel))) fail(`${rel} missing`)
564
535
  else if (!read(rel).includes('@fde')) fail(`${rel} must load @fde`)
565
536
  }
566
- ok('slash commands load @fde')
537
+ ok('Task commands have one entry; legacy engagement shortcuts load @fde')
567
538
  }
568
539
 
569
540
  if (!fs.existsSync(path.join(root, 'mcp', 'fdeops-ingest', 'server.js'))) {
package/bin/fde.js CHANGED
@@ -569,8 +569,8 @@ function withFileLock(targetPath, fn, opts = {}) {
569
569
  console.error(msg)
570
570
  process.exit(1)
571
571
  }
572
- const waitUntil = Date.now() + 20
573
- while (Date.now() < waitUntil) { /* spin */ }
572
+ // This CLI is synchronous; yield CPU while the other writer finishes.
573
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 20)
574
574
  continue
575
575
  }
576
576
  if (opts.soft) throw e
@@ -31,8 +31,16 @@ function referencesFor(method, referenceRoot = source) {
31
31
  }
32
32
  return [...found].sort()
33
33
  }
34
+ const inputGuidance = {
35
+ context: 'Work directly from the supplied permitted context. Standalone work does not require an engagement folder or initialization. Record filenames in the method are optional persistence destinations when no engagement is bound.',
36
+ records: 'This task operates on existing engagement records. Use the local CLI and permitted sanitized packets; do not invent a portfolio or initialize records merely to complete the task. Report missing records or access as a limitation.',
37
+ source: 'Source configuration and capability checks do not require an engagement record. Use available host tools and source documentation. Any later record staging or application follows the ingest method and its binding and confirmation requirements.',
38
+ 'record-write': 'Use permitted supplied material or available source tools to prepare a sourced proposal without requiring an engagement record. CLI staging and reconciliation use a bound engagement; applying updates requires the bound record and confirmation. Do not claim an unbound draft has been saved to engagement memory.',
39
+ }
34
40
  function entrypoint(item) {
35
- return `---\nname: ${item.name}\ndescription: ${item.description}\n---\n\n# ${item.name}\n\n<!-- Generated by bin/generate-skills.js; edit the canonical references and catalog. -->\n\n## Purpose\n\n${item.description}\n\nRead [the task context contract](references/task-context.md), then [the method](references/${item.method}.md). Load further references only when the task needs them. Everything linked is included in this skill; no other skill pack is required.\n\n## Principles\n\n- Work directly from the supplied permitted context. Standalone work does not require an engagement folder or initialization. Record filenames in the method are optional persistence destinations when no engagement is bound.\n- If called by @fde, reuse its current sanitized packet and scope. Do not restart setup, discovery or questions already answered.\n- The task context contract controls persistence and authority in both modes. Preserve unknowns and distinguish implementation, verification, deployment and acceptance.\n- Use the customer's repository instructions and available tools. Report a missing capability or unrun check honestly; do not claim that installing a skill provisions infrastructure.\n`
41
+ const mode = item.inputMode || 'context'
42
+ if (!Object.hasOwn(inputGuidance, mode)) throw new Error(`Invalid input mode: ${mode}`)
43
+ return `---\nname: ${item.name}\ndescription: ${item.description}\n---\n\n# ${item.name}\n\n<!-- Generated by bin/generate-skills.js; edit the canonical references and catalog. -->\n\n## Purpose\n\n${item.description}\n\nRead [the task context contract](references/task-context.md), then [the method](references/${item.method}.md). Load further references only when the task needs them. Everything linked is included in this skill; no other skill pack is required.\n\n## Principles\n\n- ${inputGuidance[mode]}\n- If called by @fde, reuse its current sanitized packet and scope. Do not restart setup, discovery or questions already answered.\n- The task context contract controls persistence and authority in both modes. Preserve unknowns and distinguish implementation, verification, deployment and acceptance.\n- Use the customer's repository instructions and available tools. Report a missing capability or unrun check honestly; do not claim that installing a skill provisions infrastructure.\n`
36
44
  }
37
45
  function expectedFiles(item, referenceRoot = source) {
38
46
  const files = new Map([['SKILL.md', entrypoint(item)]])
package/bin/install.js CHANGED
@@ -11,7 +11,12 @@ const CLAUDE_MD_SRC = path.join(__dirname, '..', 'CLAUDE.md.template')
11
11
  const FDE_TEMPLATES_SRC = path.join(__dirname, '..', 'templates', '.fde')
12
12
  const ADAPTERS_SRC = path.join(__dirname, '..', 'adapters')
13
13
  const TASK_NAMES = new Set(require('./skill-catalog').map(item => item.name))
14
- const RENAMED_SKILLS = new Set([...TASK_NAMES].map(name => `fde-${name}`))
14
+ // Only these published task packages changed names. New catalog entries must
15
+ // not acquire historical migration authority over unrelated prefixed skills.
16
+ const RENAMED_SKILLS = new Set([
17
+ 'discover', 'scope', 'options', 'poc', 'build', 'integrate', 'debug',
18
+ 'review', 'evaluate', 'qa', 'ship', 'readout', 'handoff', 'feedback',
19
+ ].map(name => `fde-${name}`))
15
20
  const LIB_SRC = path.join(__dirname, 'lib')
16
21
 
17
22
  const GLOBAL_SKILLS_DIR = path.join(os.homedir(), '.claude', 'skills')
@@ -135,8 +140,8 @@ function removeLegacySkills(opts = {}) {
135
140
  // Keep edits and additions outside the discovery directory, without guessing which
136
141
  // individual files are personal. Unmarked third-party installs require manual cleanup.
137
142
  function archiveRenamedSkill(name) {
138
- if (!TASK_NAMES.has(name)) return
139
143
  const oldName = `fde-${name}`
144
+ if (!RENAMED_SKILLS.has(oldName)) return
140
145
  const old = path.join(GLOBAL_SKILLS_DIR, oldName)
141
146
  checkPath(old)
142
147
  if (!fs.existsSync(old)) return
@@ -163,7 +168,8 @@ function installSkillDirs(opts = {}) {
163
168
  for (const entry of fs.readdirSync(SKILLS_SRC, { withFileTypes: true })) {
164
169
  const src = path.join(SKILLS_SRC, entry.name)
165
170
  const dest = path.join(GLOBAL_SKILLS_DIR, entry.name)
166
- if (!entry.isDirectory()) { copyFile(src, dest); continue }
171
+ // Repository-level documentation is not an installable skill.
172
+ if (!entry.isDirectory()) continue
167
173
  if (isLink(dest)) { links.push(entry.name); continue }
168
174
  try {
169
175
  checkTree(src, dest)
@@ -1,17 +1,284 @@
1
- // Public entry points. Methods remain authored once in skills/fde/references/.
1
+ // One public task catalog. Methods remain authored once in skills/fde/references/.
2
+ // inputMode distinguishes supplied-context tasks from operations that use engagement records.
2
3
  module.exports = [
3
- ['discover', 'discover', 'Trace a customer workflow and identify the problem, baseline and evidence gaps. Use for discovery or an unclear customer brief, before choosing a solution.'],
4
- ['scope', 'hold-scope', 'Assess a new customer request against agreed scope, trade-offs and ownership. Use when an engagement expands or a custom feature needs a commitment decision.'],
5
- ['options', 'three-options', 'Compare feasible approaches to a customer problem and recommend a path with costs, constraints and evidence. Use for an architecture or delivery decision, not implementation.'],
6
- ['poc', 'poc', 'Run a bounded customer proof of concept to test a consequential uncertainty. Use for a spike or pilot with a question and decision deadline, not a full rollout.'],
7
- ['build', 'build', 'Implement a scoped customer-facing software change in the existing repository and verify its behavior. Use for delivery work with an understood outcome, not incident response.'],
8
- ['integrate', 'integrate', 'Build or change a customer-system integration with explicit data mapping, permissions, retries and reconciliation. Use for connectors, imports, write-back and upstream APIs.'],
9
- ['debug', 'debug', 'Investigate and repair a reproducible failure in a customer integration or application. Use for diagnosis and regression prevention; follow incident authority for live mitigation.'],
10
- ['review', 'review', 'Review a proposed customer code change against its intended outcome and operational risks. Use for a diff or PR review; report evidence and actionable findings.'],
11
- ['evaluate', 'eval-pack', 'Evaluate an AI workflow against representative cases and its permitted actions. Use for model, retrieval or agent evaluation; tests do not grant release authority.'],
12
- ['qa', 'qa', 'Exercise the delivered customer journey using real runtime or browser evidence. Use for functional acceptance testing after implementation, including failure paths.'],
13
- ['ship', 'ship', 'Prepare or execute an authorized controlled release with verified checks, recovery and an operating owner. Use when a customer increment is ready for deployment.'],
14
- ['readout', 'readout', 'Prepare a sponsor update separating promised outcomes, measured results and customer acceptance. Use for progress readouts or defending a delivery claim.'],
15
- ['handoff', 'close', 'Transfer operation of a customer deployment with ownership, evidence and a tested support path. Use for handoff or an engineer rotation, not merely code delivery.'],
16
- ['feedback', 'encode-pattern', 'Assess a field lesson for reuse or product feedback without exposing customer context. Use for recurring deployment lessons; distinguish a hypothesis from a validated pattern.'],
17
- ].map(([name, method, description]) => ({ name, method, description }))
4
+ {
5
+ "name": "brief",
6
+ "method": "land",
7
+ "group": "Start",
8
+ "result": "A grounded brief with success criteria and open questions.",
9
+ "description": "Clarify a new customer brief, desired outcome, constraints and evidence gaps. Use for kickoff or a first meeting; do not repeat discovery already supplied.",
10
+ "inputMode": "context"
11
+ },
12
+ {
13
+ "name": "audit",
14
+ "method": "audit",
15
+ "group": "Start",
16
+ "result": "An audit of inherited claims and takeover risks.",
17
+ "description": "Audit an inherited engagement or implementation against its evidence. Use when taking over work or joining mid-project; distinguish verified facts from inherited claims.",
18
+ "inputMode": "context"
19
+ },
20
+ {
21
+ "name": "who-decides",
22
+ "method": "who-decides",
23
+ "group": "Start",
24
+ "result": "A stakeholder map with decision rights and unknowns.",
25
+ "description": "Map stakeholders, decision rights, influence and blockers from supplied evidence. Use when ownership is unclear or the stakeholder landscape changes.",
26
+ "inputMode": "context"
27
+ },
28
+ {
29
+ "name": "earn-trust",
30
+ "method": "earn-trust",
31
+ "group": "Start",
32
+ "result": "A plan for access, credibility and permitted AI use.",
33
+ "description": "Plan how to earn customer trust and appropriate access. Use when credibility, permissions or AI policy constrain the engagement.",
34
+ "inputMode": "context"
35
+ },
36
+ {
37
+ "name": "discover",
38
+ "method": "discover",
39
+ "description": "Trace a customer workflow and identify the problem, baseline and evidence gaps. Use for discovery or an unclear customer brief, before choosing a solution.",
40
+ "group": "Discover",
41
+ "result": "A workflow diagnosis with baseline and evidence gaps.",
42
+ "inputMode": "context"
43
+ },
44
+ {
45
+ "name": "test-assumptions",
46
+ "method": "test-assumptions",
47
+ "group": "Discover",
48
+ "result": "A ranked set of assumptions and ways to test them.",
49
+ "description": "Challenge a proposed solution by identifying and testing consequential assumptions. Use when the brief feels too certain or discovery reveals contradictions.",
50
+ "inputMode": "context"
51
+ },
52
+ {
53
+ "name": "score-use-cases",
54
+ "method": "score-use-cases",
55
+ "group": "Discover",
56
+ "result": "A ranked use-case shortlist with evidence and trade-offs.",
57
+ "description": "Compare competing customer use cases by value, feasibility and evidence. Use when several problems compete for delivery capacity.",
58
+ "inputMode": "context"
59
+ },
60
+ {
61
+ "name": "poc",
62
+ "method": "poc",
63
+ "description": "Run a bounded customer proof of concept to test a consequential uncertainty. Use for a spike or pilot with a question and decision deadline, not a full rollout.",
64
+ "group": "Discover",
65
+ "result": "A bounded experiment with evidence and a decision.",
66
+ "inputMode": "context"
67
+ },
68
+ {
69
+ "name": "scope",
70
+ "method": "hold-scope",
71
+ "description": "Assess a new customer request against agreed scope, trade-offs and ownership. Use when an engagement expands or a custom feature needs a commitment decision.",
72
+ "group": "Plan",
73
+ "result": "A scope decision with trade-offs and ownership.",
74
+ "inputMode": "context"
75
+ },
76
+ {
77
+ "name": "options",
78
+ "method": "three-options",
79
+ "description": "Compare feasible approaches to a customer problem and recommend a path with costs, constraints and evidence. Use for an architecture or delivery decision, not implementation.",
80
+ "group": "Plan",
81
+ "result": "Compared approaches and an evidence-backed recommendation.",
82
+ "inputMode": "context"
83
+ },
84
+ {
85
+ "name": "plan",
86
+ "method": "plan",
87
+ "group": "Plan",
88
+ "result": "A sequenced delivery plan with owners and acceptance checks.",
89
+ "description": "Sequence an understood outcome into verifiable delivery slices with dependencies, ownership and acceptance checks. Use for delivery planning, estimation or migration strategy.",
90
+ "inputMode": "context"
91
+ },
92
+ {
93
+ "name": "business-case",
94
+ "method": "business-case",
95
+ "group": "Plan",
96
+ "result": "An evidence-backed investment case with explicit assumptions.",
97
+ "description": "Develop a business case for an initiative using costs, benefits, risks and evidence. Use when a sponsor needs budget or timeline justification.",
98
+ "inputMode": "context"
99
+ },
100
+ {
101
+ "name": "prioritize",
102
+ "method": "pick-three",
103
+ "group": "Plan",
104
+ "result": "Three immediate priorities and explicit deferrals.",
105
+ "description": "Choose up to three immediate priorities from competing initiatives. Use when everything is urgent and the customer needs a defensible order with explicit deferrals.",
106
+ "inputMode": "context"
107
+ },
108
+ {
109
+ "name": "red-team",
110
+ "method": "red-team",
111
+ "group": "Plan",
112
+ "result": "A critique of weak claims, failure modes and corrective actions.",
113
+ "description": "Stress-test a plan, brief or delivery claim against evidence and plausible failure modes. Use when the user asks for a red team or preparation for a consequential decision.",
114
+ "inputMode": "context"
115
+ },
116
+ {
117
+ "name": "build",
118
+ "method": "build",
119
+ "description": "Implement a scoped customer-facing software change in the existing repository and verify its behavior. Use for delivery work with an understood outcome, not incident response.",
120
+ "group": "Build and verify",
121
+ "result": "An implemented change with verification evidence.",
122
+ "inputMode": "context"
123
+ },
124
+ {
125
+ "name": "integrate",
126
+ "method": "integrate",
127
+ "description": "Build or change a customer-system integration with explicit data mapping, permissions, retries and reconciliation. Use for connectors, imports, write-back and upstream APIs.",
128
+ "group": "Build and verify",
129
+ "result": "An integration with tested mapping and failure handling.",
130
+ "inputMode": "context"
131
+ },
132
+ {
133
+ "name": "debug",
134
+ "method": "debug",
135
+ "description": "Investigate and repair a reproducible failure in a customer integration or application. Use for diagnosis and regression prevention; follow incident authority for live mitigation.",
136
+ "group": "Build and verify",
137
+ "result": "A diagnosed failure, repair and regression evidence.",
138
+ "inputMode": "context"
139
+ },
140
+ {
141
+ "name": "review",
142
+ "method": "review",
143
+ "description": "Review a proposed customer code change against its intended outcome and operational risks. Use for a diff or PR review; report evidence and actionable findings.",
144
+ "group": "Build and verify",
145
+ "result": "Actionable findings tied to the intended outcome.",
146
+ "inputMode": "context"
147
+ },
148
+ {
149
+ "name": "evaluate",
150
+ "method": "eval-pack",
151
+ "description": "Evaluate an AI workflow against representative cases and its permitted actions. Use for model, retrieval or agent evaluation; tests do not grant release authority.",
152
+ "group": "Build and verify",
153
+ "result": "Evaluation results, failure analysis and release evidence.",
154
+ "inputMode": "context"
155
+ },
156
+ {
157
+ "name": "qa",
158
+ "method": "qa",
159
+ "description": "Exercise the delivered customer journey using real runtime or browser evidence. Use for functional acceptance testing after implementation, including failure paths.",
160
+ "group": "Build and verify",
161
+ "result": "Customer-journey evidence and acceptance gaps.",
162
+ "inputMode": "context"
163
+ },
164
+ {
165
+ "name": "what-breaks",
166
+ "method": "what-breaks",
167
+ "group": "Build and verify",
168
+ "result": "A blast-radius assessment and mitigation plan.",
169
+ "description": "Assess the impact of a proposed change on dependencies and shared infrastructure. Use before touching unfamiliar or consequential systems.",
170
+ "inputMode": "context"
171
+ },
172
+ {
173
+ "name": "rollback",
174
+ "method": "rollback",
175
+ "group": "Build and verify",
176
+ "result": "A rollback drill with recovery evidence and remaining gaps.",
177
+ "description": "Prepare and rehearse a recovery path for an intended release. Use when rollback is assumed, untested or previously failed; follow the environment authority for any drill.",
178
+ "inputMode": "context"
179
+ },
180
+ {
181
+ "name": "ship",
182
+ "method": "ship",
183
+ "description": "Prepare or execute an authorized controlled release with verified checks, recovery and an operating owner. Use when a customer increment is ready for deployment.",
184
+ "group": "Build and verify",
185
+ "result": "A controlled release result with recovery and ownership.",
186
+ "inputMode": "context"
187
+ },
188
+ {
189
+ "name": "readout",
190
+ "method": "readout",
191
+ "description": "Prepare a sponsor update separating promised outcomes, measured results and customer acceptance. Use for progress readouts or defending a delivery claim.",
192
+ "group": "Report",
193
+ "result": "A sponsor update separating promises, results and acceptance.",
194
+ "inputMode": "context"
195
+ },
196
+ {
197
+ "name": "demo-prep",
198
+ "method": "demo-prep",
199
+ "group": "Report",
200
+ "result": "A demo narrative, rehearsal plan and failure fallback.",
201
+ "description": "Prepare a customer demo or executive walkthrough around an evidenced outcome. Use before show-and-tell to rehearse the journey and prepare a fallback.",
202
+ "inputMode": "context"
203
+ },
204
+ {
205
+ "name": "debrief",
206
+ "method": "debrief",
207
+ "group": "Report",
208
+ "result": "A sourced meeting summary with decisions and next actions.",
209
+ "description": "Turn meeting notes or a transcript into sourced decisions, changes and next actions. Use after a customer conversation; review consequential record updates before saving.",
210
+ "inputMode": "context"
211
+ },
212
+ {
213
+ "name": "board-memo",
214
+ "method": "board-memo",
215
+ "group": "Report",
216
+ "result": "An executive memo separating evidence, risk and decisions.",
217
+ "description": "Draft a board or executive summary of an engagement using outcomes, risks and investment decisions. Use when the sponsor needs to brief senior leadership.",
218
+ "inputMode": "context"
219
+ },
220
+ {
221
+ "name": "rescue",
222
+ "method": "rescue",
223
+ "group": "Operate",
224
+ "result": "A recovery plan and evidence of authorized mitigation.",
225
+ "description": "Triage an outage, loss of stakeholder trust or a failing engagement direction. Use for urgent recovery; distinguish diagnosis from authorized production mitigation.",
226
+ "inputMode": "context"
227
+ },
228
+ {
229
+ "name": "dashboard",
230
+ "method": "dashboard",
231
+ "group": "Operate",
232
+ "result": "A portfolio view of engagement status and attention needed.",
233
+ "description": "Review the portfolio across existing engagement records. Use for status across customers; requires accessible permitted records and does not create missing client histories.",
234
+ "inputMode": "records"
235
+ },
236
+ {
237
+ "name": "switch-clients",
238
+ "method": "switch-clients",
239
+ "group": "Operate",
240
+ "result": "A refreshed client binding and cross-client triage.",
241
+ "description": "Switch between existing customer engagements and triage competing needs. Use when context switching causes confusion; requires engagement records and preserves one client per write.",
242
+ "inputMode": "records"
243
+ },
244
+ {
245
+ "name": "runbook",
246
+ "method": "runbook",
247
+ "group": "Operate",
248
+ "result": "An operating runbook with recovery steps and ownership.",
249
+ "description": "Write an operating runbook from the delivered system and verified procedures. Use when the customer team or a successor needs to operate without the original engineer.",
250
+ "inputMode": "context"
251
+ },
252
+ {
253
+ "name": "handoff",
254
+ "method": "close",
255
+ "description": "Transfer operation of a customer deployment with ownership, evidence and a tested support path. Use for handoff or an engineer rotation, not merely code delivery.",
256
+ "group": "Operate",
257
+ "result": "An operating handoff with ownership and a support path.",
258
+ "inputMode": "context"
259
+ },
260
+ {
261
+ "name": "feedback",
262
+ "method": "encode-pattern",
263
+ "description": "Assess a field lesson for reuse or product feedback without exposing customer context. Use for recurring deployment lessons; distinguish a hypothesis from a validated pattern.",
264
+ "group": "Operate",
265
+ "result": "A reusable field lesson with evidence and privacy boundaries.",
266
+ "inputMode": "context"
267
+ },
268
+ {
269
+ "name": "connect",
270
+ "method": "connect",
271
+ "group": "Operate",
272
+ "result": "Source setup guidance and an honest capability check.",
273
+ "description": "Configure or diagnose access to a requested source using available host tools. Use for source MCP setup; source configuration needs no engagement record and credentials stay with the host.",
274
+ "inputMode": "source"
275
+ },
276
+ {
277
+ "name": "ingest",
278
+ "method": "ingest",
279
+ "group": "Operate",
280
+ "result": "Sourced proposed updates, with confirmed record application when bound.",
281
+ "description": "Fetch requested source material and prepare sourced engagement updates. Use to catch up from external notes or messages; applying updates requires a bound record and confirmation.",
282
+ "inputMode": "record-write"
283
+ }
284
+ ]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fdeops-ingest-mcp",
3
- "version": "5.0.0",
3
+ "version": "5.1.0",
4
4
  "private": true,
5
5
  "description": "Thin stdio MCP sink for FDEOps ingest (stage \u2192 propose \u2192 apply). Zero runtime dependencies.",
6
6
  "bin": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fdeops",
3
- "version": "5.0.0",
3
+ "version": "5.1.0",
4
4
  "description": "Forward deployed engineering skills for AI coding agents. Use focused task skills or @fde for discovery, implementation, verification and handoff, with local engagement records.",
5
5
  "bin": {
6
6
  "fdeops": "bin/install.js",
@@ -11,7 +11,7 @@
11
11
  "test": "node --test test/*.test.js",
12
12
  "test:skill-routing": "node evals/skill-routing/check.js && node evals/skill-routing/live-smoke.js",
13
13
  "prepublishOnly": "node bin/check.js && npm test",
14
- "generate:skills": "node bin/generate-skills.js"
14
+ "generate:skills": "node bin/generate-skills.js && node bin/catalog-doc.js"
15
15
  },
16
16
  "files": [
17
17
  "bin/",