fdeops 4.0.4 → 4.1.1
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/AGENTS.md +1 -1
- package/README.md +33 -6
- package/bin/check.js +14 -23
- package/bin/generate-skills.js +144 -0
- package/bin/install.js +2 -1
- package/bin/skill-catalog.js +17 -0
- package/mcp/fdeops-ingest/package.json +2 -2
- package/package.json +4 -3
- package/plugin.json +2 -2
- package/skills/fde/SKILL.md +18 -10
- package/skills/fde/references/board-memo.md +1 -1
- package/skills/fde/references/build.md +20 -0
- package/skills/fde/references/business-case.md +9 -7
- package/skills/fde/references/close.md +6 -4
- package/skills/fde/references/debug.md +18 -0
- package/skills/fde/references/encode-pattern.md +10 -8
- package/skills/fde/references/eval-pack.md +16 -33
- package/skills/fde/references/hold-scope.md +9 -7
- package/skills/fde/references/integrate.md +18 -0
- package/skills/fde/references/plan.md +4 -2
- package/skills/fde/references/poc.md +5 -3
- package/skills/fde/references/qa.md +18 -0
- package/skills/fde/references/readout.md +6 -4
- package/skills/fde/references/review.md +22 -60
- package/skills/fde/references/ship.md +42 -287
- package/skills/fde/references/task-context.md +12 -0
- package/skills/fde/references/test-assumptions.md +2 -2
- package/skills/fde/references/three-options.md +19 -27
- package/skills/fde/references/verification.md +31 -0
- package/skills/fde-build/.fde-generated.json +16 -0
- package/skills/fde-build/SKILL.md +21 -0
- package/skills/fde-build/references/build.md +20 -0
- package/skills/fde-build/references/debug.md +18 -0
- package/skills/fde-build/references/eval-pack.md +26 -0
- package/skills/fde-build/references/integrate.md +18 -0
- package/skills/fde-build/references/qa.md +18 -0
- package/skills/fde-build/references/review.md +39 -0
- package/skills/fde-build/references/ship.md +73 -0
- package/skills/fde-build/references/task-context.md +12 -0
- package/skills/fde-build/references/verification.md +31 -0
- package/skills/fde-debug/.fde-generated.json +16 -0
- package/skills/fde-debug/SKILL.md +21 -0
- package/skills/fde-debug/references/build.md +20 -0
- package/skills/fde-debug/references/debug.md +18 -0
- package/skills/fde-debug/references/eval-pack.md +26 -0
- package/skills/fde-debug/references/integrate.md +18 -0
- package/skills/fde-debug/references/qa.md +18 -0
- package/skills/fde-debug/references/review.md +39 -0
- package/skills/fde-debug/references/ship.md +73 -0
- package/skills/fde-debug/references/task-context.md +12 -0
- package/skills/fde-debug/references/verification.md +31 -0
- package/skills/fde-discover/.fde-generated.json +10 -0
- package/skills/fde-discover/SKILL.md +21 -0
- package/skills/fde-discover/references/audit.md +71 -0
- package/skills/fde-discover/references/discover.md +254 -0
- package/skills/fde-discover/references/task-context.md +12 -0
- package/skills/fde-evaluate/.fde-generated.json +16 -0
- package/skills/fde-evaluate/SKILL.md +21 -0
- package/skills/fde-evaluate/references/build.md +20 -0
- package/skills/fde-evaluate/references/debug.md +18 -0
- package/skills/fde-evaluate/references/eval-pack.md +26 -0
- package/skills/fde-evaluate/references/integrate.md +18 -0
- package/skills/fde-evaluate/references/qa.md +18 -0
- package/skills/fde-evaluate/references/review.md +39 -0
- package/skills/fde-evaluate/references/ship.md +73 -0
- package/skills/fde-evaluate/references/task-context.md +12 -0
- package/skills/fde-evaluate/references/verification.md +31 -0
- package/skills/fde-feedback/.fde-generated.json +9 -0
- package/skills/fde-feedback/SKILL.md +21 -0
- package/skills/fde-feedback/references/encode-pattern.md +96 -0
- package/skills/fde-feedback/references/task-context.md +12 -0
- package/skills/fde-handoff/.fde-generated.json +10 -0
- package/skills/fde-handoff/SKILL.md +21 -0
- package/skills/fde-handoff/references/close.md +66 -0
- package/skills/fde-handoff/references/encode-pattern.md +96 -0
- package/skills/fde-handoff/references/task-context.md +12 -0
- package/skills/fde-integrate/.fde-generated.json +16 -0
- package/skills/fde-integrate/SKILL.md +21 -0
- package/skills/fde-integrate/references/build.md +20 -0
- package/skills/fde-integrate/references/debug.md +18 -0
- package/skills/fde-integrate/references/eval-pack.md +26 -0
- package/skills/fde-integrate/references/integrate.md +18 -0
- package/skills/fde-integrate/references/qa.md +18 -0
- package/skills/fde-integrate/references/review.md +39 -0
- package/skills/fde-integrate/references/ship.md +73 -0
- package/skills/fde-integrate/references/task-context.md +12 -0
- package/skills/fde-integrate/references/verification.md +31 -0
- package/skills/fde-options/.fde-generated.json +11 -0
- package/skills/fde-options/SKILL.md +21 -0
- package/skills/fde-options/references/business-case.md +90 -0
- package/skills/fde-options/references/task-context.md +12 -0
- package/skills/fde-options/references/test-assumptions.md +102 -0
- package/skills/fde-options/references/three-options.md +90 -0
- package/skills/fde-poc/.fde-generated.json +23 -0
- package/skills/fde-poc/SKILL.md +21 -0
- package/skills/fde-poc/references/audit.md +71 -0
- package/skills/fde-poc/references/build.md +20 -0
- package/skills/fde-poc/references/business-case.md +90 -0
- package/skills/fde-poc/references/debug.md +18 -0
- package/skills/fde-poc/references/discover.md +254 -0
- package/skills/fde-poc/references/eval-pack.md +26 -0
- package/skills/fde-poc/references/integrate.md +18 -0
- package/skills/fde-poc/references/plan.md +167 -0
- package/skills/fde-poc/references/poc.md +55 -0
- package/skills/fde-poc/references/qa.md +18 -0
- package/skills/fde-poc/references/review.md +39 -0
- package/skills/fde-poc/references/ship.md +73 -0
- package/skills/fde-poc/references/task-context.md +12 -0
- package/skills/fde-poc/references/test-assumptions.md +102 -0
- package/skills/fde-poc/references/three-options.md +90 -0
- package/skills/fde-poc/references/verification.md +31 -0
- package/skills/fde-qa/.fde-generated.json +16 -0
- package/skills/fde-qa/SKILL.md +21 -0
- package/skills/fde-qa/references/build.md +20 -0
- package/skills/fde-qa/references/debug.md +18 -0
- package/skills/fde-qa/references/eval-pack.md +26 -0
- package/skills/fde-qa/references/integrate.md +18 -0
- package/skills/fde-qa/references/qa.md +18 -0
- package/skills/fde-qa/references/review.md +39 -0
- package/skills/fde-qa/references/ship.md +73 -0
- package/skills/fde-qa/references/task-context.md +12 -0
- package/skills/fde-qa/references/verification.md +31 -0
- package/skills/fde-readout/.fde-generated.json +11 -0
- package/skills/fde-readout/SKILL.md +21 -0
- package/skills/fde-readout/references/board-memo.md +108 -0
- package/skills/fde-readout/references/business-case.md +90 -0
- package/skills/fde-readout/references/readout.md +71 -0
- package/skills/fde-readout/references/task-context.md +12 -0
- package/skills/fde-review/.fde-generated.json +16 -0
- package/skills/fde-review/SKILL.md +21 -0
- package/skills/fde-review/references/build.md +20 -0
- package/skills/fde-review/references/debug.md +18 -0
- package/skills/fde-review/references/eval-pack.md +26 -0
- package/skills/fde-review/references/integrate.md +18 -0
- package/skills/fde-review/references/qa.md +18 -0
- package/skills/fde-review/references/review.md +39 -0
- package/skills/fde-review/references/ship.md +73 -0
- package/skills/fde-review/references/task-context.md +12 -0
- package/skills/fde-review/references/verification.md +31 -0
- package/skills/fde-scope/.fde-generated.json +9 -0
- package/skills/fde-scope/SKILL.md +21 -0
- package/skills/fde-scope/references/hold-scope.md +83 -0
- package/skills/fde-scope/references/task-context.md +12 -0
- package/skills/fde-ship/.fde-generated.json +16 -0
- package/skills/fde-ship/SKILL.md +21 -0
- package/skills/fde-ship/references/build.md +20 -0
- package/skills/fde-ship/references/debug.md +18 -0
- package/skills/fde-ship/references/eval-pack.md +26 -0
- package/skills/fde-ship/references/integrate.md +18 -0
- package/skills/fde-ship/references/qa.md +18 -0
- package/skills/fde-ship/references/review.md +39 -0
- package/skills/fde-ship/references/ship.md +73 -0
- package/skills/fde-ship/references/task-context.md +12 -0
- package/skills/fde-ship/references/verification.md +31 -0
package/AGENTS.md
CHANGED
|
@@ -8,7 +8,7 @@ Route via **`@fde`** - read `skills/fde/SKILL.md` (the single source of truth),
|
|
|
8
8
|
|
|
9
9
|
## If you are contributing to this repository
|
|
10
10
|
|
|
11
|
-
- **One brain.** Method lives once in `skills/fde/SKILL.md` + `skills/fde/references/`. Adapters in `adapters/` only point at it - never fork logic per platform.
|
|
11
|
+
- **One brain.** Method lives once in `skills/fde/SKILL.md` + `skills/fde/references/`. Adapters in `adapters/` only point at it - never fork logic per platform. Standalone skills are generated by `node bin/generate-skills.js` from `bin/skill-catalog.js` and canonical references; do not hand-edit generated copies.
|
|
12
12
|
- **Deterministic core.** `bin/fde.js` is local-only (git + file reads, no network, no AI). Keep it that way.
|
|
13
13
|
- **Run the checks.** `npm run check` must pass before any PR (`node bin/check.js`).
|
|
14
14
|
- **Conventions.** See `CONTRIBUTING.md`, `docs/REPO_LAYOUT.md`, and `docs/schema.md`.
|
package/README.md
CHANGED
|
@@ -4,18 +4,41 @@
|
|
|
4
4
|
|
|
5
5
|
<a name="why-use-it"></a>
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Take a customer request from discovery through implementation, verification and handoff. Use one task skill for the work in front of you, or `@fde` to coordinate the engagement and keep its decisions and evidence together.
|
|
8
8
|
|
|
9
9
|
Notes stay on your laptop, in a separate record for each client. Review the agent's proposed changes before saving them.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Implementation, integration, debugging and QA are included. Use your existing repository tools; no additional skill pack is required. Credentials, infrastructure and production authority still come from the customer.
|
|
12
12
|
|
|
13
|
-
[Quick start](#quick-start) · [Daily fieldbook](#your-daily-fieldbook) · [
|
|
13
|
+
[Quick start](#quick-start) · [Daily fieldbook](#your-daily-fieldbook) · [Task skills](#task-skills) · [Documentation](docs/README.md)
|
|
14
14
|
|
|
15
15
|
<img width="960" height="640" alt="FDEOps: client delivery from the first meeting to handover" src="https://github.com/user-attachments/assets/2bcb8739-55ee-445d-8a1a-8b38433b7b58" />
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
+
## Task skills
|
|
20
|
+
|
|
21
|
+
Call the task directly when you know what you need. No client folder is required for a one-off task.
|
|
22
|
+
|
|
23
|
+
| Work | Skill |
|
|
24
|
+
|------|-------|
|
|
25
|
+
| Understand the workflow | `fde-discover` |
|
|
26
|
+
| Handle a new scope request | `fde-scope` |
|
|
27
|
+
| Compare approaches | `fde-options` |
|
|
28
|
+
| Test a risky assumption | `fde-poc` |
|
|
29
|
+
| Implement, integrate, repair | `fde-build`, `fde-integrate`, `fde-debug` |
|
|
30
|
+
| Review, evaluate AI, test the journey | `fde-review`, `fde-evaluate`, `fde-qa` |
|
|
31
|
+
| Release a verified increment | `fde-ship` |
|
|
32
|
+
| Present evidence, transfer operation, reuse a lesson | `fde-readout`, `fde-handoff`, `fde-feedback` |
|
|
33
|
+
|
|
34
|
+
For example, install just the integration skill:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx skills add suboss87/fdeops --skill fde-integrate
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Ask it to connect a permitted customer API and test retry behavior. It includes the references it needs. `@fde` uses those same methods when the integration is part of an ongoing engagement. [Full pack and selective installation](docs/install.md#individual-skills-and-the-full-pack).
|
|
41
|
+
|
|
19
42
|
## Quick Start
|
|
20
43
|
|
|
21
44
|
**Try it in a local checkout.** Requires Node.js 18+ and Git:
|
|
@@ -138,9 +161,9 @@ You can also just say it: “Prep me for the sponsor meeting,” “What did we
|
|
|
138
161
|
|
|
139
162
|
---
|
|
140
163
|
|
|
141
|
-
##
|
|
164
|
+
## Engagement workflows
|
|
142
165
|
|
|
143
|
-
Thirty
|
|
166
|
+
Thirty-four workflows, grouped by stage. Each skill gives the agent steps to follow, a record or report to produce, and a checkpoint with you. You describe the work; `@fde` finds the skill.
|
|
144
167
|
|
|
145
168
|
Full detail: [docs/skills-reference.md](docs/skills-reference.md).
|
|
146
169
|
|
|
@@ -176,7 +199,11 @@ Full detail: [docs/skills-reference.md](docs/skills-reference.md).
|
|
|
176
199
|
|
|
177
200
|
| Skill | What it does | Use when |
|
|
178
201
|
|--------|--------------|----------|
|
|
179
|
-
| [
|
|
202
|
+
| [build](skills/fde/references/build.md) | Implement the increment | A scoped change in their repository |
|
|
203
|
+
| [integrate](skills/fde/references/integrate.md) | Prove the system boundary | APIs, imports and write-back |
|
|
204
|
+
| [debug](skills/fde/references/debug.md) | Reproduce and repair a failure | Unexpected behavior or a regression |
|
|
205
|
+
| [qa](skills/fde/references/qa.md) | Exercise the delivered journey | Functional acceptance or browser QA |
|
|
206
|
+
| [ship](skills/fde/references/ship.md) | Release with evidence | Ready for an authorized rollout |
|
|
180
207
|
| [what-breaks](skills/fde/references/what-breaks.md) | Assess impact | Touching shared infrastructure |
|
|
181
208
|
| [rescue](skills/fde/references/rescue.md) | Resolve the incident | Down, or they went quiet |
|
|
182
209
|
| [review](skills/fde/references/review.md) | Review the change | Before merge, scope creep |
|
package/bin/check.js
CHANGED
|
@@ -6,6 +6,7 @@ const fs = require('fs')
|
|
|
6
6
|
const path = require('path')
|
|
7
7
|
|
|
8
8
|
const root = path.join(__dirname, '..')
|
|
9
|
+
const catalog = require('./skill-catalog')
|
|
9
10
|
let failed = 0
|
|
10
11
|
|
|
11
12
|
function fail(msg) {
|
|
@@ -190,8 +191,8 @@ ok(`router dispatch (${mentioned.length} reference targets verified) + memory co
|
|
|
190
191
|
// a skill could disappear from the docs behind a hyphenated sibling.
|
|
191
192
|
const absent = [...documented].filter(name => !new RegExp(`(?<![\\w-])${name}(?![\\w-])`).test(body))
|
|
192
193
|
if (absent.length) fail(`${rel} does not list skill(s): ${absent.join(', ')}`)
|
|
193
|
-
const claims = [...body.matchAll(/(\d+)\s+
|
|
194
|
-
if (!claims.length) fail(`${rel} must state how many
|
|
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`)
|
|
195
196
|
const wrong = [...new Set(claims.filter(n => n !== documented.size))]
|
|
196
197
|
if (wrong.length) {
|
|
197
198
|
fail(`${rel} claims ${wrong.join('/')} skills; ${documented.size} are documented`)
|
|
@@ -204,20 +205,10 @@ ok(`router dispatch (${mentioned.length} reference targets verified) + memory co
|
|
|
204
205
|
if (extra.length) fail(`unrouted reference file(s) - dead skill: ${extra.join(', ')}`)
|
|
205
206
|
else ok('no unrouted reference files')
|
|
206
207
|
|
|
207
|
-
// The on-site change loop lives in ship.md. A sibling skill is a split.
|
|
208
|
-
for (const dead of ['small-prs.md', 'thin-slices.md', 'implement.md']) {
|
|
209
|
-
if (fs.existsSync(path.join(refDir, dead))) {
|
|
210
|
-
fail(`${dead} must not exist - that craft lives in ship.md`)
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
ok('ship is one skill (no implement / small-prs / thin-slices sibling)')
|
|
214
|
-
|
|
215
208
|
if (/^### Prove\b/m.test(read('skills/fde/SKILL.md'))) {
|
|
216
209
|
fail('SKILL.md must not use Prove as a stage heading - the public stage is Outcome')
|
|
217
210
|
} else ok('SKILL.md stage heading is Outcome')
|
|
218
|
-
|
|
219
|
-
fail('README must not advertise 31 skills')
|
|
220
|
-
} else ok('README skill count is 30')
|
|
211
|
+
|
|
221
212
|
}
|
|
222
213
|
|
|
223
214
|
const install = read('bin/install.js')
|
|
@@ -292,11 +283,11 @@ if (!readme.includes('fde-engagements') || !/fdeops.*resume --init/i.test(readme
|
|
|
292
283
|
// The advertised command must name the one skill a field user wants.
|
|
293
284
|
// Contributor CLI attack notes live in evals/testing-fieldbook.md, not as a skill.
|
|
294
285
|
for (const m of readme.match(/^.*npx skills add .*$/gm) || []) {
|
|
295
|
-
if (!
|
|
296
|
-
fail(`README skills-add command must
|
|
286
|
+
if (!['fde', ...catalog.map(s => s.name)].some(name => new RegExp(`--skill ${name}(?:\\s|$)`).test(m))) {
|
|
287
|
+
fail(`README skills-add command must name a shipped skill: ${m.trim()}`)
|
|
297
288
|
}
|
|
298
289
|
}
|
|
299
|
-
ok('README
|
|
290
|
+
ok('README skill install commands name a discoverable entry')
|
|
300
291
|
|
|
301
292
|
// A skill-only install has no fde on the PATH; the router must reach npx before
|
|
302
293
|
// falling back to writing memory by hand.
|
|
@@ -661,9 +652,10 @@ for (const entry of fs.readdirSync(path.join(root, 'skills'))) {
|
|
|
661
652
|
ok(`skill ${entry} discoverable`)
|
|
662
653
|
}
|
|
663
654
|
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
655
|
+
const expectedSkills = ['fde', ...catalog.map(s => s.name)].sort()
|
|
656
|
+
if (JSON.stringify(skillDirs.sort()) !== JSON.stringify(expectedSkills)) fail('Skill directories differ from catalog')
|
|
657
|
+
try { require('./generate-skills').generate(true); ok('generated standalone reference closure and freshness') }
|
|
658
|
+
catch (error) { fail(error.message) }
|
|
667
659
|
|
|
668
660
|
function findSkillMd(dir, acc = []) {
|
|
669
661
|
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
@@ -675,10 +667,9 @@ function findSkillMd(dir, acc = []) {
|
|
|
675
667
|
return acc
|
|
676
668
|
}
|
|
677
669
|
const skillFiles = findSkillMd(root)
|
|
678
|
-
const
|
|
679
|
-
if (skillFiles.
|
|
680
|
-
|
|
681
|
-
} else ok('one SKILL.md')
|
|
670
|
+
const allowedSkills = expectedSkills.map(name => path.join('skills', name, 'SKILL.md')).sort()
|
|
671
|
+
if (JSON.stringify(skillFiles.sort()) !== JSON.stringify(allowedSkills)) fail('Unexpected SKILL.md outside public catalog')
|
|
672
|
+
else ok('all skill entry points accounted for')
|
|
682
673
|
|
|
683
674
|
if (!fs.existsSync(path.join(root, '.github', 'ISSUE_TEMPLATE', 'bug_report.yml'))) {
|
|
684
675
|
fail('GitHub issue template missing')
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Generated packages are independent installations, not independently authored methods.
|
|
3
|
+
const fs = require('node:fs')
|
|
4
|
+
const path = require('node:path')
|
|
5
|
+
const { createHash } = require('node:crypto')
|
|
6
|
+
const catalog = require('./skill-catalog')
|
|
7
|
+
const root = path.resolve(__dirname, '..')
|
|
8
|
+
const source = path.join(root, 'skills/fde/references')
|
|
9
|
+
|
|
10
|
+
function referencesFor(method, referenceRoot = source) {
|
|
11
|
+
const known = new Set(fs.readdirSync(referenceRoot).filter(f => f.endsWith('.md')))
|
|
12
|
+
const pending = [`${method}.md`, 'task-context.md']
|
|
13
|
+
const found = new Set()
|
|
14
|
+
while (pending.length) {
|
|
15
|
+
const file = pending.pop()
|
|
16
|
+
if (found.has(file)) continue
|
|
17
|
+
if (!known.has(file)) throw new Error(`Missing canonical reference: ${file}`)
|
|
18
|
+
found.add(file)
|
|
19
|
+
const body = fs.readFileSync(path.join(referenceRoot, file), 'utf8')
|
|
20
|
+
// Includes plain/backticked method links in older references as well as Markdown links.
|
|
21
|
+
for (const match of body.matchAll(/(?<![\w-])([a-z][a-z-]*\.md)\b/g)) {
|
|
22
|
+
if (known.has(match[1]) && !found.has(match[1])) pending.push(match[1])
|
|
23
|
+
}
|
|
24
|
+
for (const match of body.matchAll(/\]\(([^)]+\.md)(?:#[^)]*)?\)/g)) {
|
|
25
|
+
if (/^(?:https?:|#)/.test(match[1])) continue
|
|
26
|
+
const target = path.resolve(referenceRoot, match[1])
|
|
27
|
+
if (path.dirname(target) !== referenceRoot || !known.has(path.basename(target))) {
|
|
28
|
+
throw new Error(`Nonportable instruction link in ${file}: ${match[1]}`)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return [...found].sort()
|
|
33
|
+
}
|
|
34
|
+
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`
|
|
36
|
+
}
|
|
37
|
+
function expectedFiles(item, referenceRoot = source) {
|
|
38
|
+
const files = new Map([['SKILL.md', entrypoint(item)]])
|
|
39
|
+
for (const ref of referencesFor(item.method, referenceRoot)) files.set(`references/${ref}`, fs.readFileSync(path.join(referenceRoot, ref), 'utf8'))
|
|
40
|
+
return files
|
|
41
|
+
}
|
|
42
|
+
const marker = '<!-- Generated by bin/generate-skills.js; edit the canonical references and catalog. -->'
|
|
43
|
+
const manifestName = '.fde-generated.json'
|
|
44
|
+
const digest = body => createHash('sha256').update(body).digest('hex')
|
|
45
|
+
const stat = file => {
|
|
46
|
+
try { return fs.lstatSync(file) } catch (error) { if (error.code === 'ENOENT') return null; throw error }
|
|
47
|
+
}
|
|
48
|
+
function walk(dir, prefix = '') {
|
|
49
|
+
const entries = []
|
|
50
|
+
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
51
|
+
const rel = prefix + e.name
|
|
52
|
+
if (e.isSymbolicLink() || (!e.isDirectory() && !e.isFile()) || (e.isFile() && fs.lstatSync(path.join(dir, e.name)).nlink > 1)) throw new Error(`Unsafe generated path: ${path.join(dir, e.name)}`)
|
|
53
|
+
if (e.isDirectory()) {
|
|
54
|
+
if (rel !== 'references') throw new Error(`Unowned generated directory: ${path.join(dir, e.name)}`)
|
|
55
|
+
entries.push(...walk(path.join(dir, e.name), rel + '/'))
|
|
56
|
+
} else entries.push(rel)
|
|
57
|
+
}
|
|
58
|
+
return entries
|
|
59
|
+
}
|
|
60
|
+
function generate(check = false, options = {}) {
|
|
61
|
+
const skillRoot = path.join(options.root || root, 'skills')
|
|
62
|
+
const referenceRoot = options.referenceRoot || source
|
|
63
|
+
const items = options.catalog || catalog
|
|
64
|
+
const wanted = new Map()
|
|
65
|
+
for (const item of items) {
|
|
66
|
+
if (!/^fde-[a-z-]+$/.test(item.name) || wanted.has(item.name)) throw new Error(`Invalid generated skill name: ${item.name}`)
|
|
67
|
+
wanted.set(item.name, expectedFiles(item, referenceRoot))
|
|
68
|
+
}
|
|
69
|
+
const rootStat = stat(skillRoot)
|
|
70
|
+
if (rootStat && (!rootStat.isDirectory() || rootStat.isSymbolicLink())) throw new Error(`Unsafe skills root: ${skillRoot}`)
|
|
71
|
+
const names = new Set([...wanted.keys(), ...(rootStat ? fs.readdirSync(skillRoot).filter(n => /^fde-[a-z-]+$/.test(n)) : [])])
|
|
72
|
+
const errors = []
|
|
73
|
+
const plans = []
|
|
74
|
+
for (const name of names) {
|
|
75
|
+
const dest = path.join(skillRoot, name)
|
|
76
|
+
const expected = wanted.get(name) || new Map()
|
|
77
|
+
const destStat = stat(dest)
|
|
78
|
+
let owned = {}
|
|
79
|
+
let actual = []
|
|
80
|
+
if (destStat) {
|
|
81
|
+
if (!destStat.isDirectory() || destStat.isSymbolicLink()) {
|
|
82
|
+
if (wanted.has(name)) throw new Error(`Unsafe generated path: ${dest}`)
|
|
83
|
+
continue
|
|
84
|
+
}
|
|
85
|
+
const entry = path.join(dest, 'SKILL.md')
|
|
86
|
+
const entryStat = stat(entry)
|
|
87
|
+
const isGenerated = entryStat && entryStat.isFile() && fs.readFileSync(entry, 'utf8').includes(marker)
|
|
88
|
+
if (!isGenerated) {
|
|
89
|
+
if (wanted.has(name) || stat(path.join(dest, manifestName))) throw new Error(`Unowned skill: ${name}`)
|
|
90
|
+
continue
|
|
91
|
+
}
|
|
92
|
+
actual = walk(dest)
|
|
93
|
+
if (actual.includes(manifestName)) {
|
|
94
|
+
const manifest = JSON.parse(fs.readFileSync(path.join(dest, manifestName), 'utf8'))
|
|
95
|
+
if (manifest.generator !== 'bin/generate-skills.js' || manifest.version !== 1 || !manifest.files || Array.isArray(manifest.files) || typeof manifest.files !== 'object') throw new Error(`Invalid ownership manifest: ${name}`)
|
|
96
|
+
owned = manifest.files
|
|
97
|
+
for (const [rel, hash] of Object.entries(owned)) {
|
|
98
|
+
if (!/^(?:SKILL\.md|references\/[a-z][a-z-]*\.md)$/.test(rel) || !/^[a-f0-9]{64}$/.test(hash)) throw new Error(`Invalid ownership entry: ${name}/${rel}`)
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
// Migrate 4.1.0 packages conservatively: only the marked entry and exact
|
|
102
|
+
// canonical copies are known to belong to the generator.
|
|
103
|
+
for (const rel of actual) {
|
|
104
|
+
const body = fs.readFileSync(path.join(dest, rel))
|
|
105
|
+
const canonical = path.join(referenceRoot, path.basename(rel))
|
|
106
|
+
if (rel === 'SKILL.md' || (/^references\/[a-z][a-z-]*\.md$/.test(rel) && stat(canonical)?.isFile() && body.equals(fs.readFileSync(canonical)))) owned[rel] = digest(body)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
for (const rel of actual.filter(rel => rel !== manifestName)) {
|
|
110
|
+
if (!Object.hasOwn(owned, rel)) throw new Error(`Unowned generated file: ${name}/${rel}`)
|
|
111
|
+
if (!expected.has(rel) && digest(fs.readFileSync(path.join(dest, rel))) !== owned[rel]) throw new Error(`Modified obsolete generated file: ${name}/${rel}`)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const output = new Map(expected)
|
|
115
|
+
if (wanted.has(name)) output.set(manifestName, JSON.stringify({ generator: 'bin/generate-skills.js', version: 1, files: Object.fromEntries([...expected].map(([rel, body]) => [rel, digest(body)])) }, null, 2) + '\n')
|
|
116
|
+
for (const rel of actual) if (!output.has(rel)) errors.push(`Obsolete generated file: ${name}/${rel}`)
|
|
117
|
+
for (const [rel, body] of output) {
|
|
118
|
+
if (!actual.includes(rel) || fs.readFileSync(path.join(dest, rel), 'utf8') !== body) errors.push(`Stale generated skill: ${name}/${rel}`)
|
|
119
|
+
}
|
|
120
|
+
plans.push({ dest, actual, output })
|
|
121
|
+
}
|
|
122
|
+
if (check) {
|
|
123
|
+
if (errors.length) throw new Error(errors.join('\n'))
|
|
124
|
+
return
|
|
125
|
+
}
|
|
126
|
+
// All ownership and path checks finish before any package is changed.
|
|
127
|
+
for (const { dest, actual, output } of plans) {
|
|
128
|
+
for (const rel of actual) if (!output.has(rel)) fs.unlinkSync(path.join(dest, rel))
|
|
129
|
+
for (const [rel, body] of output) {
|
|
130
|
+
fs.mkdirSync(path.dirname(path.join(dest, rel)), { recursive: true })
|
|
131
|
+
fs.writeFileSync(path.join(dest, rel), body)
|
|
132
|
+
}
|
|
133
|
+
if (!output.size) {
|
|
134
|
+
const refs = path.join(dest, 'references')
|
|
135
|
+
if (stat(refs)) fs.rmdirSync(refs)
|
|
136
|
+
fs.rmdirSync(dest)
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
module.exports = { referencesFor, expectedFiles, generate }
|
|
141
|
+
if (require.main === module) {
|
|
142
|
+
try { generate(process.argv.includes('--check')); console.log('Skill packages match canonical methods.') }
|
|
143
|
+
catch (error) { console.error(error.message); process.exitCode = 1 }
|
|
144
|
+
}
|
package/bin/install.js
CHANGED
|
@@ -100,7 +100,7 @@ function wasInstalledByUs(dir) {
|
|
|
100
100
|
} catch (_) { return false }
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
// v2
|
|
103
|
+
// Retire v2 entries only when the current pack does not ship their replacement.
|
|
104
104
|
// Leaving the old ones in place would route users to stale content.
|
|
105
105
|
const LEGACY_SKILL_DIRS = [
|
|
106
106
|
'fde-land', 'fde-discover', 'fde-audit', 'fde-rescue', 'fde-sketch',
|
|
@@ -115,6 +115,7 @@ function removeLegacySkills(opts = {}) {
|
|
|
115
115
|
const skipped = []
|
|
116
116
|
const links = []
|
|
117
117
|
for (const dir of LEGACY_SKILL_DIRS) {
|
|
118
|
+
if (fs.existsSync(path.join(SKILLS_SRC, dir, 'SKILL.md'))) continue
|
|
118
119
|
const p = path.join(GLOBAL_SKILLS_DIR, dir)
|
|
119
120
|
if (isLink(p)) { links.push(dir); continue }
|
|
120
121
|
if (!fs.existsSync(path.join(p, 'SKILL.md'))) continue
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Public entry points. Methods remain authored once in skills/fde/references/.
|
|
2
|
+
module.exports = [
|
|
3
|
+
['fde-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
|
+
['fde-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
|
+
['fde-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
|
+
['fde-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
|
+
['fde-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
|
+
['fde-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
|
+
['fde-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
|
+
['fde-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
|
+
['fde-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
|
+
['fde-qa', 'qa', 'Exercise the delivered customer journey using real runtime or browser evidence. Use for functional acceptance testing after implementation, including failure paths.'],
|
|
13
|
+
['fde-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
|
+
['fde-readout', 'readout', 'Prepare a sponsor update separating promised outcomes, measured results and customer acceptance. Use for progress readouts or defending a delivery claim.'],
|
|
15
|
+
['fde-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
|
+
['fde-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 }))
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fdeops-ingest-mcp",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.1",
|
|
4
4
|
"private": true,
|
|
5
|
-
"description": "Thin stdio MCP sink for FDEOps ingest (stage
|
|
5
|
+
"description": "Thin stdio MCP sink for FDEOps ingest (stage \u2192 propose \u2192 apply). Zero runtime dependencies.",
|
|
6
6
|
"bin": {
|
|
7
7
|
"fdeops-ingest-mcp": "./server.js"
|
|
8
8
|
},
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fdeops",
|
|
3
|
-
"version": "4.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "4.1.1",
|
|
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",
|
|
7
7
|
"fde": "bin/fde.js"
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"check": "node bin/check.js && npm test",
|
|
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
|
-
"prepublishOnly": "node bin/check.js && npm test"
|
|
13
|
+
"prepublishOnly": "node bin/check.js && npm test",
|
|
14
|
+
"generate:skills": "node bin/generate-skills.js"
|
|
14
15
|
},
|
|
15
16
|
"files": [
|
|
16
17
|
"bin/",
|
package/plugin.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "fdeops",
|
|
4
|
-
"version": "4.
|
|
5
|
-
"description": "Forward deployed engineering skills for AI coding agents.
|
|
4
|
+
"version": "4.1.1",
|
|
5
|
+
"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.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Subash Natarajan",
|
|
8
8
|
"url": "https://github.com/suboss87"
|
package/skills/fde/SKILL.md
CHANGED
|
@@ -7,7 +7,11 @@ description: Keeps the engagement record for client work. Use when they name a c
|
|
|
7
7
|
|
|
8
8
|
## Purpose
|
|
9
9
|
|
|
10
|
-
The **engagement record** for one client, from first meeting to signed outcome. One
|
|
10
|
+
The **engagement record** for one client, from first meeting to signed outcome. One coordinator; six stages (land → close), with task skills that also work independently. Same methods on greenfield or brownfield engagements. Route from the request; never make the user choose a phase. Confirm, then write `.fde/`. The workspace still compiles and commits. `@fde` does not leave.
|
|
11
|
+
|
|
12
|
+
## Task entry
|
|
13
|
+
|
|
14
|
+
Read `references/task-context.md` first. An explicitly selected `fde-*` task runs directly; do not wrap it in another coordinator or repeat entry. For a one-off task with supplied context, use the relevant method without initializing `.fde/`. For ongoing client work use the bounded entry and memory contract below. Missing record files alone are not a reason to restart discovery.
|
|
11
15
|
|
|
12
16
|
## When to use
|
|
13
17
|
|
|
@@ -42,15 +46,15 @@ On someone else's site the work is not "write code, remember later." Every chang
|
|
|
42
46
|
|
|
43
47
|
Scale the loop to the change. A routine, reversible fix within confirmed scope reuses the existing outcome, signer, acceptance criteria, and engineering plan; batch its verification into a concise delivery receipt. It does not need a new sponsor decision or staging ceremony per edit. New outcomes, changed acceptance or authority, and production release decisions still need the relevant confirmation and evidence. This does not bypass confirmation for judgment written into the engagement record.
|
|
44
48
|
|
|
45
|
-
**Status is explicit.** Record what is implemented, verified, deployed, and accepted separately. A routine fix may be implementation-complete before release or customer acceptance; state what remains and attach the current verification receipt.
|
|
49
|
+
**Status is explicit.** Record what is implemented, verified, deployed, and accepted separately. A routine fix may be implementation-complete before release or customer acceptance; state what remains and attach the current verification receipt. The included build, integrate, debug and QA methods cover implementation; `@fde` connects their evidence to the engagement.
|
|
46
50
|
|
|
47
|
-
##
|
|
51
|
+
## Engineering within the pack
|
|
48
52
|
|
|
49
|
-
Use
|
|
53
|
+
Use `references/build.md` for implementation, `references/integrate.md` for customer-system boundaries, `references/debug.md` for failures and `references/qa.md` for the delivered journey. Each uses `references/verification.md` for actual evidence. These methods use the customer's coding conventions and installed tools; another skill pack is not required. Use an existing engineering plan rather than creating a competing backlog. Green tests establish tested behavior, not customer acceptance or production authority.
|
|
50
54
|
|
|
51
55
|
## Human surface vs agent plumbing
|
|
52
56
|
|
|
53
|
-
**FDE (human):** `@fde` + English, or `/brief` `/discover` `/plan` `/ship` `/outcome` `/close` `/debrief` `/prep` `/trust` `/receipts` `/readout`.
|
|
57
|
+
**FDE (human):** `@fde` + English, or `/brief` `/discover` `/plan` `/ship` `/outcome` `/close` `/debrief` `/prep` `/trust` `/receipts` `/readout`. They may also invoke an individual `fde-*` skill directly.
|
|
54
58
|
|
|
55
59
|
**You (agent):** run the CLI. **Never tell the FDE to type** `fde …`. If unbound, you run `fde resume --init` after one question. Never ask them to run the CLI.
|
|
56
60
|
|
|
@@ -91,7 +95,7 @@ Writes need a bind (`FDEOPS_ENGAGEMENT` or registry). Never install fdeops on in
|
|
|
91
95
|
## The memory contract
|
|
92
96
|
|
|
93
97
|
1. **On entry:** follow **Entry (every session)** above for the current packet and refresh rules. Retrieve additional evidence through targeted `fde recall` when needed.
|
|
94
|
-
2. **Deliverable
|
|
98
|
+
2. **Deliverable plus memory.** Deliver the requested code, evidence or decision artifact. On a bound engagement, record the confirmed result in the file named by the method. A standalone artifact does not require a `.fde/` folder.
|
|
95
99
|
3. **Evidence.** Without a supplied source, a decision or measurement remains CLAIM. Use `[source: meeting YYYY-MM-DD]`, a PR/URL, transcript ID, or artifact path. The automatic log date is not attribution. ON RECORD means a source was supplied, not that it was authenticated or the customer approved. Never invent a source, signer, or acceptance.
|
|
96
100
|
4. **No invented facts.** People, quotes, meetings, numbers: they said it or the repo shows it. Else `unknown - ask: <question>`.
|
|
97
101
|
5. **Session digest** (end of session and before a PR) - thinking, not the chat. Confirm, then write. Never a transcript dump.
|
|
@@ -162,7 +166,11 @@ Work names (engage, diagnose, align, deliver, realize, transfer) are the same ma
|
|
|
162
166
|
|----------|-------|-----------|
|
|
163
167
|
| What could go wrong, touching shared infrastructure, need to assess impact, assess impact, provision, IaC, shared infra | what-breaks | `references/what-breaks.md` |
|
|
164
168
|
| Production down, urgent, fix a prod bug, resolve incident, restore service - OR stakeholder gone quiet, trust slipping | rescue | `references/rescue.md` |
|
|
165
|
-
| Deliver, start building, update their checkout, first module,
|
|
169
|
+
| Deliver, start building, update their checkout, first module, their tests, build the increment, design their UI | build | `references/build.md` |
|
|
170
|
+
| Customer API, connector, data mapping, write-back, import, upstream integration | integrate | `references/integrate.md` |
|
|
171
|
+
| Reproduce a failure, unexpected output, regression, debug a connector | debug | `references/debug.md` |
|
|
172
|
+
| Exercise the customer journey, browser acceptance, functional QA | qa | `references/qa.md` |
|
|
173
|
+
| Ready to deploy, going live, pre-flight, release the verified increment | ship | `references/ship.md` |
|
|
166
174
|
| Review this change, review the pull request, is it safe, does it match what we agreed | review | `references/review.md` |
|
|
167
175
|
| Diff grew / scope creep in the PR / "did we only build what we said" / KEEP JUSTIFY SPLIT DROP | review (+ ship if going live) | `references/review.md` Stage 1 · `references/ship.md` Intent vs diff |
|
|
168
176
|
| Wrap the session / share the thinking / catch teammates up / before I open the PR | (memory contract - session digest) | SKILL.md **Session digest** - write TL;DR + decisions/why into `.fde/`; no transcript sync |
|
|
@@ -203,17 +211,17 @@ Work names (engage, diagnose, align, deliver, realize, transfer) are the same ma
|
|
|
203
211
|
| Payments, cardholder data, PCI-DSS, anything that moves money | `references/fintech.md` |
|
|
204
212
|
| Government agency, FedRAMP, ATO, CUI, classified | `references/gov.md` |
|
|
205
213
|
|
|
206
|
-
Ready to build
|
|
214
|
+
Ready to build: check that the supplied facts establish the outcome, constraints and verification path. Use discover or plan only for material gaps. On a takeover, audit inherited claims that affect the task. Two customers in one message: confirm which folder.
|
|
207
215
|
|
|
208
216
|
## Principles
|
|
209
217
|
|
|
210
218
|
- Never ask the FDE to pick a phase. That's your job.
|
|
211
219
|
- Same six stages at any scale. Overlays carry the industry. Greenfield and brownfield change the first move inside ship, not the map.
|
|
212
|
-
- Ground loop on a bound client: name → characterise → verify in the agreed environment → authorize release → log.
|
|
220
|
+
- Ground loop on a bound client: name → characterise → verify in the agreed environment → authorize release → log. The included engineering methods do the build. `@fde` keeps delivery status explicit. When they disagree, their repo and the signer win.
|
|
213
221
|
- Customer delivery needs a replayable acceptance check in the agreed environment; reuse existing criteria for routine fixes. Missing evidence means unproven, not an observed test failure. Never equate implementation-complete with deployed or customer-accepted.
|
|
214
222
|
- Read the current entry packet before speaking; follow **Entry (every session)** above. One sharp question - never a barrage.
|
|
215
223
|
- Never invent people, meetings, or numbers - `unknown - ask:` beats a polished lie.
|
|
216
|
-
-
|
|
224
|
+
- Deliver the task artifact; persist confirmed engagement judgments only when bound. Never manufacture a record to satisfy a checklist.
|
|
217
225
|
- Evidence on every claim. The FDE will be challenged on these files.
|
|
218
226
|
- Overlays activate on signal, not on request.
|
|
219
227
|
- Load `.fde/` files on demand, never the whole folder.
|
|
@@ -12,7 +12,7 @@ Technical FDEs lose renewals by presenting work instead of outcomes. The exec do
|
|
|
12
12
|
|
|
13
13
|
```
|
|
14
14
|
GOVERNING THOUGHT: (one sentence - the conclusion)
|
|
15
|
-
"The payment processing overhaul cut manual reconciliation from
|
|
15
|
+
"The payment processing overhaul cut manual reconciliation from
|
|
16
16
|
3 FTEs to 0.5 FTE and eliminated the $2M annual audit risk."
|
|
17
17
|
|
|
18
18
|
SUPPORT 1: What was done (one paragraph)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# build - Implement a verifiable increment
|
|
2
|
+
|
|
3
|
+
**Enter when:** an agreed behavior needs implementation in an existing or new repository. For a broken behavior, start with [debug](debug.md); for a system boundary, use [integrate](integrate.md).
|
|
4
|
+
|
|
5
|
+
Use the permitted context and authority in [task context](task-context.md). This method works without `.fde/`; an existing engagement record can supply the same contract. Do not initialize memory just to write code.
|
|
6
|
+
|
|
7
|
+
## Method
|
|
8
|
+
|
|
9
|
+
1. Identify the repository, its instructions, working tree, relevant callers, and test commands. Inspect examples before creating abstractions. Preserve unrelated edits and state which dependencies or interfaces the change touches.
|
|
10
|
+
2. State the observable outcome, constraints, and acceptance checks. Reuse agreed criteria for routine fixes. If a consequential product choice is unresolved, surface that choice while continuing independent investigation; do not invent acceptance.
|
|
11
|
+
3. Choose the smallest coherent path that demonstrates the outcome through the real entry point. Include the necessary storage, error handling, and interface behavior in that slice. Name the failure that stops expansion and the recovery path for stateful changes.
|
|
12
|
+
4. Implement using the repository's tools and conventions. Search for existing services, fixtures, and validation before adding alternatives. Keep cleanup limited to what makes the changed path understandable; do not expand scope to repair unrelated code.
|
|
13
|
+
5. Run focused checks, then required repository checks. Exercise the actual affected journey with [QA](qa.md) when appropriate. For uncertain model behavior, use [eval-pack](eval-pack.md). Record results with [verification](verification.md), including checks that could not run.
|
|
14
|
+
6. Inspect the final diff against the agreed outcome. For substantial or risky work, seek [review](review.md) using an actual separate reviewer when available; identify a self-check honestly. Reverify affected behavior after fixes.
|
|
15
|
+
|
|
16
|
+
## Deliverable and acceptance
|
|
17
|
+
|
|
18
|
+
Return the implemented behavior, relevant paths, evidence, remaining limitations, and any decision needed. Done means the agreed checks have applicable evidence and the change is reviewable; passing tests does not imply deployment or customer acceptance. Committing, opening a PR, merging, and publishing happen only when the requested workflow authorizes those actions.
|
|
19
|
+
|
|
20
|
+
When coordinated through `@fde`, record implementation and verification in the existing decisions/delivery records under their write rules. Standalone work can return the same receipt directly or use the repository's task record.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# business-case - Build the business case
|
|
2
2
|
|
|
3
|
+
**Context:** apply [task context and evidence](task-context.md) before using the named records below.
|
|
4
|
+
|
|
3
5
|
**Enter when:** the sponsor needs justification for the next phase, the FDE needs to defend budget or timeline, a feature decision needs cost/benefit evidence, or poc produced a direction that needs funding.
|
|
4
6
|
|
|
5
7
|
**Read first:** `reality.md`, `success.md`, `delivery.md`, `context.md`. Load `business-case.md` from poc if it exists - extend it, don't restart.
|
|
@@ -12,7 +14,7 @@ Technical FDEs lose engagements by shipping good code without business justifica
|
|
|
12
14
|
|
|
13
15
|
| Cost type | How to find it | Example |
|
|
14
16
|
|-----------|---------------|---------|
|
|
15
|
-
| **
|
|
17
|
+
| **Labor capacity / direct spend** | Ask: "What does this problem cost per month in money?" | Manual reconciliation hours × loaded rate = capacity value; separately identify reducible spend |
|
|
16
18
|
| **Opportunity cost** | Ask: "What can't you do because of this problem?" | Can't onboard enterprise clients because the API can't handle their volume |
|
|
17
19
|
| **Risk cost** | Ask: "What happens if this breaks at the worst time?" | A payment processing outage during Black Friday = $X/hour in lost sales |
|
|
18
20
|
| **Velocity cost** | Measure: deployment frequency, lead time, change failure rate | Team ships once/month instead of once/week; each delay = N features not reaching customers |
|
|
@@ -22,17 +24,17 @@ Technical FDEs lose engagements by shipping good code without business justifica
|
|
|
22
24
|
```
|
|
23
25
|
Investment: <hours × rate, or fixed cost>
|
|
24
26
|
→ Delivers: <specific outcome from success.md>
|
|
25
|
-
→
|
|
26
|
-
→ Net:
|
|
27
|
+
→ Benefit: <capacity released, avoidable cash spend, revenue, or risk reduction>
|
|
28
|
+
→ Net cash: realizable incremental cash benefit - full costs over <time horizon>
|
|
27
29
|
```
|
|
28
30
|
|
|
29
|
-
Keep
|
|
31
|
+
Keep drivers, units, sources, and ranges explicit. For example, 3 people × 8h/week × $75/h × 52 weeks = $93.6K/year of labor capacity value. It is cash savings only if spend actually falls (for example, paid overtime or a contractor cost ends). Name who can realize the benefit and how. Include build, ongoing operation, adoption, and transition costs; avoid double-counting capacity and revenue enabled by the same hours. Do not calculate cash payback from capacity value alone.
|
|
30
32
|
|
|
31
33
|
**3. Sensitivity check - name the two drivers that swing the result:**
|
|
32
34
|
|
|
33
35
|
Every business case has 1-2 variables where a small change flips the outcome. Name them explicitly:
|
|
34
36
|
|
|
35
|
-
> "
|
|
37
|
+
> "The capacity case assumes the team reclaims 6 hours/week per person. At 3 hours, that benefit halves. Cash payback remains unproven until finance identifies avoidable spend. Validate time-spent before and after the pilot with representative team members."
|
|
36
38
|
|
|
37
39
|
The sponsor who sees you've identified where the case could break trusts the case more, not less.
|
|
38
40
|
|
|
@@ -53,7 +55,7 @@ The sponsor who sees you've identified where the case could break trusts the cas
|
|
|
53
55
|
**The problem costs:** <one line, quantified>
|
|
54
56
|
**The investment:** <hours and cost>
|
|
55
57
|
**The return:** <quantified, with time horizon>
|
|
56
|
-
**Payback:** <months>
|
|
58
|
+
**Payback:** <months from realizable cash benefits, or not established>
|
|
57
59
|
**Sensitivity:** <the 1-2 drivers that swing it, with thresholds>
|
|
58
60
|
**Risks:** <what must be true for this to hold>
|
|
59
61
|
**Recommendation:** <proceed / proceed-with-conditions / defer>
|
|
@@ -67,7 +69,7 @@ The sponsor who sees you've identified where the case could break trusts the cas
|
|
|
67
69
|
|
|
68
70
|
## Checkpoint
|
|
69
71
|
|
|
70
|
-
Walk the FDE through: the cost of doing nothing (anchor), the investment, the return, and the one sensitivity that matters most. If the FDE says "the sponsor won't buy the ROI number"
|
|
72
|
+
Walk the FDE through: the cost of doing nothing (anchor), the investment, the return, and the one sensitivity that matters most. If the FDE says "the sponsor won't buy the ROI number," inspect the disputed inputs and sources, test plausible ranges, and identify what measurement would resolve the disagreement. Never reverse-engineer assumptions to hit a desired number.
|
|
71
73
|
|
|
72
74
|
## Worked example
|
|
73
75
|
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# close - Transfer operations
|
|
2
2
|
|
|
3
|
+
**Context:** apply [task context and evidence](task-context.md) before using the named records below.
|
|
4
|
+
|
|
3
5
|
**Enter when:** the engagement is ending - the customer team must run this without the FDE.
|
|
4
6
|
|
|
5
|
-
**Read first:** bounded `fde handoff` or `fde resume`, then targeted `fde recall` for missing evidence. Build the
|
|
7
|
+
**Read first:** for standalone work, use the supplied permitted operating notes, evidence and ownership; no engagement binding or CLI command is required. For a bound engagement, use bounded `fde handoff` or `fde resume`, then targeted `fde recall` for missing evidence. Never initialize records merely to draft a handoff. Build the picture through relevant excerpts, not a full-directory load. Consult `terrain.md` only for code paths needed by the successor.
|
|
6
8
|
|
|
7
9
|
The engagement doesn't end at ship. It ends when the customer can maintain what was built without calling.
|
|
8
10
|
|
|
@@ -20,10 +22,10 @@ The engagement doesn't end at ship. It ends when the customer can maintain what
|
|
|
20
22
|
**1b. Value + receipts close gate (refuse green close if any fail):**
|
|
21
23
|
- Primary value bucket in `success.md` matches what the sponsor funded; at least one ledger row has **Measured** (not forever-`pending`) with evidence **and a named customer-side owner in Accepted by** for that bucket - or the retrospective explicitly records “not measured; sponsor accepted pending.” A measured-but-unaccepted number closes as `claimed`; say so in the retrospective rather than closing green on arithmetic nobody signed.
|
|
22
24
|
- Audit receipt exists for the final shipped path (exceptions/operating map walked; cite file).
|
|
23
|
-
- Eval receipt: **n/a if no AI**, else final
|
|
25
|
+
- Eval receipt: **n/a if no AI**, else final scoped eval result + operating owner and required human-review or bounded-automation authority recorded; kill switch / fallback named in `handoff.md`.
|
|
24
26
|
- One line in the retrospective: which bucket moved, by how much, vs baseline.
|
|
25
27
|
|
|
26
|
-
**2. The pattern.** Anything that happened here and will happen again - a compliance approach, a migration pattern, a stakeholder dynamic - gets encoded for reuse.
|
|
28
|
+
**2. The pattern.** Anything that happened here and will happen again - a compliance approach, a migration pattern, a stakeholder dynamic - gets encoded for reuse. Use [encode-pattern](encode-pattern.md) to distinguish candidate patterns from supported ones and protect customer data.
|
|
27
29
|
|
|
28
30
|
**3. The handoff.** Operational knowledge for the person woken at 2am, not technical documentation: the 3 things that will break and the fix for each · who holds the tribal knowledge · what each alert means · deploy and rollback in plain language. AI components additionally: model version, what normal output looks like (so drift is recognisable), fallback behaviour, who owns retraining, **how to disable the AI path without taking down the feature** - without this the team turns it off at the first misbehaviour and it stays off.
|
|
29
31
|
|
|
@@ -41,7 +43,7 @@ The engagement doesn't end at ship. It ends when the customer can maintain what
|
|
|
41
43
|
|
|
42
44
|
**Check the handoff as a lookup tool.** Give the intended operator one realistic task, such as finding the owner and recovery steps for a failed run. Can they locate the answer and its source in the permitted handoff without your explanation? A reader finding the instructions is not proof they can execute them; verify operation separately in the agreed safe environment. Correct the passage they could not use, rather than adding a longer introduction.
|
|
43
45
|
|
|
44
|
-
If the operator is unavailable, a fresh reviewer can attempt the same lookup using only the permitted draft and task. Report this as a simulated clarity check, not operator validation, customer approval, or a green close. Use one focused pass for a consequential handoff; do not add a committee or a second approval ritual.
|
|
46
|
+
If the operator is unavailable, a fresh reviewer can attempt the same lookup using only the permitted draft and task. Report this as a simulated clarity check, not operator validation, customer approval, or a green close. Claim independent review only if a separate reviewer actually performed it; identify the reviewer and evidence available. If none is available, perform a labeled self-check and report independent review as unperformed. Use one focused pass for a consequential handoff; do not add a committee or a second approval ritual.
|
|
45
47
|
|
|
46
48
|
Direct assessment to the FDE: did the engagement achieve `success.md` · 2-3 lessons that matter · is the pattern worth encoding · is the handoff complete or where are the gaps. Also: value bucket + audit receipt green; eval **n/a or green**. Pending Measured without sponsor acceptance = gap, not green close. Honest - a gap named now is cheaper than a callback in six weeks.
|
|
47
49
|
|