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.
@@ -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=".fde"
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
- # Mirrors stripPrivate() in bin/fde.js: this is what an agent loads as
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
- if [ -n "$CONTEXT_FILE" ] && [ -f "$CONTEXT_FILE" ]; then
188
- FDE_CMD=$(resolve_fde || true)
189
- if [ -n "$FDE_CMD" ]; then
190
- if [ "$FDE_CMD" = "fde" ]; then
191
- TRIAGE=$(FDEOPS_ENGAGEMENT="$ENG_DIR" fde triage 2>/dev/null || true)
192
- else
193
- TRIAGE=$(FDEOPS_ENGAGEMENT="$ENG_DIR" node "$FDE_CMD" triage 2>/dev/null || true)
194
- fi
195
- if [ -n "$TRIAGE" ]; then
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 '%b' "$CONTENT"
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"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fdeops-ingest-mcp",
3
- "version": "3.24.0",
3
+ "version": "3.27.0",
4
4
  "private": true,
5
5
  "description": "Thin stdio MCP sink for FDEOps ingest (stage → propose → apply). Zero runtime dependencies.",
6
6
  "bin": {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fdeops",
3
- "version": "3.24.0",
4
- "description": "Forward deployed engineering skills for AI coding agents. One @fde skill for the client work around the code: who can say yes, what went live, whether they signed off. Dated markdown on your laptop. You confirm each write.",
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.24.0",
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",
@@ -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 (decided / asked / open / 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`.
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 kill it in a day (poc).
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` (bounded `context.md`). `--full` only if you need the whole log.
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 outcome | `fde status` |
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.** Every claim has a source. Traceable beats plausible.
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.** No error handling, no polish. Same-day demo if possible. Rough is honest. The POC is done when the person who can say no has seen it and reacted, not when the code looks finished.
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-data prototypes say nothing about production behaviour.
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
- - Speed of learning beats code quality. Never more than a day.
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 same-day throwaway that kills an assumption is `poc`. This skill is the real change on a repo they will own, then production.
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