fdeops 3.24.0 → 3.27.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.
- package/README.md +78 -216
- package/adapters/LOCAL-LLM.md +14 -102
- package/bin/check.js +3 -3
- package/bin/fde.js +517 -375
- package/bin/install.js +74 -51
- package/bin/lib/context.js +85 -0
- package/bin/lib/delivery-gaps.js +34 -0
- package/bin/lib/fieldbook-client.js +41 -10
- package/bin/lib/font-css.js +115 -0
- package/bin/lib/install-paths.js +53 -0
- package/bin/lib/provenance.js +42 -0
- package/bin/lib/render.js +57 -74
- package/bin/lib/value-ledger.js +40 -0
- package/hooks/session-start +18 -84
- package/mcp/fdeops-ingest/package.json +1 -1
- package/package.json +2 -2
- package/plugin.json +1 -1
- package/skills/fde/SKILL.md +6 -5
- package/skills/fde/references/plan.md +2 -0
- package/skills/fde/references/poc.md +11 -3
- package/skills/fde/references/ship.md +3 -1
package/hooks/session-start
CHANGED
|
@@ -91,7 +91,7 @@ fi
|
|
|
91
91
|
|
|
92
92
|
# 5) Optional in-repo .fde (customer-approved only)
|
|
93
93
|
if [ -z "$CONTEXT_FILE" ] && [ -f ".fde/context.md" ]; then
|
|
94
|
-
ENG_DIR="
|
|
94
|
+
ENG_DIR="$(pwd -P)/.fde"
|
|
95
95
|
CONTEXT_FILE=".fde/context.md"
|
|
96
96
|
fi
|
|
97
97
|
|
|
@@ -105,72 +105,8 @@ if [ "$IS_FDE_PROJECT" -eq 0 ]; then
|
|
|
105
105
|
exit 0
|
|
106
106
|
fi
|
|
107
107
|
|
|
108
|
-
#
|
|
109
|
-
# context, so <private>...</private> blocks (sacred data, never-AI content)
|
|
110
|
-
# must never reach here unredacted, same guarantee as the dashboard renderer.
|
|
111
|
-
# <private> blocks are written one per line in the templates (own line, own
|
|
112
|
-
# closing tag), so a line-based state machine matches the real usage; an
|
|
113
|
-
# unclosed <private> redacts to end-of-file, same as the JS regex fallback.
|
|
114
|
-
strip_private() {
|
|
115
|
-
# Detection is case-insensitive (matches the JS /gi redactor) - <PRIVATE>,
|
|
116
|
-
# <Private>, <private> all redact. Detect on a lowercased copy of the line;
|
|
117
|
-
# never print the original when a tag is present.
|
|
118
|
-
awk '
|
|
119
|
-
BEGIN { inblock = 0 }
|
|
120
|
-
{
|
|
121
|
-
line = $0
|
|
122
|
-
lc = tolower(line)
|
|
123
|
-
if (inblock) {
|
|
124
|
-
if (index(lc, "</private>") > 0) { inblock = 0 }
|
|
125
|
-
next
|
|
126
|
-
}
|
|
127
|
-
if (index(lc, "<private>") > 0) {
|
|
128
|
-
print "(private - redacted)"
|
|
129
|
-
if (index(lc, "</private>") == 0) { inblock = 1 }
|
|
130
|
-
next
|
|
131
|
-
}
|
|
132
|
-
print line
|
|
133
|
-
}
|
|
134
|
-
' "$1"
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
# Token discipline: context.md grows every session (session-stop appends a
|
|
138
|
-
# snapshot). Inject a bounded view - curated head + most recent activity -
|
|
139
|
-
# instead of the whole log. Mirrors resumeView() in bin/fde.js; keep in sync.
|
|
140
|
-
bounded_context() {
|
|
141
|
-
local f="$1" total head_end tail_start hidden
|
|
142
|
-
total=$(wc -l < "$f" 2>/dev/null | tr -d ' ')
|
|
143
|
-
[ -z "$total" ] && { cat "$f"; return; }
|
|
144
|
-
if [ "$total" -le 160 ]; then cat "$f"; return; fi
|
|
145
|
-
# Anchor on the "## Session end" heading, matching resumeView() in bin/fde.js.
|
|
146
|
-
# The JS path reads via readClean (strips HTML comments), so both sides must
|
|
147
|
-
# anchor on a marker that survives redaction - the heading, not the comment.
|
|
148
|
-
head_end=$(grep -n -m1 '^## Session end' "$f" 2>/dev/null | cut -d: -f1)
|
|
149
|
-
if [ -n "$head_end" ]; then head_end=$((head_end - 1)); else head_end=120; fi
|
|
150
|
-
[ "$head_end" -gt 120 ] && head_end=120
|
|
151
|
-
[ "$head_end" -lt 0 ] && head_end=0
|
|
152
|
-
tail_start=$((total - 40 + 1))
|
|
153
|
-
if [ "$tail_start" -le "$((head_end + 1))" ]; then cat "$f"; return; fi
|
|
154
|
-
hidden=$((tail_start - head_end - 1))
|
|
155
|
-
[ "$head_end" -ge 1 ] && sed -n "1,${head_end}p" "$f"
|
|
156
|
-
printf '\n_(… %s lines of earlier session log hidden - `fde resume --full` or open context.md for the full history)_\n\n' "$hidden"
|
|
157
|
-
sed -n "${tail_start},\$p" "$f"
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
CONTENT=""
|
|
161
|
-
|
|
162
|
-
# Lean pointer only - never cat SKILL.md. Methods load on @fde / skill trigger.
|
|
163
|
-
CONTENT="${CONTENT}fdeops: engagement fieldbook active. Human speaks plain language with @fde - you (the agent) run the local fde CLI for memory plumbing; never ask the human to type fde commands. Load skills/fde/SKILL.md when @fde triggers.\n\n"
|
|
164
|
-
|
|
165
|
-
# Same TRIAGE block as `fde resume` / `fde triage` (includes proactive hygiene
|
|
166
|
-
# when the fieldbook has doctor issues; silent when clean). Monday morning must
|
|
167
|
-
# not depend on the model remembering to run a CLI command. Prefer the installed
|
|
168
|
-
# fde binary; fall back to the plugin/repo copy of bin/fde.js.
|
|
108
|
+
# Prefer this installation so its hook and CLI share the same safety contract.
|
|
169
109
|
resolve_fde() {
|
|
170
|
-
if command -v fde >/dev/null 2>&1; then
|
|
171
|
-
printf '%s\n' "fde"
|
|
172
|
-
return 0
|
|
173
|
-
fi
|
|
174
110
|
for candidate in \
|
|
175
111
|
"${CLAUDE_PLUGIN_ROOT:+$CLAUDE_PLUGIN_ROOT/bin/fde.js}" \
|
|
176
112
|
"$(dirname "$0")/../bin/fde.js" \
|
|
@@ -181,25 +117,23 @@ resolve_fde() {
|
|
|
181
117
|
return 0
|
|
182
118
|
fi
|
|
183
119
|
done
|
|
120
|
+
if command -v fde >/dev/null 2>&1; then
|
|
121
|
+
printf '%s\n' "fde"
|
|
122
|
+
return 0
|
|
123
|
+
fi
|
|
184
124
|
return 1
|
|
185
125
|
}
|
|
186
126
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
CONTENT="$CONTENT---\n$TRIAGE\n\n"
|
|
197
|
-
fi
|
|
198
|
-
fi
|
|
199
|
-
REDACTED_CONTEXT=$(mktemp)
|
|
200
|
-
strip_private "$CONTEXT_FILE" > "$REDACTED_CONTEXT"
|
|
201
|
-
CONTENT="$CONTENT---\nEngagement context ($CONTEXT_FILE):\n$(bounded_context "$REDACTED_CONTEXT")\n"
|
|
202
|
-
rm -f "$REDACTED_CONTEXT"
|
|
127
|
+
# The matching CLI owns triage, private redaction, and context bounds.
|
|
128
|
+
# Never fall back to reading raw notes when Node or the CLI is unavailable.
|
|
129
|
+
FDE_CMD=$(resolve_fde || true)
|
|
130
|
+
[ -n "$FDE_CMD" ] || exit 0
|
|
131
|
+
[ -n "$CONTEXT_FILE" ] && [ -f "$CONTEXT_FILE" ] || exit 0
|
|
132
|
+
if [ "$FDE_CMD" = "fde" ]; then
|
|
133
|
+
CONTEXT=$(FDEOPS_ENGAGEMENT="$ENG_DIR" fde resume 2>/dev/null) || exit 0
|
|
134
|
+
else
|
|
135
|
+
CONTEXT=$(FDEOPS_ENGAGEMENT="$ENG_DIR" node "$FDE_CMD" resume 2>/dev/null) || exit 0
|
|
203
136
|
fi
|
|
204
|
-
|
|
205
|
-
printf '%
|
|
137
|
+
[ -n "$CONTEXT" ] || exit 0
|
|
138
|
+
printf '%s\n\n' 'fdeops: engagement fieldbook active. Human speaks plain language with @fde - you (the agent) run the local fde CLI for memory plumbing; never ask the human to type fde commands. Load skills/fde/SKILL.md when @fde triggers.'
|
|
139
|
+
printf '%s\n' 'Engagement context:' "$CONTEXT"
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fdeops",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "3.27.0",
|
|
4
|
+
"description": "Client delivery tools for Forward Deployed Engineers. One @fde skill, local Markdown engagement records, and an offline dashboard for decisions, evidence, approvals, and next actions.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"fdeops": "bin/install.js",
|
|
7
7
|
"fde": "bin/fde.js"
|
package/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "fdeops",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.27.0",
|
|
5
5
|
"description": "Forward deployed engineering skills for AI coding agents. One @fde skill for the client work around the code. You confirm; then it lands in .fde/ on your laptop.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Subash Natarajan",
|
package/skills/fde/SKILL.md
CHANGED
|
@@ -28,13 +28,13 @@ A one-line typo or compile error in a file that will not ship. On a bound client
|
|
|
28
28
|
| **When did we agree?** | Don't argue from memory. Search the record. | `fde receipts <term>` | - |
|
|
29
29
|
| **What's the outcome?** | A number nobody signed is claimed, not delivered. | `fde status` | `references/readout.md` |
|
|
30
30
|
|
|
31
|
-
After a meeting: `fde debrief --smart` → one REVIEW screen (
|
|
31
|
+
After a meeting: `fde debrief --smart` → one REVIEW screen (decisions / asks / scope / delivery gaps / next / signer) → in chat, a four-row card (omit empty; Previously / Not yet agreed) → **Save this update?** (engineer accepted the record, not customer approval of every ask) → `--apply`. Walk-in: `fde prep`. Friday: `fde status`.
|
|
32
32
|
|
|
33
33
|
## Ground loop
|
|
34
34
|
|
|
35
35
|
On someone else's site the work is not "write code, remember later." Every change on a bound client stays on `@fde`:
|
|
36
36
|
|
|
37
|
-
1. **Name it** in `decisions.md` (plan) or
|
|
37
|
+
1. **Name it** in `decisions.md` (plan), or timebox the riskiest assumption and record what the POC proves.
|
|
38
38
|
2. **Characterise their code** before you change it. Brownfield: their tests, their runner. Greenfield: the empty tree, first path they can click.
|
|
39
39
|
3. **Prove it on their staging.** Staging they operate, a screen the signer in `success.md` can reject.
|
|
40
40
|
4. **If a model judges:** `evals.md` Verdict SHIP before that change is done (eval-pack).
|
|
@@ -58,7 +58,7 @@ Fallbacks: `node ~/.claude/fdeops/fde.js …`, then `npx --yes fdeops …`. Skil
|
|
|
58
58
|
|
|
59
59
|
## Entry (every session)
|
|
60
60
|
|
|
61
|
-
1. `fde resume` (
|
|
61
|
+
1. `fde resume` (16 KiB output ceiling, not a model token count). Read client constraints first, then signer, goals, risks, delivery ledger and current context. This command is the inspectable packet the session hook loads; never substitute a recursive read of `.fde/` or raw transcripts. If truncated or a decision needs evidence, run `fde recall <specific topic>`; narrow the query rather than loading the whole history. `--max-bytes 4096` reduces the allowance for smaller models. `--full` only when the complete log is explicitly needed.
|
|
62
62
|
2. **NO ENGAGEMENT:** ask "What should we call this client?" then **you** init. Pasted notes → debrief after bind.
|
|
63
63
|
3. Playback 2-3 lines. `hygiene:` → offer `fde doctor`; **never auto-rewrite**.
|
|
64
64
|
4. Route. Read **one** `references/*.md`. Confirm, then write.
|
|
@@ -72,7 +72,8 @@ Writes need a bind (`FDEOPS_ENGAGEMENT` or registry). Never install fdeops on in
|
|
|
72
72
|
| debrief / pasted notes | `fde debrief --smart` → REVIEW → four-row chat card → Save this update? → `--apply`. `--smart` is a gate, not a brain. `references/debrief.md` |
|
|
73
73
|
| prep me for … | `fde prep "<label>"` |
|
|
74
74
|
| when did we agree | `fde receipts <term>` |
|
|
75
|
-
| sponsor update / the
|
|
75
|
+
| sponsor update / defend the number | `fde defend` |
|
|
76
|
+
| successor / rotation / portable handoff | `fde handoff` (stdout; `--out new-file.md` only after export requested) |
|
|
76
77
|
| they went quiet | `fde log contact "…" --signal amber\|green\|red` |
|
|
77
78
|
| fieldbook page | `fde dashboard` (`--all` portfolio, `--open` to open the file) |
|
|
78
79
|
| clean up the fieldbook | `fde doctor` - never auto-rewrite |
|
|
@@ -85,7 +86,7 @@ Writes need a bind (`FDEOPS_ENGAGEMENT` or registry). Never install fdeops on in
|
|
|
85
86
|
|
|
86
87
|
1. **On entry:** `fde resume` only. Pull other `.fde/` files when the skill needs them.
|
|
87
88
|
2. **Deliverable = memory.** The work *is* the `.fde/` file. The reference names which one.
|
|
88
|
-
3. **Evidence.**
|
|
89
|
+
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.
|
|
89
90
|
4. **No invented facts.** People, quotes, meetings, numbers: they said it or the repo shows it. Else `unknown - ask: <question>`.
|
|
90
91
|
5. **Session digest** (end of session and before a PR) - thinking, not the chat. Confirm, then write. Never a transcript dump.
|
|
91
92
|
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
**Read first:** `reality.md`, `success.md`, `terrain.md`, `stakeholders.md`. Load `business-case.md` if poc produced one. Not the full folder.
|
|
6
6
|
|
|
7
|
+
**Before committing a plan or building:** run `fde doctor --ready`. Missing binary success or a named customer-side signer blocks progression: review the proposed acceptance check and authority with the FDE first. Use a test/input and observable pass/fail under **Done when:** or **Acceptance check:**. A number, role, or successful demo alone is insufficient. Do not invent missing facts to pass lint.
|
|
8
|
+
|
|
7
9
|
## Validation gate (confirm understanding, clarify where it elevates)
|
|
8
10
|
|
|
9
11
|
Before planning, state what you're working from in 2-3 lines:
|
|
@@ -14,10 +14,10 @@ A green check on synthetic data is not a validated solution. The person who can
|
|
|
14
14
|
|
|
15
15
|
**1. Pick by score when several use cases compete.** Use the scoring model from `discover.md` - (Value × Data readiness) / Complexity. If discover or score-use-cases already produced a ranking, reuse it; never invent a third ranking.
|
|
16
16
|
|
|
17
|
-
**2. Build the minimum that tests the assumption.**
|
|
17
|
+
**2. Build the minimum that tests the assumption.** Timebox the experiment with the FDE; aim for a same-day result when access and evidence permit it. Skip cosmetic polish, but keep the input validation, access controls, and failure handling needed to protect the test environment and data. Label shortcuts and simulated inputs. The POC is done when the person who can say no has seen the evidence and reacted, not when the code looks finished.
|
|
18
18
|
|
|
19
19
|
**3. AI directions - test these before anything else:**
|
|
20
|
-
- Data: available, clean, sufficient volume? Synthetic
|
|
20
|
+
- Data: available, clean, sufficient volume? Synthetic data can test mechanics, but does not establish production quality or real-world coverage.
|
|
21
21
|
- Environment: are external model calls even allowed here?
|
|
22
22
|
- Latency: acceptable against real user expectations, not ideal conditions?
|
|
23
23
|
- Is AI the right tool at all - or is this a data-quality or process problem wearing an AI costume?
|
|
@@ -26,6 +26,14 @@ A green check on synthetic data is not a validated solution. The person who can
|
|
|
26
26
|
|
|
27
27
|
**5. Translate to business language** once validated: problem solved, cost of inaction, success in numbers, 2-3 trade-offs. Three sentences max for the stakeholder - can't say it in three, don't understand it yet.
|
|
28
28
|
|
|
29
|
+
## If proceeding to production
|
|
30
|
+
|
|
31
|
+
Carry the hypothesis, test evidence, customer reaction, and remaining unknowns into the existing `plan` and `ship` workflow. A working demo does not establish production readiness or customer acceptance.
|
|
32
|
+
|
|
33
|
+
Inspect the prototype before deciding what to reuse. Keep components whose behavior and boundaries are suitable and tested. Replace or harden shortcuts that fail production requirements; rewrite only where the evidence justifies it. Record the decision and remaining work in `decisions.md`, rather than treating all prototype code as disposable or all working code as ready to deploy.
|
|
34
|
+
|
|
35
|
+
Production work includes the actual data path, permissions, failure recovery, realistic load, observability, ownership, and required AI evaluations. Use the existing ship gates for those checks.
|
|
36
|
+
|
|
29
37
|
## Artifact
|
|
30
38
|
|
|
31
39
|
**`prototype-log.md`** - what was built, shown, the actual reaction, what was learned (including kills - a killed prototype that saved three weeks is a win worth recording).
|
|
@@ -38,7 +46,7 @@ Tell the FDE: did the riskiest assumption hold · what the customer's reaction a
|
|
|
38
46
|
|
|
39
47
|
## Principles
|
|
40
48
|
|
|
41
|
-
-
|
|
49
|
+
- Optimize for a bounded learning outcome. Agree a timebox and revisit scope if access or evidence blocks it; never skip necessary safeguards to meet an arbitrary duration.
|
|
42
50
|
- Write pass/fail before you build. A demo with no kill line is a show.
|
|
43
51
|
- Show it rough. Polish misleads.
|
|
44
52
|
- Prototype the killer assumption, not the demo.
|
|
@@ -12,7 +12,9 @@ Do not ask them to pick a mode. Name where you are, then start at the matching s
|
|
|
12
12
|
|
|
13
13
|
If going live, opening question: **has anyone actually *run* the rollback, or is it still a slide?** If only planned, that's today's work - say so plainly.
|
|
14
14
|
|
|
15
|
-
A
|
|
15
|
+
A bounded experiment that tests an assumption is `poc`. This skill turns a validated direction into a maintainable change on a repo they will own, then production. Inspect existing prototype code and retain suitable tested parts; replace unsafe shortcuts based on evidence. A successful demo alone does not satisfy the readiness gates below.
|
|
16
|
+
|
|
17
|
+
**Before committing a plan or building:** run `fde doctor --ready`. Missing binary success or a named customer-side signer blocks progression: review the proposed acceptance check and authority with the FDE first. Use a test/input and observable pass/fail under **Done when:** or **Acceptance check:**. A number, role, or successful demo alone is insufficient. Do not invent missing facts to pass lint.
|
|
16
18
|
|
|
17
19
|
## Field (name it once, then the same loop)
|
|
18
20
|
|