Skip to content

fix: route legacy Lavish captain answers safely - #63

Merged
MrGTV-love merged 4 commits into
mainfrom
fm/fm-lavish-legacy-answer-schema
Oct 9, 2026
Merged

MrGTV-love merged 4 commits into
mainfrom
fm/fm-lavish-legacy-answer-schema

Conversation

@MrGTV-love

Copy link
Copy Markdown
Owner

Intent

I would like all bugs to be fixed so tomorrow can be focused entirely to Vernant and not problems preventning Vernant from getting built.

A recommended architecture should come with proof.

Context (the backlog record for this bug, as filed): Lavish answers adapter returns nothing for older page choice formats, so captured captain answers (e.g. Backpass A) never route; adapt the legacy shape and replay unrouted captured answers safely (repo: firstmate) (kind: ship) (priority: 0) (since 2026-09-30) ... Found by fm-open-loops-audit 2026-09-30 (data/fm-open-loops-audit/report.md root cause 2): 46 of 251 captured structured answers lack proved routing; lavish-43b2c19414f5cd4f.1.result holds key backpass-path answer A-upstream-optin-plus-fork-bridge but the answers adapter emits no keyed row. Fork MrGTV-love/firstmate only. mode=no-mistakes yolo=off.

What Changed

  • Accept unversioned Lavish answers with optional notes and bookkeeping fields, supporting choice when answer is absent and preserving notes in answer labels.
  • Resolve the latest valid choice before filtering outputs so legacy Reconcile values suppress earlier answers or requests without entering either intake.
  • Add legacy-format and mixed-order regression coverage, update the captured-choice documentation and bearings guidance, and include live-validation decks and captured session artifacts.

Risk Assessment

🚨 High: The newly accepted legacy path can close a task using a superseded answer, and the explicitly required recovery of previously captured answers remains undelivered.

Testing

Five real Lavish browser submissions and an idempotent capture replay passed, with screenshots, raw captures, CLI resolutions, and persisted-state evidence saved. The base adapter reproduced the dropped-answer regression, and all four focused regression selectors passed after completing the initially timed-out invocation separately. Disposable resources were removed.

  • Live validation: ✅ go - 6 of 6 scenarios driven live against the product
Scenario Result Live Evidence
Submit legacy answers with notes, bookkeeping fields, and the choice alias; matching held tasks close ✅ pass live Ordinary Lavish screenshot, consolidated live results, and product CLI transcript show four completed tasks, including Backpass A and preserved captain note text.
Choose legacy Reconcile after an earlier answer or versioned reconcile; neither intake receives the superseded choice ✅ pass live The real suppress deck exercised 16 combinations of answer/choice, bare/annotated reconcile, and legacy/versioned preceding choices. All corresponding tasks remained held; reconciles output was empty;…
Choose an ordinary answer or versioned reconcile after legacy Reconcile; the latest valid choice controls routing ✅ pass live The real reverse deck closed three tasks with their final A choices and created exactly one note-bearing versioned reconcile request while leaving that task held.
Submit forged, malformed, or structurally uncertain rows; they cannot close held tasks or replace a valid earlier choice ✅ pass live The real guards capture rejected freeform prose, a qualified key, unknown schema, unversioned selection, empty/object answers, object notes, and an unsupported close mode. Only the earlier valid A pre…
Submit a valid legacy answer from an unbound source; capture succeeds without closing its task ✅ pass live The real unbound source captured its valid A choice, but produced no intake delivery; tasks-axi reported unbound-call as queued and held.
Replay captured legacy answers with their original source and sequence; existing resolutions remain unchanged ✅ pass live The real keyed-answer intake accepted all four replayed answers with zero skips, and the persisted backlog was byte-for-byte unchanged.

Legacy answers queued in real Lavish

Evidence: Consolidated live results, raw captures, baseline comparison, and replay evidence

Source: Consolidated live results, raw captures, baseline comparison, and replay evidence

{
  "sources": {
    "ordinary": "lavish-53b7a2f80d4ae0c6",
    "suppress": "lavish-5ead1811a4f6977c",
    "reverse": "lavish-69722a80cbcb9b20",
    "guards": "lavish-5d3eb6e808355bd6",
    "unbound": "lavish-32f5e6ea360f1c1b"
  },
  "urls": {
    "ordinary": "http://127.0.0.1:54468/session/53b7a2f80d4ae0c6",
    "suppress": "http://127.0.0.1:54468/session/5ead1811a4f6977c",
    "reverse": "http://127.0.0.1:54468/session/69722a80cbcb9b20",
    "guards": "http://127.0.0.1:54468/session/5d3eb6e808355bd6",
    "unbound": "http://127.0.0.1:54468/session/32f5e6ea360f1c1b"
  },
  "runtime": "lavish-axi 0.1.79",
  "delivery": {
    "ordinary": {
      "status": 0,
      "stdout": "reconciles-fed: lavish-53b7a2f80d4ae0c6\nanswers-fed: lavish-53b7a2f80d4ae0c6\nretired: lavish-53b7a2f80d4ae0c6 (adapter classified the captured result terminal)\ncaptured: ~/.no-mistakes/worktrees/32d18ed9638d/01M4FNRD2AJ451SEXVEK0B3FHW/.gate-lavish-verify-current/home/state/procevent-inbox/lavish-53b7a2f80d4ae0c6.1.result\n",
      "stderr": "not-autohandled: lavish-53b7a2f80d4ae0c6 (left for the handler; still unacknowledged)\n"
    },
    "suppress": {
      "status": 0,
      "stdout": "reconciles-fed: lavish-5ead1811a4f6977c\nanswers-fed: lavish-5ead1811a4f6977c\nretired: lavish-5ead1811a4f6977c (adapter classified the captured result terminal)\ncaptured: ~/.no-mistakes/worktrees/32d18ed9638d/01M4FNRD2AJ451SEXVEK0B3FHW/.gate-lavish-verify-current/home/state/procevent-inbox/lavish-5ead1811a4f6977c.1.result\n",
      "stderr": "not-autohandled: lavish-5ead1811a4f6977c (left for the handler; still unacknowledged)\n"
    },
    "reverse": {
      "status": 0,
      "stdout": "reconciles-fed: lavish-69722a80cbcb9b20\nanswers-fed: lavish-69722a80cbcb9b20\nretired: lavish-69722a80cbcb9b20 (adapter classified the captured result terminal)\ncaptured: ~/.no-mistakes/worktrees/32d18ed9638d/01M4FNRD2AJ451SEXVEK0B3FHW/.gate-lavish-verify-current/home/state/procevent-inbox/lavish-69722a80cbcb9b20.1.result\n",
      "stderr": "not-autohandled: lavish-69722a80cbcb9b20 (left for the handler; still unacknowledged)\n"
    },
    "guards": {
      "status": 0,
      "stdout": "reconciles-fed: lavish-5d3eb6e808355bd6\nanswers-fed: lavish-5d3eb6e808355bd6\nretired: lavish-5d3eb6e808355bd6 (adapter classified the captured result terminal)\ncaptured: ~/.no-mistakes/worktrees/32d18ed9638d/01M4FNRD2AJ451SEXVEK0B3FHW/.gate-lavish-verify-current/home/state/procevent-inbox/lavish-5d3eb6e808355bd6.1.result\n",
      "stderr": "not-autohandled: lavish-5d3eb6e808355bd6 (left for the handler; still unacknowledged)\n"
    },
    "unbound": {
      "status": 0,
      "stdout": "retired: lavish-32f5e6ea360f1c1b (adapter classified the captured result terminal)\ncaptured: ~/.no-mistakes/worktrees/32d18ed9638d/01M4FNRD2AJ451SEXVEK0B3FHW/.gate-lavish-verify-current/home/state/procevent-inbox/lavish-32f5e6ea360f1c1b.1.result\n",
      "stderr": "not-autohandled: lavish-32f5e6ea360f1c1b (left for the handler; still unacknowledged)\n"
    }
  },
  "adapter_outputs": {
    "ordinary": {
      "answers": "backpass-path\tA-upstream-optin-plus-fork-bridge\tBackpass A — empty note\nlegacy-extras\tA\tBookkeeping fields\nlegacy-note\tOther: see note\tOther: see note - Edit the plan first; keep the fork bridge\nlegacy-alias\tB (published examples)\tChoice alias\n",
      "reconciles": ""
    },
    "suppress": {
      "answers": "unrelated-answer\tB\tIndependent answer B\n",
      "reconciles": ""
    },
    "reverse": {
      "answers": "reverse-0\tA\treverse-0: latest legacy-answer\nreverse-1\tA\treverse-1: latest legacy-choice\nreverse-2\tA\treverse-2: latest versioned-answer\n",
      "reconciles": "reverse-3\tlatest reality check\n"
    },
    "guards": {
      "answers": "guard-invalid-latest\tA\tInvalid latest row — earlier valid A\n",
      "reconciles": ""
    },
    "unbound": {
      "answers": "unbound-call\tA\tUnbound ordinary choice\n",
      "reconciles": ""
    }
  },
  "task_states": {
    "suppress-0": "captain-held queued",
    "suppress-1": "captain-held queued",
    "suppress-10": "captain-held queued",
    "suppress-11": "captain-held queued",
    "suppress-12": "captain-held queued",
    "suppress-13": "captain-held queued",
    "suppress-14": "captain-held queued",
    "suppress-15": "captain-held queued",
    "suppress-2": "captain-held queued",
    "suppress-3": "captain-held queued",
    "suppress-4": "captain-held queued",
    "suppress-5": "captain-held queued",
    "suppress-6": "captain-held queued",
    "suppress-7": "captain-held queued",
    "suppress-8": "captain-held queued",
    "suppress-9": "captain-held queued",
    "reverse-3": "captain-held queued",
    "guard-close": "captain-held queued",
    "guard-empty": "captain-held queued",
    "guard-freeform": "captain-held queued",
    "guard-note-object": "captain-held queued",
    "guard-object": "captain-held queued",
    "guard-schema": "captain-held queued",
    "guard-selection": "captain-held queued",
    "unbound-call": "captain-held queued",
    "reverse-2": "done",
    "reverse-1": "done",
    "guard-invalid-latest": "done",
    "reverse-0": "done",
    "unrelated-answer": "done",
    "legacy-alias": "done",
    "legacy-note": "done",
    "legacy-extras": "done",
    "backpass-path": "done"
  },
  "reconcile_requests": "reverse-3\trequested=2026-10-09T08:38:05Z\tsource=the captured result lavish-69722a80cbcb9b20 sequence 1; captain note: latest reality check\nreconcile-requests: 1\n",
  "safe_replay": {
    "status": 0,
    "stdout": "closed: backpass-path\nclosed: legacy-extras\nclosed: legacy-note\nclosed: legacy-alias\nanswers: closed=4 skipped=0\n",
    "stderr": "",
    "backlog_unchanged": true
  },
  "base_adapter_answers": "",
  "current_adapter_answers": "backpass-path\tA-upstream-optin-plus-fork-bridge\tBackpass A — empty note\nlegacy-extras\tA\tBookkeeping fields\nlegacy-note\tOther: see note\tOther: see note - Edit the plan first; keep the fork bridge\nlegacy-alias\tB (published examples)\tChoice alias\n",
  "actual_lavish_captures": {
    "ordinary": "session:\n  file: ~/.no-mistakes/worktrees/32d18ed9638d/01M4FNRD2AJ451SEXVEK0B3FHW/.gate-lavish-verify-current/ordinary.html\n  status: feedback\n  session_ended: true\n  ended_by: user\nprompts[4]{uid,prompt,selector,tag,text}:\n  \"1\",\"Backpass A — empty note\\n\\nContext data:\\n{\\n  \\\"question\\\": \\\"backpass-path\\\",\\n  \\\"answer\\\": \\\"A-upstream-optin-plus-fork-bridge\\\",\\n  \\\"note\\\": \\\"\\\"\\n}\",form#row-0,choice,Backpass A — empty note\n  \"2\",\"Bookkeeping fields\\n\\nContext data:\\n{\\n  \\\"question\\\": \\\"legacy-extras\\\",\\n  \\\"answer\\\": \\\"A\\\",\\n  \\\"note\\\": \\\"\\\",\\n  \\\"task\\\": \\\"not-the-key\\\",\\n  \\\"owner\\\": \\\"lane\\\",\\n  \\\"recommended\\\": \\\"B\\\",\\n  \\\"decision_key\\\": \\\"not-the-key\\\"\\n}\",form#row-1,choice,Bookkeeping fields\n  \"3\",\"Other: see note\\n\\nContext data:\\n{\\n  \\\"question\\\": \\\"legacy-note\\\",\\n  \\\"answer\\\": \\\"Other: see note\\\",\\n  \\\"note\\\": \\\"Edit the plan first; keep the fork bridge\\\"\\n}\",form#row-2,choice,\"Other: see note\"\n  \"4\",\"Choice alias\\n\\nContext data:\\n{\\n  \\\"question\\\": \\\"legacy-alias\\\",\\n  \\\"choice\\\": \\\"B (published examples)\\\",\\n  \\\"note\\\": \\\"\\\"\\n}\",form#row-3,choice,Choice alias\nnext_step: This was the last feedback before the user ended the session. Stop polling ~/.no-mistakes/worktrees/32d18ed9638d/01M4FNRD2AJ451SEXVEK0B3FHW/.gate-lavish-verify-current/ordinary.html and do not reopen it - deliver any remaining updates directly in this conversation instead. Only run `lavish-axi ~/.no-mistakes/worktrees/32d18ed9638d/01M4FNRD2AJ451SEXVEK0B3FHW/.gate-lavish-verify-current/ordinary.html --reopen` if the user explicitly asks for further review or something genuinely important needs their visual attention.\ndom_snapshot: \"uid=5 body \\\"Live legacy answer validation: ordinary Disposable review deck. Qu

... [30795 bytes truncated] ...

string answer\\n\\nContext data:\\n{\\n  \\\"question\\\": \\\"guard-object\\\",\\n  \\\"answer\\\": {\\n    \\\"picked\\\": \\\"A\\\"\\n  }\\n}\",form#row-5,choice,Non-string answer\n  \"7\",\"Non-string note\\n\\nContext data:\\n{\\n  \\\"question\\\": \\\"guard-note-object\\\",\\n  \\\"answer\\\": \\\"A\\\",\\n  \\\"note\\\": [\\n    \\\"prose\\\"\\n  ]\\n}\",form#row-6,choice,Non-string note\n  \"8\",\"Unsupported close mode\\n\\nContext data:\\n{\\n  \\\"question\\\": \\\"guard-close\\\",\\n  \\\"answer\\\": \\\"A\\\",\\n  \\\"close\\\": \\\"erase\\\"\\n}\",form#row-7,choice,Unsupported close mode\n  \"9\",\"Invalid latest row — earlier valid A\\n\\nContext data:\\n{\\n  \\\"question\\\": \\\"guard-invalid-latest\\\",\\n  \\\"answer\\\": \\\"A\\\",\\n  \\\"note\\\": \\\"\\\"\\n}\",form#row-8,choice,Invalid latest row — earlier valid A\n  \"10\",\"Invalid latest row — note is an object\\n\\nContext data:\\n{\\n  \\\"question\\\": \\\"guard-invalid-latest\\\",\\n  \\\"answer\\\": \\\"B\\\",\\n  \\\"note\\\": {\\n    \\\"bad\\\": true\\n  }\\n}\",form#row-9,choice,Invalid latest row — note is an object\nnext_step: This was the last feedback before the user ended the session. Stop polling ~/.no-mistakes/worktrees/32d18ed9638d/01M4FNRD2AJ451SEXVEK0B3FHW/.gate-lavish-verify-current/guards.html and do not reopen it - deliver any remaining updates directly in this conversation instead. Only run `lavish-axi ~/.no-mistakes/worktrees/32d18ed9638d/01M4FNRD2AJ451SEXVEK0B3FHW/.gate-lavish-verify-current/guards.html --reopen` if the user explicitly asks for further review or something genuinely important needs their visual attention.\ndom_snapshot: \"uid=11 body \\\"Live legacy answer validation: guards Disposable review deck. Queue the choices \\\"\\n  uid=12 h1 \\\"Live legacy answer validation: guards\\\"\\n  uid=13 p \\\"Disposable review deck. Queue the choices below, then use Lavish’s Send to Agent\\\"\\n  uid=14 main \\\"Forged freeform key { 'question': 'guard-freeform', 'answer': 'A', 'note': '' } \\\"\\n    uid=1 form \\\"Forged freeform key { 'question': 'guard-freeform', 'answer': 'A', 'note': '' } \\\"\\n      uid=15 p \\\"Forged freeform key\\\"\\n      uid=16 pre \\\"{ 'question': 'guard-freeform', 'answer': 'A', 'note': '' }\\\"\\n      uid=17 button \\\"Queued: Forged freeform key\\\"\\n    uid=2 form \\\"Qualified owner key { 'question': 'lane/guard-qualified', 'answer': 'A', 'owner'\\\"\\n      uid=18 p \\\"Qualified owner key\\\"\\n      uid=19 pre \\\"{ 'question': 'lane/guard-qualified', 'answer': 'A', 'owner': 'lane' }\\\"\\n      uid=20 button \\\"Queued: Qualified owner key\\\"\\n    uid=3 form \\\"Unknown schema { 'schema': 'other.v9', 'question': 'guard-schema', 'answer': 'A'\\\"\\n      uid=21 p \\\"Unknown schema\\\"\\n      uid=22 pre \\\"{ 'schema': 'other.v9', 'question': 'guard-schema', 'answer': 'A', 'note': '' }\\\"\\n      uid=23 button \\\"Queued: Unknown schema\\\"\\n    uid=4 form \\\"Selection without schema { 'question': 'guard-selection', 'selection': 'A', 'ans\\\"\\n      uid=24 p \\\"Selection without schema\\\"\\n      uid=25 pre \\\"{ 'question': 'guard-selection', 'selection': 'A', 'answer': 'A', 'note': '' }\\\"\\n      uid=26 button \\\"Queued: Selection without schema\\\"\\n    uid=5 form \\\"Note without answer { 'question': 'guard-empty', 'answer': '', 'note': 'only pro\\\"\\n      uid=27 p \\\"Note without answer\\\"\\n      uid=28 pre \\\"{ 'question': 'guard-empty', 'answer': '', 'note': 'only prose' }\\\"\\n      uid=29 button \\\"Queued: Note without answer\\\"\\n    uid=6 form \\\"Non-string answer { 'question': 'guard-object', 'answer': { 'picked': 'A' } } Qu\\\"\\n      uid=30 p \\\"Non-string answer\\\"\\n      uid=31 pre \\\"{ 'question': 'guard-object', 'answer': { 'picked': 'A' } }\\\"\\n      uid=32 button \\\"Queued: Non-string answer\\\"\\n    uid=7 form \\\"Non-string note { 'question': 'guard-note-object', 'answer': 'A', 'note': [ 'pro\\\"\\n      uid=33 p \\\"Non-string note\\\"\\n      uid=34 pre \\\"{ 'question': 'guard-note-object', 'answer': 'A', 'note': [ 'prose' ] }\\\"\\n      uid=35 button \\\"Queued: Non-string note\\\"\\n    uid=8 form \\\"Unsupported close mode { 'question': 'guard-close', 'answer': 'A', 'close': 'era\\\"\\n      uid=36 p \\\"Unsupported close mode\\\"\\n      uid=37 pre \\\"{ 'question': 'guard-close', 'answer': 'A', 'close': 'erase' }\\\"\\n      uid=38 button \\\"Queued: Unsupported close mode\\\"\\n    uid=9 form \\\"Invalid latest row — earlier valid A { 'question': 'guard-invalid-latest', 'answ\\\"\\n      uid=39 p \\\"Invalid latest row — earlier valid A\\\"\\n      uid=40 pre \\\"{ 'question': 'guard-invalid-latest', 'answer': 'A', 'note': '' }\\\"\\n      uid=41 button \\\"Queued: Invalid latest row — earlier valid A\\\"\\n    uid=10 form \\\"Invalid latest row — note is an object { 'question': 'guard-invalid-latest', 'an\\\"\\n      uid=42 p \\\"Invalid latest row — note is an object\\\"\\n      uid=43 pre \\\"{ 'question': 'guard-invalid-latest', 'answer': 'B', 'note': { 'bad': true } }\\\"\\n      uid=44 button \\\"Queued: Invalid latest row — note is an object\\\"\\n  uid=45 script \\\"const rows = [{'label': 'Forged freeform key', 'tag': 'message', 'data': {'quest\\\"\\n  uid=46 script\"\n",
    "unbound": "session:\n  file: ~/.no-mistakes/worktrees/32d18ed9638d/01M4FNRD2AJ451SEXVEK0B3FHW/.gate-lavish-verify-current/unbound.html\n  status: feedback\n  session_ended: true\n  ended_by: user\nprompts[1]{uid,prompt,selector,tag,text}:\n  \"1\",\"Unbound ordinary choice\\n\\nContext data:\\n{\\n  \\\"question\\\": \\\"unbound-call\\\",\\n  \\\"answer\\\": \\\"A\\\",\\n  \\\"note\\\": \\\"\\\"\\n}\",form#row-0,choice,Unbound ordinary choice\nnext_step: This was the last feedback before the user ended the session. Stop polling ~/.no-mistakes/worktrees/32d18ed9638d/01M4FNRD2AJ451SEXVEK0B3FHW/.gate-lavish-verify-current/unbound.html and do not reopen it - deliver any remaining updates directly in this conversation instead. Only run `lavish-axi ~/.no-mistakes/worktrees/32d18ed9638d/01M4FNRD2AJ451SEXVEK0B3FHW/.gate-lavish-verify-current/unbound.html --reopen` if the user explicitly asks for further review or something genuinely important needs their visual attention.\ndom_snapshot: \"uid=2 body \\\"Live legacy answer validation: unbound Disposable review deck. Queue the choices\\\"\\n  uid=3 h1 \\\"Live legacy answer validation: unbound\\\"\\n  uid=4 p \\\"Disposable review deck. Queue the choices below, then use Lavish’s Send to Agent\\\"\\n  uid=5 main \\\"Unbound ordinary choice { 'question': 'unbound-call', 'answer': 'A', 'note': '' \\\"\\n    uid=1 form \\\"Unbound ordinary choice { 'question': 'unbound-call', 'answer': 'A', 'note': '' \\\"\\n      uid=6 p \\\"Unbound ordinary choice\\\"\\n      uid=7 pre \\\"{ 'question': 'unbound-call', 'answer': 'A', 'note': '' }\\\"\\n      uid=8 button \\\"Queued: Unbound ordinary choice\\\"\\n  uid=9 script \\\"const rows = [{'label': 'Unbound ordinary choice', 'data': {'question': 'unbound\\\"\\n  uid=10 script\"\n"
  },
  "focused_regressions": {
    "initial_command": "bash tests/fm-captain-hold-lifecycle.test.sh test_unversioned_deck_shapes_with_extra_fields_still_route test_legacy_reconcile_replaces_previous_choices test_bound_channel_answers_close_at_answer_time test_unbound_source_closes_no_hold",
    "initial_result": "First two selectors passed; command reached its 240-second deadline during the next selector.",
    "remaining_command": "bash tests/fm-captain-hold-lifecycle.test.sh test_bound_channel_answers_close_at_answer_time test_unbound_source_closes_no_hold",
    "remaining_result": "Both selectors passed; exit 0, wall time 220.91 seconds."
  },
  "cleanup": {
    "browser_tabs": "all five closed",
    "procevent_list": "no sources registered",
    "isolated_server": "stopped; exit 0, port 54468",
    "disposable_workspace": "Removed .gate-lavish-verify-current and bin/.gate-lavish-baseline.sh; evidence retained only in the designated evidence directory."
  }
}
Evidence: Product CLI task resolutions and unchanged replay state

Source: Product CLI task resolutions and unchanged replay state

$ (cd isolated-home && tasks-axi show backpass-path --full)
task:
  id: backpass-path
  title: Live validation backpass-path
  state: done
  blocked: no
  blocked_by: none
  held: no
  hold_reason: "fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24="
  hold_kind: captain
  hold_until: "-"
  kind: captain
  repo: sample
  priority: "-"
  created: "-"
  closed: 2026-10-09
  deps: none
  links: none
  body: "Resolution recorded by fm-captain-hold.\nDecision digest: 77c460e7307299a3f392918dafea845ac185515e30c4ff9e79de1ef69a802258\nResolution mode: answered\n\nCaptain decision:\nCaptain answered this call through the captured result lavish-53b7a2f80d4ae0c6 sequence 1.\nTask: backpass-path\nAnswer: A-upstream-optin-plus-fork-bridge\nAnswer as shown to the captain: Backpass A — empty note"


$ (cd isolated-home && tasks-axi show legacy-note --full)
task:
  id: legacy-note
  title: Live validation legacy-note
  state: done
  blocked: no
  blocked_by: none
  held: no
  hold_reason: "fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24="
  hold_kind: captain
  hold_until: "-"
  kind: captain
  repo: sample
  priority: "-"
  created: "-"
  closed: 2026-10-09
  deps: none
  links: none
  body: "Resolution recorded by fm-captain-hold.\nDecision digest: a32e3a618759d57fef79d82b74d7a3ef14c53d528d9eb29e69a4763394aa6b3f\nResolution mode: answered\n\nCaptain decision:\nCaptain answered this call through the captured result lavish-53b7a2f80d4ae0c6 sequence 1.\nTask: legacy-note\nAnswer: Other: see note\nAnswer as shown to the captain: Other: see note - Edit the plan first; keep the fork bridge"


$ (cd isolated-home && tasks-axi show suppress-0 --full)
task:
  id: suppress-0
  title: Live validation suppress-0
  state: queued
  blocked: no
  blocked_by: none
  held: yes
  hold_reason: "fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24="
  hold_kind: captain
  hold_until: "-"
  kind: captain
  repo: sample
  priority: "-"
  created: 2026-10-09
  closed: "-"
  deps: none
  links: none
  body: "Captain hold set: 2026-10-09T08:27:25Z"


$ (cd isolated-home && tasks-axi show reverse-3 --full)
task:
  id: reverse-3
  title: Live validation reverse-3
  state: queued
  blocked: no
  blocked_by: none
  held: yes
  hold_reason: "fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24="
  hold_kind: captain
  hold_until: "-"
  kind: captain
  repo: sample
  priority: "-"
  created: 2026-10-09
  closed: "-"
  deps: none
  links: none
  body: "Captain hold set: 2026-10-09T08:34:41Z"


$ (cd isolated-home && tasks-axi show unbound-call --full)
task:
  id: unbound-call
  title: Live validation unbound-call
  state: queued
  blocked: no
  blocked_by: none
  held: yes
  hold_reason: "fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24="
  hold_kind: captain
  hold_until: "-"
  kind: captain
  repo: sample
  priority: "-"
  created: 2026-10-09
  closed: "-"
  deps: none
  links: none
  body: "Captain hold set: 2026-10-09T08:36:18Z"

$ fm-captain-hold.sh reconcile list
reverse-3	requested=2026-10-09T08:38:05Z	source=the captured result lavish-69722a80cbcb9b20 sequence 1; captain note: latest reality check
reconcile-requests: 1

$ replay captured legacy answers with identical source and sequence
closed: backpass-path
closed: legacy-extras
closed: legacy-note
closed: legacy-alias
answers: closed=4 skipped=0
Persisted backlog byte-for-byte unchanged: True
Evidence: Persisted backlog after live routing

Source: Persisted backlog after live routing

## In flight

## Queued
- [ ] suppress-0 - Live validation suppress-0 (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:27:25Z
- [ ] suppress-1 - Live validation suppress-1 (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:27:52Z
- [ ] suppress-10 - Live validation suppress-10 (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:28:10Z
- [ ] suppress-11 - Live validation suppress-11 (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:28:34Z
- [ ] suppress-12 - Live validation suppress-12 (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:30:30Z
- [ ] suppress-13 - Live validation suppress-13 (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:30:46Z
- [ ] suppress-14 - Live validation suppress-14 (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:31:04Z
- [ ] suppress-15 - Live validation suppress-15 (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:31:35Z
- [ ] suppress-2 - Live validation suppress-2 (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:32:08Z
- [ ] suppress-3 - Live validation suppress-3 (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:32:22Z
- [ ] suppress-4 - Live validation suppress-4 (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:32:59Z
- [ ] suppress-5 - Live validation suppress-5 (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:33:11Z
- [ ] suppress-6 - Live validation suppress-6 (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:33:27Z
- [ ] suppress-7 - Live validation suppress-7 (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:33:35Z
- [ ] suppress-8 - Live validation suppress-8 (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:33:48Z
- [ ] suppress-9 - Live validation suppress-9 (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:34:01Z
- [ ] reverse-3 - Live validation reverse-3 (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:34:41Z
- [ ] guard-close - Live validation guard-close (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:34:58Z
- [ ] guard-empty - Live validation guard-empty (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:35:21Z
- [ ] guard-freeform - Live validation guard-freeform (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:35:31Z
- [ ] guard-note-object - Live validation guard-note-object (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:35:54Z
- [ ] guard-object - Live validation guard-object (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:36:00Z
- [ ] guard-schema - Live validation guard-schema (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:36:07Z
- [ ] guard-selection - Live validation guard-selection (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:36:13Z
- [ ] unbound-call - Live validation unbound-call (repo: sample) (kind: captain) (since 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Captain hold set: 2026-10-09T08:36:18Z
## Done
- [x] reverse-2 - Live validation reverse-2 (repo: sample) (kind: captain) (done 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Resolution recorded by fm-captain-hold.
  Decision digest: cfd1b03e00d574c5e4f2bca0bc2c42e7be27544cc7cce11fcfee5b335f83f459
  Resolution mode: answered

  Captain decision:
  Captain answered this call through the captured result lavish-69722a80cbcb9b20 sequence 1.
  Task: reverse-2
  Answer: A
  Answer as shown to the captain: reverse-2: latest versioned-answer

- [x] reverse-1 - Live validation reverse-1 (repo: sample) (kind: captain) (done 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Resolution recorded by fm-captain-hold.
  Decision digest: da5685bb89beadda9bb77ecf96cf35c4a85fa40fb1490e183243057fd1734172
  Resolution mode: answered

  Captain decision:
  Captain answered this call through the captured result lavish-69722a80cbcb9b20 sequence 1.
  Task: reverse-1
  Answer: A
  Answer as shown to the captain: reverse-1: latest legacy-choice

- [x] guard-invalid-latest - Live validation guard-invalid-latest (repo: sample) (kind: captain) (done 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Resolution recorded by fm-captain-hold.
  Decision digest: 2d0106f708b9826fce5e8cfa5d3e6524806d55440476c6ee36e73092a8d42f31
  Resolution mode: answered

  Captain decision:
  Captain answered this call through the captured result lavish-5d3eb6e808355bd6 sequence 1.
  Task: guard-invalid-latest
  Answer: A
  Answer as shown to the captain: Invalid latest row — earlier valid A

- [x] reverse-0 - Live validation reverse-0 (repo: sample) (kind: captain) (done 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Resolution recorded by fm-captain-hold.
  Decision digest: c41d8ab5e7ade9a61c6f702cafd479d08fbe63b1c6686800b241770fed0b2bd3
  Resolution mode: answered

  Captain decision:
  Captain answered this call through the captured result lavish-69722a80cbcb9b20 sequence 1.
  Task: reverse-0
  Answer: A
  Answer as shown to the captain: reverse-0: latest legacy-answer

- [x] unrelated-answer - Live validation unrelated-answer (repo: sample) (kind: captain) (done 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Resolution recorded by fm-captain-hold.
  Decision digest: 20fbd22a5cd8a98d6abd709a68816bee84190352f2a9cef32ad6b144d9986184
  Resolution mode: answered

  Captain decision:
  Captain answered this call through the captured result lavish-5ead1811a4f6977c sequence 1.
  Task: unrelated-answer
  Answer: B
  Answer as shown to the captain: Independent answer B

- [x] legacy-alias - Live validation legacy-alias (repo: sample) (kind: captain) (done 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Resolution recorded by fm-captain-hold.
  Decision digest: e46daaba8410dfa254dd0fc48d9bdd4f12004ef9abae814f2566044562ab4ff3
  Resolution mode: answered

  Captain decision:
  Captain answered this call through the captured result lavish-53b7a2f80d4ae0c6 sequence 1.
  Task: legacy-alias
  Answer: B (published examples)
  Answer as shown to the captain: Choice alias

- [x] legacy-note - Live validation legacy-note (repo: sample) (kind: captain) (done 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Resolution recorded by fm-captain-hold.
  Decision digest: a32e3a618759d57fef79d82b74d7a3ef14c53d528d9eb29e69a4763394aa6b3f
  Resolution mode: answered

  Captain decision:
  Captain answered this call through the captured result lavish-53b7a2f80d4ae0c6 sequence 1.
  Task: legacy-note
  Answer: Other: see note
  Answer as shown to the captain: Other: see note - Edit the plan first; keep the fork bridge

- [x] legacy-extras - Live validation legacy-extras (repo: sample) (kind: captain) (done 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Resolution recorded by fm-captain-hold.
  Decision digest: eb229410e20c9595347339c266bcfea4a6da504fb97d0b6c50151b596cc92f58
  Resolution mode: answered

  Captain decision:
  Captain answered this call through the captured result lavish-53b7a2f80d4ae0c6 sequence 1.
  Task: legacy-extras
  Answer: A
  Answer as shown to the captain: Bookkeeping fields

- [x] backpass-path - Live validation backpass-path (repo: sample) (kind: captain) (done 2026-10-09) (hold: fm-hold-v1:aXNvbGF0ZWQgbGVnYWN5IGRlY2lzaW9uIHZhbGlkYXRpb24=) (hold-kind: captain)
  Resolution recorded by fm-captain-hold.
  Decision digest: 77c460e7307299a3f392918dafea845ac185515e30c4ff9e79de1ef69a802258
  Resolution mode: answered

  Captain decision:
  Captain answered this call through the captured result lavish-53b7a2f80d4ae0c6 sequence 1.
  Task: backpass-path
  Answer: A-upstream-optin-plus-fork-bridge
  Answer as shown to the captain: Backpass A — empty note

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

⚠️ **Review** - 1 error
  • 🚨 bin/fm-procevent-lavish.sh:827 - A later legacy Reconcile choice does not invalidate an earlier ordinary answer for the same question. For example, a capture containing {question:"sample-call",answer:"A",note:""} followed by {question:"sample-call",answer:"reconcile",note:"check first"} now emits A: the second row exits before the last-choice replacement at line 846. The bound runner consequently closes the held task using the superseded answer. Before this change, both note-bearing rows were skipped. The same invariant must hold for the answer/choice alternatives at line 823, bare and annotated reconcile values at line 827, duplicate replacement at line 846, and both answers/reconciles outputs at lines 853–866. Resolve the latest structurally valid choice per question before filtering legacy reconcile values, so those values suppress earlier answers without entering either intake.
  • 🚨 bin/fm-procevent-lavish.sh:821 - The required recovery is absent from this deliverable. The authoritative criterion is “adapt the legacy shape and replay unrouted captured answers safely”; the changed hunk only broadens the unversioned extraction branch, and the new test at tests/fm-captain-hold-lifecycle.test.sh:1810 feeds a fresh synthetic capture once. Existing routing runs only after a new capture (bin/fm-procevent.sh:1373); restart reconciliation merely republishes pending notifications (lines 1688 and 895–903), without feeding stored answers. Thus upgrading the adapter alone does not route previously captured answers such as the reported Backpass capture. Deliver a bounded replay procedure or executable recovery path using the existing binding and keyed-answer intake, preserving original source/sequence provenance and reporting applied, already-resolved, and unresolved outcomes, together with recovery evidence. This is an unmet intent requirement, not a request for general retry machinery.

🔧 Fix applied.
1 error still open:

  • 🚨 bin/fm-procevent-lavish.sh:821 - The required recovery is absent from this deliverable. The authoritative criterion is “adapt the legacy shape and replay unrouted captured answers safely”; the changed hunk only broadens the unversioned extraction branch, and the new test at tests/fm-captain-hold-lifecycle.test.sh:1810 feeds a fresh synthetic capture once. Existing routing runs only after a new capture (bin/fm-procevent.sh:1373); restart reconciliation merely republishes pending notifications (lines 1688 and 895–903), without feeding stored answers. Thus upgrading the adapter alone does not route previously captured answers such as the reported Backpass capture. Deliver a bounded replay procedure or executable recovery path using the existing binding and keyed-answer intake, preserving original source/sequence provenance and reporting applied, already-resolved, and unresolved outcomes, together with recovery evidence. This is an unmet intent requirement, not a request for general retry machinery.
✅ **Test** - passed

✅ No issues found.

  • Live validation: ✅ go - 6 of 6 scenarios driven live against the product
Scenario Result Live Evidence
Submit legacy answers with notes, bookkeeping fields, and the choice alias; matching held tasks close ✅ pass live Ordinary Lavish screenshot, consolidated live results, and product CLI transcript show four completed tasks, including Backpass A and preserved captain note text.
Choose legacy Reconcile after an earlier answer or versioned reconcile; neither intake receives the superseded choice ✅ pass live The real suppress deck exercised 16 combinations of answer/choice, bare/annotated reconcile, and legacy/versioned preceding choices. All corresponding tasks remained held; reconciles output was empty;…
Choose an ordinary answer or versioned reconcile after legacy Reconcile; the latest valid choice controls routing ✅ pass live The real reverse deck closed three tasks with their final A choices and created exactly one note-bearing versioned reconcile request while leaving that task held.
Submit forged, malformed, or structurally uncertain rows; they cannot close held tasks or replace a valid earlier choice ✅ pass live The real guards capture rejected freeform prose, a qualified key, unknown schema, unversioned selection, empty/object answers, object notes, and an unsupported close mode. Only the earlier valid A pre…
Submit a valid legacy answer from an unbound source; capture succeeds without closing its task ✅ pass live The real unbound source captured its valid A choice, but produced no intake delivery; tasks-axi reported unbound-call as queued and held.
Replay captured legacy answers with their original source and sequence; existing resolutions remain unchanged ✅ pass live The real keyed-answer intake accepted all four replayed answers with zero skips, and the persisted backlog was byte-for-byte unchanged.
  • Started real lavish-axi server --verbose version 0.1.79 on private port 54468 with worktree-local LAVISH_AXI_STATE_DIR and isolated FM_HOME.
  • Created held tasks using bin/fm-captain-hold.sh hold, explicitly bound four sources, and registered real Lavish polling through bin/fm-procevent.sh register lavish ... -- bin/fm-procevent-lavish.sh poll ....
  • Drove five actual Lavish browser decks: clicked their choice controls and Send & End, then observed real runner captures, adapter outputs, persisted task resolutions, and reconcile requests.
  • Executed the base-commit adapter against feedback captured during this run: it emitted no ordinary legacy answers; the current adapter emitted all four.
  • Replayed the ordinary capture through bin/fm-captain-hold.sh answers --source 'the captured result lavish-53b7a2f80d4ae0c6 sequence 1'; all four deliveries were accepted and the persisted backlog remained byte-for-byte unchanged.
  • Ran bash tests/fm-captain-hold-lifecycle.test.sh test_unversioned_deck_shapes_with_extra_fields_still_route test_legacy_reconcile_replaces_previous_choices test_bound_channel_answers_close_at_answer_time test_unbound_source_closes_no_hold. The first two selectors passed before the command reached its 240-second deadline.
  • Ran the remaining selectors separately: bash tests/fm-captain-hold-lifecycle.test.sh test_bound_channel_answers_close_at_answer_time test_unbound_source_closes_no_hold; both passed.
  • Inspected screenshots and tasks-axi show <task-id> --full output; closed all test tabs, stopped the isolated server, confirmed no sources remained registered, and removed this run's disposable worktree files.
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

…ce field

The Lavish answers adapter only read an unversioned question/answer row when it
had no note field. Lane-composed decision decks emit note, task, owner,
recommended and decision_key beside answer, and some name the pick choice, so
their captured answers produced no keyed row and never reached the intake.

Require only a slug-shaped question and one nonempty string answer (or choice)
for a row with no schema and no selection, keep the reserved reconcile values
refused, and append a nonempty note to the label so the record keeps the
captain words.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant