fix: a typo'd fdeops command errors instead of installing; LOG shows each contact once - #33
fix: a typo'd fdeops command errors instead of installing; LOG shows each contact once#33devin-ai-integration[bot] wants to merge 3 commits into
Conversation
…LOG panel - `fdeops <typo>` (including `Demo`/`DEMO`) exited 0, printed the install banner and rewrote ~/.claude instead of running anything. Verbs now match case-insensitively and anything unrecognized exits 1 with a suggestion; bare `npx fdeops` still installs. - The fieldbook LOG rendered every `fde log contact` entry twice, because the timeline reads both stakeholders.md and .signal-ledger (the CLI writes both on purpose). Identical rows are collapsed at read time. - doctor now flags unbalanced <private> markers: a stray closer leaves the following text public, a forgotten opener seals later notes. Counts only. - A copy failure named the source path inside the package; it now names the destination the user can actually fix.
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
…ag no longer eats the verb - `fdeops --help`/`-h` printed the install banner and rewrote ~/.claude at exit 0, because the positional filter dropped every dash-prefixed argument. Flags now answer: --help routes to the CLI help, --version prints the version, and only a genuinely empty (or install-flag-only) argv installs. - `fdeops --force redact ledger` searched for "--force ledger": the verb was no longer argv[2] after the rewrite. The hand-off now passes the verb first plus only what followed it - a flag typed before the verb belongs to fdeops. - FDE_SUBCOMMANDS was missing `preserve`, which fde.js implements. - The LOG de-dup key now includes the signal, so the same note logged amber then red on one day stays two rows: that is an escalation, not a duplicate.
…re the verb Two cosmetic gaps left by the previous commit: - A same-day amber then red note is two LOG rows by design, but the row markup carried date/kind/text only, so an escalation looked like a double write. Rows now render the signal (colored dot + label). - A flag typed before the verb is fdeops' own and is not forwarded, which meant `fdeops --all status` silently ignored --all at exit 0. Anything outside --force/--help/--version there now exits 1 and says where the option belongs.
Runtime verification — launch polishTested the published package built from this branch ( Verification below is against Dispatch: asking a question no longer writes to
|
| case | result |
|---|---|
--help / -h / --version / -v (+ -H, --HELP, each with a trailing --force) |
exit 0, help or 3.9.20, $HOME clean |
bare fdeops, --force, install, install --force, --force install |
exit 0, skills + 3 hooks installed |
9 typo'd verbs incl. presrve, Dmeo |
exit 1, correct did you mean, $HOME clean |
Demo / DEMO / DeMo / Scan / HELP / PRESERVE |
run the command, install nothing |
preserve |
dispatches (was "unknown command") |
--force redact X vs redact X |
same term (previously searched "--force X") |
19 valid verbs were compared differentially against fde — identical exit codes, $HOME/.claude never created.
Flags after the verb were verified with flags whose effect is observable, not just exit codes: redact --apply <term> parsed the term and deleted only the matching line; log --signal red/amber wrote the token to both storage locations while --signal purple still exits 1 (so the value forwards); log --undo restored byte-identical state; log --force overrode the secret refusal; debrief --smart FILE --apply committed decision + risk, reversed order identical; dashboard --all/--out wrote the expected files; demo --clean removed .demo with a decoy real client byte-identical.
LOG: each contact once, escalations still two rows
Counted by parsing only fb-row fb-log blocks — a whole-file grep double-counts, since row text also appears in the People panel.
| case | on disk | rendered |
|---|---|---|
one log contact |
stakeholders.md and .signal-ledger |
1 row (no data loss) |
| 4 byte-identical rows | 4 | 1 |
| amber → red, same day/text | 4 | 2 |
| distinct same-day text · same date+text different kind | — | both render |
| 15 unique + 3 exact dupes | 18 | 15, UNIQUE-OLDEST-15 retained (de-dup precedes the slice) |
fde prep |
— | agrees with the dashboard; shows [red] (latest) |
Installer, privacy, doctor, demo (regression)
install.js changed, so the install matrix was re-run: permission failure → exit 1, permission denied at <path under $HOME>, 0 package-source paths, 0 stack frames, install continued (3 hooks), and chmod u+w on exactly the reported path makes the re-run exit 0 and restore the file. Symlink refusal ± --force: refused, target byte-identical, 0 stray managed markers.
Privacy through the rewritten dispatch: needle 0 across 13 model-facing commands and 0 in both rendered HTMLs, marker rendered, needle preserved on disk. doctor marker counts on a non-fresh engagement: 9 shapes all exact (nested/attribute/balanced silent; 3-openers-1-closer → 2 unclosed; 2 strays → 2 unmatched; HTML-comment marker → 1 unclosed), 0 sealed content printed. demo: 10 steps, needle 0 in transcript and HTML with the on-disk control inside <private>; 60-second appears 0 times in the installed package. dashboard --open handed xdg-open the exact plain path (0 %2F) and Chrome rendered the Fieldbook.
Note for future readers: the doctor marker check sits after the day-1 if (fresh) return issues early-return, so it cannot fire on a freshly initialized engagement — matching the "don't nag on day 1" rule.
Not tested: npx skills add suboss87/fdeops (needs network egress from the test sandbox).





Summary
First-impression defects found by a fresh-user pass over merged trunk (
f4214b8), tested against the published package rather than a checkout.1.
fdeops <anything-unknown>silently performed a full install.bin/install.jsdispatchedinit/adapters/FDE_SUBCOMMANDSand let everything else fall through tocmdInstall(), exit 0. Sonpx fdeops Demo(ordmeo,dashbord) rewrote~/.claude/skills,~/.claude/hooks/fdeops-*and~/.claude/fdeops/fde.js, never ran the demo, and reported success. Verbs now resolve case-insensitively, and an unrecognized one exits 1 with a nearest-match suggestion; barenpx fdeopsstill installs.2. Every
fde log contactentry rendered twice in the fieldbook LOG panel.fde log contactdeliberately records into bothstakeholders.md"## Signal history" and.signal-ledger(the ledger survives an agent rewriting the markdown), and the timeline reads both. Two contacts showed as four adjacent identical rows — it reads as "this tool double-writes my data", which is the opposite of the pitch. Collapsed at read time, so both storage locations stay:The signal is part of the key on purpose: an amber note escalated to red the same day is two real events, and they must not collapse into one. Which then required (6).
3.
doctorsaid nothing about unbalanced<private>markers. Not a sealed-block leak — non-greedy pairing is working as designed — but the user's intent silently differs from the result: a stray</private>leaves everything after it public, and a forgotten closer seals every note appended later.doctornow reports counts per file, never the sealed text:4. A copy failure named the wrong path.
~/.claude/skills/fde - permission denied at <package>/skills/fde/references/ai.mdpointed the user at a file inside the package they can't fix; the unwritable path is the destination, sodestPathFor()re-roots the reported path underdest.5.
fdeops --help/--versioninstalled. Fixing (1) by filtering dash-prefixed args out ofpositionalleft flag-only invocations with no verb at all, so they fell through tocmdInstall()— asking the tool a question rewrote~/.claude. Help and version are now answered before dispatch and touch nothing.6. A flag before the verb ate the verb's argument, and is now rejected outright. The first pass set
process.argv[2] = argin place, sofdeops --force redact ledgerleft--forcesitting where the CLI expects the search term:A flag typed there belongs to
fdeops, not to the command, and forwarding it would silently change what the command operates on. So rather than dropping it quietly —fdeops --all statusexiting 0 having ignored--all— anything outside--force/--help/--versionbefore the verb exits 1 and says where the option belongs.7. An escalation looked like a double write. With (2) in place,
amberthenredon the same note correctly renders two rows — but the row markup carried date/kind/text only, so the two rows were pixel-identical. Rows now render the signal (● red), which is also the first place the timeline shows trust movement at all.Also dropped the "60-second walkthrough" wording from
fde demohelp — it takes ~0.4s, and this repo's whole thesis is claims that check out.Five regression tests, each verified to fail with the fix reverted.
npm run check= 53 gates + 91/91 tests. Full runtime evidence (dispatch matrix, LOG counts parsed from row markup, installer/privacy/demo regression,dashboard --openin real Chrome) is in the verification comment below.Link to Devin session: https://app.devin.ai/sessions/f135381c4682413bae73dff38eb6d1a3
Requested by: @suboss87