Skip to content

fix: guard omp launches against missing or invalid default roles - #68

Merged
MrGTV-love merged 12 commits into
mainfrom
fm/fm-omp-global-roles-overwrite
Oct 9, 2026
Merged

MrGTV-love merged 12 commits into
mainfrom
fm/fm-omp-global-roles-overwrite

Conversation

@MrGTV-love

@MrGTV-love MrGTV-love commented Oct 9, 2026 •

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 preventing Vernant from getting built. A recommended architecture should come with proof.

Context: omp (Oh My Pi) keeps its model roles in one shared global file (~/.omp/agent/config.yml, modelRoleStorage: global). modelRoles.default was lost from that file. omp did not fail. It silently picked the first model with credentials, google/gemini-3.1-pro-preview, which is free tier and answers HTTP 429. Pipeline runs and omp worker launches failed because of it. Isolated repro with omp 18.8.1 shows a missing default and an unresolvable default both resolve to that model; --config overlay beats the global file; --model beats both.

Decisions already made (deliberate, not mistakes):

  1. Ship W only: bin/fm-spawn.sh must refuse an omp launch with no --model whose shared default role is missing or names a model absent from the omp catalog, and print the exact remedy (pass --model / or a dispatch profile, or restore the Default role with /model). It needs a behavioral test that fails on the old code and passes on the new.
  2. Do NOT add a no-mistakes agent_config model pin for acp:omp (option E). The captain ruled static model pins a defect: every agent role selects models dynamically. The pipeline half is tracked under backlog item fm-review-agent-dynamic-selector. The guard therefore covers fm-spawn launches only; it does not touch the pipeline agent and does not edit captain-private config.
  3. The guard keeps the existing validation contract: an unreadable listing or config establishes nothing (launch proceeds), an unknown provider passes with a notice, a bare fuzzy pattern is omp's job. A known thinking suffix (:off|minimal|low|medium|high|xhigh|max|auto) is stripped from the default role before the catalog check; other colons stay, because model ids can contain them. The existing omp_model_validate behaviour and messages are unchanged; it now shares omp_catalog_verdict.
  4. The guard reads the global config only. It ignores --config overlays; the repo overlays set no role. Known and accepted gap.
  5. Writer of the lost role: omp itself, from interactive sessions (a Vernant session changed the default with /model at 21:48:52Z, and that proves such a change writes the shared file). The exact action that cleared it between 21:50:24Z and 21:54:36Z is not recorded. Firstmate code never writes that file.

Tests are behavioral only (fake omp executable driving fm-spawn; five cases in tests/fm-omp-harness.test.sh). Do not add source-text assertions. Do not change ~/.no-mistakes/config.yaml or other captain-private config.

What Changed

  • Refuse omp launches without an effective model override when the readable shared Default role is missing or names an unlisted model from a known provider, and print explicit recovery instructions.
  • Inspect global configuration read-only, strip recognized thinking suffixes for catalog checks, and align validation with the launch’s model and agent directory while preserving pass-through behavior for uncertain evidence and profile-selected launches.
  • Add behavioral regression coverage for default-role failures, overrides, directory selection, profiles, and raw shell commands; document the guard’s remedies and evidence limits.

Risk Assessment

✅ Low: The changes are bounded to the authorized launch guard and its regression coverage, with no additional material defects or unrequired components substantiated in this pass.

Testing

Live CLI admission and real omp RPC checks passed, including colon-preserving model selection and long-glob pass-through without catalog probing; baseline ancestry and early timing limitations were addressed with focused selectors and serialized verification. The fake-harness regression demonstrated fixed-code success and old-regex timeout failure, but did not establish a live result for the bounded external-timeout scenario. CLI/RPC evidence was retained and disposable fixtures removed.

  • Live validation: ✅ go - 13 of 14 scenarios driven live against the product
Scenario Result Live Evidence
Spawn unpinned omp with no Default role: refuse before task creation and print the exact remedy ✅ pass live Live spawn transcript: missing-default; exit 1, no task metadata, configuration byte-identical, full remedy printed.
Spawn with an unlisted Default role and thinking suffix: refuse using the real provider catalog ✅ pass live Live spawn transcript: unlisted-default; apple/definitely-missing-model:high refused against installed omp's catalog.
Set a valid project role while the global role is missing: project settings cannot mask the refusal ✅ pass live Live spawn transcript: project-cannot-mask-global; refused with no task metadata and unchanged global configuration.
Use a literal raw omp command with a known agent directory and redirection: invalid Default role still refuses ✅ pass live Live spawn transcript: literal-raw-refused; supplemental literal-boundary checks covered all supported quoting forms and verified redirections were not executed.
Pass a long unquoted path ending in a glob: launch unchanged without inspecting the Default-role catalog ✅ pass live live-omp-long-glob-rpc.txt: actual validator execution, genuine omp launch, no models --json invocation, and successful get_state response.
Pin an explicit model while the Default role is missing: admit the canonical launch ✅ pass live Live spawn transcript: explicit-model-overrides-missing; exit 0 and published omp task metadata.
Use a listed Default role with a known thinking suffix: admit the canonical launch ✅ pass live Live spawn transcript: listed-thinking-suffix; apple/on-device:high admitted against the real catalog.
Pin the model through native raw-command arguments: do not refuse because the shared Default role is missing ✅ pass live Live spawn transcript: raw-native-model-pin; --model=apple/on-device admitted and task metadata published.
Use a Default role from an unknown provider: print a notice and admit the launch ✅ pass live Live spawn transcript: unknown-provider-notice; notice identified fixture-extension/model:high and spawn succeeded.
Use a bare fuzzy Default-role pattern: leave matching to omp ✅ pass live Live spawn transcript: bare-fuzzy-pattern; gpt-style/provider-independent matching remained delegated and spawn was admitted.
Provide malformed global YAML: preserve its bytes and admit the launch without established role evidence ✅ pass live Live spawn transcript: malformed-config-pass-through; exit 0, published task metadata, and byte-identical malformed configuration.
Select a catalog model whose id contains a colon plus a thinking suffix: preserve the id and select the intended effort ✅ pass live real-runtime-state.json: genuine get_state response reported provider lab-local, id qwen3:8b, and thinkingLevel high.
Make the real catalog listing unreadable while the configured model is unlisted: admit rather than infer a refusal ✅ pass live live-omp-unreadable-rpc.txt and unreadable-real-catalog.txt: a disposable extension emitted a catalog preamble; fm-spawn admitted the launch and actual omp printed its help surface.
Run the bounded regression with external timeout present: execute validator stdin and distinguish fixed code from catastrophic backtracking ⏸️ untested no The prior payload records only a fake-harness behavioral regression with live=false, so it did not establish a live product result for this scenario. The separately exercised real-product long-glob sc…
Evidence: Live spawn decisions, remedies, and persisted task state

Source: Live spawn decisions, remedies, and persisted task state


SCENARIO: missing-default
exit=1; elapsed=42.722s
fm-gate-refuse: gate agent lifecycle permitted only against lab home ~/tmp/fm-lab.zds2s_pu
error: omp modelRoles.default is not set in the shared omp config, so an omp launch with no --model would silently run on the first model with credentials (a free-tier model that answers HTTP 429); pass --model <provider>/<id> (or a dispatch profile) so this launch stops depending on the shared default, or restore the Default role in omp with /model

config byte-identical before/after admission=True; task metadata exists=False
result=pass


SCENARIO: unlisted-default
exit=1; elapsed=94.959s
fm-gate-refuse: gate agent lifecycle permitted only against lab home ~/tmp/fm-lab.zds2s_pu
error: omp modelRoles.default 'apple/definitely-missing-model:high' is not listed by 'omp models --json' although provider 'apple' is, so an omp launch with no --model would silently run on the first model with credentials (a free-tier model that answers HTTP 429); pass --model <provider>/<id> (or a dispatch profile) so this launch stops depending on the shared default, or restore the Default role in omp with /model

config byte-identical before/after admission=True; task metadata exists=False
result=pass


SCENARIO: project-cannot-mask-global
exit=1; elapsed=52.641s
fm-gate-refuse: gate agent lifecycle permitted only against lab home ~/tmp/fm-lab.zds2s_pu
error: omp modelRoles.default is not set in the shared omp config, so an omp launch with no --model would silently run on the first model with credentials (a free-tier model that answers HTTP 429); pass --model <provider>/<id> (or a dispatch profile) so this launch stops depending on the shared default, or restore the Default role in omp with /model

config byte-identical before/after admission=True; task metadata exists=False
result=pass


SCENARIO: literal-raw-refused
exit=1; elapsed=101.342s
fm-gate-refuse: gate agent lifecycle permitted only against lab home ~/tmp/fm-lab.zds2s_pu
error: omp modelRoles.default is not set in the shared omp config, so an omp launch with no --model would silently run on the first model with credentials (a free-tier model that answers HTTP 429); pass --model <provider>/<id> (or a dispatch profile) so this launch stops depending on the shared default, or restore the Default role in omp with /model

config byte-identical before/after admission=True; task metadata exists=False
result=pass


SCENARIO: long-glob-pass-through
exit=0; elapsed=177.588s
fm-gate-refuse: gate agent lifecycle permitted only against lab home ~/tmp/fm-lab.zds2s_pu
skill selection for nm-long-glob-pass-through: undelivered - raw launch command has no supported brief transport
spawned nm-long-glob-pass-through harness=omp kind=scout window=primary:fm-nm-long-glob-pass-through worktree=~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/treehouse/.treehouse/live-project-6625d6/1/live-project

config byte-identical before/after admission=True; task metadata exists=True
window=primary:fm-nm-long-glob-pass-through
endpoint_task_id=nm-long-glob-pass-through
worktree=~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/treehouse/.treehouse/live-project-6625d6/1/live-project
project=~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/live-project
harness=omp
kind=scout
tasktmp=/tmp/fm-nm-long-glob-pass-through
model=default
effort=default
skill_selection=undelivered
skill_selection_reason=raw launch command has no supported brief transport
busy_gen=g1791530403.23682.24308
spawn_gen=s1791530421.77255.4413

PANE:

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
bash-3.2$ treehouse get
🌳 Setting up worktree...
🌳 Entered worktree at ~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/treehouse/.treehouse/live-projec
t-6625d6/1/live-project. Type 'exit' to return.

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
Mac-Studio:live-project charlesabrooker$ cd -- '~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/treehou
se/.treehouse/live-project-6625d6/1/live-project'
Mac-Studio:live-project charlesabrooker$ export GOTMPDIR=/tmp/fm-nm-long-glob-pass-through/gotmp
Mac-Studio:live-project charlesabrooker$ export COMPACT_ADVISER_DISABLE=1
Mac-Studio:live-project charlesabrooker$ export FM_TASK_ID=nm-long-glob-pass-through
Mac-Studio:live-project charlesabrooker$ . '/tmp/fm-nm-long-glob-pass-through+25dc40c07fbe82ae37a4e2c91abde8f4dc7339c23f9653ef3d8ecead60a4dd69/launch.s179153042
1.77255.4413.sh'






























result=pass


SCENARIO: explicit-model-overrides-missing
exit=0; elapsed=165.275s
fm-gate-refuse: gate agent lifecycle permitted only against lab home ~/tmp/fm-lab.zds2s_pu
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
●  WATCHER DOWN - SUPERVISION IS OFF
●  1 task(s) in flight, but no watcher has a fresh beacon (last beat: never, grace 300s).
●  Trust the emitted supervision protocol for this harness; do not use shell & for watcher repair.
●  This is a supervision warning only; the guarded operation WILL still run.
●  repair missing watcher supervision according to the session-start block for this harness; do not use shell &.
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
skill selection for nm-explicit-model-overrides-missing: unavailable - no TypeSafe or OpenRouter key
spawned nm-explicit-model-overrides-missing harness=omp kind=scout window=primary:fm-nm-explicit-model-overrides-missing worktree=~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/treehouse/.treehouse/live-project-6625d6/1/live-project

config byte-identical before/after admission=True; task metadata exists=True
window=primary:fm-nm-explicit-model-overrides-missing
endpoint_task_id=nm-explicit-model-overrides-missing
worktree=~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/treehouse/.treehouse/live-project-6625d6/1/live-project
project=~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/live-project
harness=omp
kind=scout
tasktmp=/tmp/fm-nm-explicit-model-overrides-missing
model=apple/on-device
effort=default
skill_selection=unavailable
skill_selection_reason=no TypeSafe or OpenRouter key
busy_gen=g1791530620.40451.7908
spawn_gen=s1791530637.97372.218

PANE:

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
bash-3.2$ treehouse get
A new version of treehouse is available: v2.3.1-fm.e58947de → v3.1.2
Run "treehouse update" to update

🌳 Setting up worktree...
🌳 Entered worktree at ~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/treehouse/.treehouse/live-projec
t-6625d6/1/live-project. Type 'exit' to return.

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
Mac-Studio:live-project charlesabrooker$ cd -- '~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/treehou
se/.treehouse/live-

... [7762 bytes truncated] ...

t interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
bash-3.2$ treehouse get
A new version of treehouse is available: v2.3.1-fm.e58947de → v3.1.2
Run "treehouse update" to update

🌳 Setting up worktree...
🌳 Entered worktree at ~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/treehouse/.treehouse/live-projec
t-6625d6/1/live-project. Type 'exit' to return.

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
Mac-Studio:live-project charlesabrooker$ cd -- '~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/treehou
se/.treehouse/live-project-6625d6/1/live-project'
Mac-Studio:live-project charlesabrooker$ export GOTMPDIR=/tmp/fm-nm-unknown-provider-notice/gotmp
Mac-Studio:live-project charlesabrooker$ export COMPACT_ADVISER_DISABLE=1
Mac-Studio:live-project charlesabrooker$ export FM_TASK_ID=nm-unknown-provider-notice
Mac-Studio:live-project charlesabrooker$ . '/tmp/fm-nm-unknown-provider-notice+25dc40c07fbe82ae37a4e2c91abde8f4dc7339c23f9653ef3d8ecead60a4dd69/launch.s17915308
50.28838.2869.sh'



























result=pass


SCENARIO: bare-fuzzy-pattern
exit=0; elapsed=54.18s
fm-gate-refuse: gate agent lifecycle permitted only against lab home ~/tmp/fm-lab.zds2s_pu
WARNING: watcher still down (same stale episode; last beat: never, grace 300s) - full banner already printed this episode.
skill selection for nm-bare-fuzzy-pattern: undelivered - raw launch command has no supported brief transport
spawned nm-bare-fuzzy-pattern harness=omp kind=scout window=primary:fm-nm-bare-fuzzy-pattern worktree=~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/treehouse/.treehouse/live-project-6625d6/1/live-project

config byte-identical before/after admission=True; task metadata exists=True
window=primary:fm-nm-bare-fuzzy-pattern
endpoint_task_id=nm-bare-fuzzy-pattern
worktree=~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/treehouse/.treehouse/live-project-6625d6/1/live-project
project=~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/live-project
harness=omp
kind=scout
tasktmp=/tmp/fm-nm-bare-fuzzy-pattern
model=default
effort=default
skill_selection=undelivered
skill_selection_reason=raw launch command has no supported brief transport
busy_gen=g1791530895.24274.8418
spawn_gen=s1791530902.42451.22286

PANE:

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
bash-3.2$ treehouse get
A new version of treehouse is available: v2.3.1-fm.e58947de → v3.1.2
Run "treehouse update" to update

🌳 Setting up worktree...
🌳 Entered worktree at ~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/treehouse/.treehouse/live-projec
t-6625d6/1/live-project. Type 'exit' to return.

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
Mac-Studio:live-project charlesabrooker$ cd -- '~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/treehou
se/.treehouse/live-project-6625d6/1/live-project'
Mac-Studio:live-project charlesabrooker$ export GOTMPDIR=/tmp/fm-nm-bare-fuzzy-pattern/gotmp
Mac-Studio:live-project charlesabrooker$ export COMPACT_ADVISER_DISABLE=1
Mac-Studio:live-project charlesabrooker$ export FM_TASK_ID=nm-bare-fuzzy-pattern
Mac-Studio:live-project charlesabrooker$ . '/tmp/fm-nm-bare-fuzzy-pattern+25dc40c07fbe82ae37a4e2c91abde8f4dc7339c23f9653ef3d8ecead60a4dd69/launch.s1791530902.42
451.22286.sh'



























result=pass


SCENARIO: malformed-config-pass-through
exit=0; elapsed=76.211s
fm-gate-refuse: gate agent lifecycle permitted only against lab home ~/tmp/fm-lab.zds2s_pu
WARNING: watcher still down (same stale episode; last beat: never, grace 300s) - full banner already printed this episode.
skill selection for nm-malformed-config-pass-through: undelivered - raw launch command has no supported brief transport
spawned nm-malformed-config-pass-through harness=omp kind=scout window=primary:fm-nm-malformed-config-pass-through worktree=~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/treehouse/.treehouse/live-project-6625d6/1/live-project

config byte-identical before/after admission=True; task metadata exists=True
window=primary:fm-nm-malformed-config-pass-through
endpoint_task_id=nm-malformed-config-pass-through
worktree=~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/treehouse/.treehouse/live-project-6625d6/1/live-project
project=~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/live-project
harness=omp
kind=scout
tasktmp=/tmp/fm-nm-malformed-config-pass-through
model=default
effort=default
skill_selection=undelivered
skill_selection_reason=raw launch command has no supported brief transport
busy_gen=g1791530964.69793.25889
spawn_gen=s1791530977.63433.13084

PANE:

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
bash-3.2$ treehouse get
A new version of treehouse is available: v2.3.1-fm.e58947de → v3.1.2
Run "treehouse update" to update

🌳 Setting up worktree...
🌳 Entered worktree at ~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/treehouse/.treehouse/live-projec
t-6625d6/1/live-project. Type 'exit' to return.

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
Mac-Studio:live-project charlesabrooker$ cd -- '~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/treehou
se/.treehouse/live-project-6625d6/1/live-project'
Mac-Studio:live-project charlesabrooker$ export GOTMPDIR=/tmp/fm-nm-malformed-config-pass-through/gotmp
Mac-Studio:live-project charlesabrooker$ export COMPACT_ADVISER_DISABLE=1
Mac-Studio:live-project charlesabrooker$ export FM_TASK_ID=nm-malformed-config-pass-through
Mac-Studio:live-project charlesabrooker$ . '/tmp/fm-nm-malformed-config-pass-through+25dc40c07fbe82ae37a4e2c91abde8f4dc7339c23f9653ef3d8ecead60a4dd69/launch.s17
91530977.63433.13084.sh'



























result=pass

Traceback (most recent call last):
  File "~/.no-mistakes/worktrees/32d18ed9638d/01M4EXEQ168BN8K184P4R3DTM9/.nm-omp-validation/live.py", line 110, in <module>
    shutil.rmtree(lab)
    ~~~~~~~~~~~~~^^^^^
  File "~/.pyenv/versions/3.13.6/lib/python3.13/shutil.py", line 763, in rmtree
    _rmtree_safe_fd(stack, onexc)
    ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
  File "~/.pyenv/versions/3.13.6/lib/python3.13/shutil.py", line 707, in _rmtree_safe_fd
    onexc(func, path, err)
    ~~~~~^^^^^^^^^^^^^^^^^
  File "~/.pyenv/versions/3.13.6/lib/python3.13/shutil.py", line 700, in _rmtree_safe_fd
    onexc(os.unlink, fullname, err)
    ~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/.pyenv/versions/3.13.6/lib/python3.13/shutil.py", line 696, in _rmtree_safe_fd
    os.unlink(entry.name, dir_fd=topfd)
    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
PermissionError: [Errno 13] Permission denied: '~/tmp/fm-lab.zds2s_pu/state/nm-raw-native-model-pin.git-hooks'


Wall time: 1003.28 seconds

Command exited with code 1
Evidence: Selected fields from genuine omp RPC responses

Source: Selected fields from genuine omp RPC responses

[
  {
    "scenario": "colon",
    "command": "get_state",
    "success": true,
    "model": {
      "provider": "lab-local",
      "id": "qwen3:8b",
      "baseUrl": "http://127.0.0.1:62996/v1"
    },
    "thinkingLevel": "high",
    "isSettled": true,
    "messageCount": 0,
    "configByteIdentical": true,
    "catalogProbe": true,
    "extraction": "Selected complete fields from captured real RPC response; full frame exceeds tmux capture depth."
  },
  {
    "scenario": "long-glob",
    "command": "get_state",
    "success": true,
    "model": {
      "provider": "lab-local",
      "id": "qwen3:8b",
      "baseUrl": "http://127.0.0.1:62996/v1"
    },
    "thinkingLevel": "high",
    "isSettled": true,
    "messageCount": 0,
    "configByteIdentical": true,
    "catalogProbe": false,
    "extraction": "Selected complete fields from captured real RPC response; full frame exceeds tmux capture depth."
  }
]
Evidence: Original three-second regression: fixed passes, old regex times out

Source: Original three-second regression: fixed passes, old regex times out

fixed-original-3-second-bound
command: bash tests/.nm-omp-long-glob.sh (original unchanged 3-second bound; serial run)
exit=0; elapsed=56.662s
ok - fm-spawn: any expanded raw token passes through unchanged without evaluating it or probing the default-role catalog


mutant-original-3-second-bound
command: bash tests/.nm-omp-mutation.sh (original unchanged 3-second bound; serial run)
exit=1; elapsed=28.101s
not ok - a long literal prefix ending in a glob must classify within three seconds
Evidence: Baseline and completed targeted-selector results

Source: Baseline and completed targeted-selector results

Command: env TMPDIR="$PWD/.nm-omp-validation/tmp" FM_TEST_SKIP_ORPHAN_REAP=1 bash tests/.nm-omp-targeted.sh
Outer deadline: 1200 seconds (reached)

selector: test_spawn_model_validation_scoped_to_listed_providers
ok - fm-spawn: omp model validation is scoped to providers the listing can prove
elapsed 126.431 seconds
selector: test_spawn_refuses_a_missing_or_unlisted_default_role
ok - fm-spawn: an omp launch with no model refuses a missing or unlisted default role and names the remedy
elapsed 549.228 seconds
selector: test_spawn_global_config_is_read_only_and_unlayered
ok - fm-spawn: global role inspection is read-only, unlayered, and honors PI_CODING_AGENT_DIR
elapsed 298.286 seconds
selector: test_spawn_raw_omp_guard_uses_the_launch_model
(no completed result before outer deadline)

Pipeline

Updates from git push no-mistakes

... (11 earlier update rounds omitted to keep the PR body within GitHub's 65536-char limit; full history is in the run log.)

🔧 **Review** - 2 issues found → auto-fixed (8) ✅

🔧 Fix applied.
8 issues (5 errors, 3 warnings) still open:

  • ⚠️ bin/fm-spawn.sh:2285 - Intent criterion 3 requires that "an unknown provider passes with a notice." With no explicit model and modelRoles.default='claude-bridge/claude-opus-4-8', omp_catalog_verdict returns unknown-provider, but the added hunk checks only if [ &#34;$verdict&#34; = unlisted ] and then returns success silently. The explicit-model sibling at bin/fm-spawn.sh:2229 prints the required notice; the default-role consumer at bin/fm-spawn.sh:2284 must preserve that contract too. Add the unknown-provider notice without changing pass-through behavior.
  • ⚠️ bin/fm-spawn.sh:2829 - The new guard also runs for supported raw launch commands, but MODEL does not include their native arguments. With the optional session-launch restriction disabled, a spawn using the documented launch-command interface with omp --model openai-codex/gpt-6-astra and a missing shared default resolves HARNESS=omp at lines 2590–2603 while MODEL remains empty. The check at bin/fm-spawn.sh:2269 therefore reads the shared role and refuses this explicitly pinned launch, although it cannot suffer the fallback being guarded. Make default-role validation depend on the effective model override for the supported raw omp path, rather than only the separate fm-spawn MODEL variable. Both the call at bin/fm-spawn.sh:2829 and its dependency predicate at bin/fm-spawn.sh:2269 must agree with the actual launch.
  • 🚨 bin/fm-spawn.sh:2315 - The new probe is not a read-only inspection of the global file. Criterion 4 requires that the guard "reads the global config only," and criterion 5 states "Firstmate code never writes that file." In omp 18.8.1, config get initializes writable Settings and returns the effective merged setting (https://github.com/can1357/oh-my-pi/blob/v18.8.1/packages/coding-agent/src/cli/config-cli.ts#L163-L164 and #L258-L275). Two concrete failures follow: (1) a listed default in the supervisor cwd's project config masks a missing global default, so a worker launched into another project without that override passes the guard and falls back; (2) malformed global YAML is renamed to .broken-* during initialization (https://github.com/can1357/oh-my-pi/blob/v18.8.1/packages/coding-agent/src/config/settings.ts#L2281-L2325), after which the suppressed probe failure permits launch against the now-missing config instead of preserving the startup parse error. Replace this probe with non-mutating, global-only role inspection at the shared validator, retaining unreadable-evidence pass-through. Affected sibling sites: bin/fm-spawn.sh:2317 consumes the merged default; bin/fm-spawn.sh:2880 applies it to canonical and raw launches; docs/configuration.md:977-981 promises global-only, non-writing behavior; tests/fm-omp-harness.test.sh:118-124 models neither layering nor initialization side effects.
  • 🚨 bin/fm-spawn.sh:2324 - The R3 fix round reads the invoking process's agent directory, but leaves the actual launch's configuration identity unaligned. With a listed default in directory A and a missing default in directory B, the supported raw command PI_CODING_AGENT_DIR=/B omp --auto-approve resolves HARNESS=omp, passes this guard using A, then launches against B and still reaches the credentialed-model fallback. Canonical launches have the same mismatch when the invoking process sets PI_CODING_AGENT_DIR but the persistent tmux pane inherits another value: the omp template does not forward it, and the launch-env allowlist can remove it. Resolve the actual launch's effective global-config directory at the shared validation boundary and keep role inspection, catalog inspection, and execution aligned. Related sites: bin/fm-spawn.sh:2278-2310 (raw assignments are skipped, not applied to config inspection), bin/fm-spawn.sh:2253 (catalog uses invoking-process environment), bin/fm-spawn.sh:2887 (both launch paths use this validator), docs/configuration.md:977 (claims inspection of the launch's shared Default role), tests/fm-omp-harness.test.sh:316 and :328 (custom-directory cases record launch text but do not establish which directory the launched process receives).
  • ⚠️ bin/fm-spawn.sh:2306 - Round 3's R4 fix introduces a guard bypass for ordinary raw-command redirections. With /B/config.yml containing modelRoles: {}, PI_CODING_AGENT_DIR=/B omp --auto-approve 2&gt;/B/errors.log resolves HARNESS=omp, but the redirection makes tokens.every(token =&gt; token.type === &#34;word&#34;) false. Lines 2316 and 2334 then discard the known directory and permit the launch, leaving the credentialed-model fallback reachable. The redirection does not make this literal directory uncertain. Preserve directory evidence for an otherwise supported simple command with redirections; the existing token collector already skips their targets. Related sites: bin/fm-spawn.sh:2298 skips redirections; :2316 clears the directory; :2334 bypasses validation; docs/configuration.md:981 promises that literal absolute assignments are honored.
  • 🚨 bin/fm-spawn.sh:2316 - Round 3's R4 fix still treats PI_CODING_AGENT_DIR as the launch's effective directory when omp profile selection overrides it. For example, let /A/config.yml have a listed default and ~/.omp/profiles/work/agent/config.yml have no default. The supported raw command PI_CODING_AGENT_DIR=/A omp --profile work --auto-approve passes this guard using /A, then omp activates work and launches against the missing profile default. omp 18.8.1 explicitly ignores agent-directory overrides for named profiles and replaces PI_CODING_AGENT_DIR during activation (https://github.com/can1357/oh-my-pi/blob/v18.8.1/packages/utils/src/dirs.ts); CLI bootstrap applies both profile flags and environment selection (https://github.com/can1357/oh-my-pi/blob/v18.8.1/packages/coding-agent/src/cli.ts). Remaining sibling inputs are OMP_PROFILE, PI_PROFILE, --profile, and --profile=; canonical launches also remain vulnerable when the destination pane inherits a different profile. At the shared directory-evidence boundary, mark profile-dependent identity unreadable whenever it cannot be established, as the R4 instructions authorize, rather than inspecting an unrelated directory. Related sites: bin/fm-spawn.sh:2307-2313 processes assignments without accounting for profile overrides; :2318-2325 scans arguments without profile handling; :2356 probes the catalog under the invoking process's profile environment; :2910-2913 forwards a directory without establishing the pane's profile; docs/configuration.md:981 claims alignment.
  • 🚨 bin/fm-spawn.sh:2321 - Round 4's R6 fix leaves shell-expanded profile flags behind. With OMP_PROFILE and PI_PROFILE unset, /A/config.yml containing modelRoles: {}, and the destination pane's PROFILE_FLAG set to --profile=work, the supported raw command PI_CODING_AGENT_DIR=/A omp &#34;$PROFILE_FLAG&#34; --auto-approve should pass through to the work profile. Instead, the lexer marks the argument nonliteral but the argument scan ignores that evidence, retains certain=true, reads /A, and refuses the launch. This contradicts the selected rule: "when the effective directory cannot be established with certainty, pass through." At the shared raw-command evidence boundary, treat shell-expanded option positions as unreadable rather than inspecting an unrelated directory; do not evaluate the expansion. Related sites: bin/fm-spawn.sh:2307 initializes certainty from token types only; :2319-2327 consumes argument values without their literal/expansion flags; :2328 retains the directory; :2338 and :2359 respectively read the role and probe its catalog; docs/configuration.md:981 promises shell-expansion pass-through; tests/fm-omp-harness.test.sh:423 covers only literal profile flags. Upstream confirms that the expanded --profile=work selects the profile: https://github.com/can1357/oh-my-pi/blob/v18.8.1/packages/coding-agent/src/cli/profile-bootstrap.ts.
  • 🚨 bin/fm-spawn.sh:2294 - Round 5's selected R7 fix (2c836b8) leaves tilde expansion outside the new pass-through rule. The decision requires that "any shell-expanded token in a raw launch command makes it unreadable evidence that passes through unchanged," but the added predicate checks only !token.literal or token.unquotedExpansion. The reused Lexer flags dollar/substitution and wildcard/brace forms, not unquoted tilde prefixes (bin/fm-arm-command-policy.mjs:384-385). With profiles unset, /A/config.yml containing modelRoles: {}, and raw commands enabled, PI_CODING_AGENT_DIR=/A omp --auto-approve 2&gt;~/omp-errors.log retains certain=true and is refused, although its redirection target undergoes shell expansion. With an unlisted default, it also performs the catalog probe that Option C forbids. Recognize unquoted tilde expansion at this guard's shared evidence check without evaluating it or changing canonical launches. Related changed sites: bin/fm-spawn.sh:2299-2301 skips redirection targets after classification; :2327 retains directory evidence; :2349 refuses missing roles; :2358 probes unlisted roles; docs/configuration.md:981 promises every expanded token passes through; tests/fm-omp-harness.test.sh:478 enumerates expansion cases but omits tilde-expanded arguments and redirection targets.

🔧 Fix applied.
9 issues (6 errors, 3 warnings) still open:

  • ⚠️ bin/fm-spawn.sh:2285 - Intent criterion 3 requires that "an unknown provider passes with a notice." With no explicit model and modelRoles.default='claude-bridge/claude-opus-4-8', omp_catalog_verdict returns unknown-provider, but the added hunk checks only if [ &#34;$verdict&#34; = unlisted ] and then returns success silently. The explicit-model sibling at bin/fm-spawn.sh:2229 prints the required notice; the default-role consumer at bin/fm-spawn.sh:2284 must preserve that contract too. Add the unknown-provider notice without changing pass-through behavior.
  • ⚠️ bin/fm-spawn.sh:2829 - The new guard also runs for supported raw launch commands, but MODEL does not include their native arguments. With the optional session-launch restriction disabled, a spawn using the documented launch-command interface with omp --model openai-codex/gpt-6-astra and a missing shared default resolves HARNESS=omp at lines 2590–2603 while MODEL remains empty. The check at bin/fm-spawn.sh:2269 therefore reads the shared role and refuses this explicitly pinned launch, although it cannot suffer the fallback being guarded. Make default-role validation depend on the effective model override for the supported raw omp path, rather than only the separate fm-spawn MODEL variable. Both the call at bin/fm-spawn.sh:2829 and its dependency predicate at bin/fm-spawn.sh:2269 must agree with the actual launch.
  • 🚨 bin/fm-spawn.sh:2315 - The new probe is not a read-only inspection of the global file. Criterion 4 requires that the guard "reads the global config only," and criterion 5 states "Firstmate code never writes that file." In omp 18.8.1, config get initializes writable Settings and returns the effective merged setting (https://github.com/can1357/oh-my-pi/blob/v18.8.1/packages/coding-agent/src/cli/config-cli.ts#L163-L164 and #L258-L275). Two concrete failures follow: (1) a listed default in the supervisor cwd's project config masks a missing global default, so a worker launched into another project without that override passes the guard and falls back; (2) malformed global YAML is renamed to .broken-* during initialization (https://github.com/can1357/oh-my-pi/blob/v18.8.1/packages/coding-agent/src/config/settings.ts#L2281-L2325), after which the suppressed probe failure permits launch against the now-missing config instead of preserving the startup parse error. Replace this probe with non-mutating, global-only role inspection at the shared validator, retaining unreadable-evidence pass-through. Affected sibling sites: bin/fm-spawn.sh:2317 consumes the merged default; bin/fm-spawn.sh:2880 applies it to canonical and raw launches; docs/configuration.md:977-981 promises global-only, non-writing behavior; tests/fm-omp-harness.test.sh:118-124 models neither layering nor initialization side effects.
  • 🚨 bin/fm-spawn.sh:2324 - The R3 fix round reads the invoking process's agent directory, but leaves the actual launch's configuration identity unaligned. With a listed default in directory A and a missing default in directory B, the supported raw command PI_CODING_AGENT_DIR=/B omp --auto-approve resolves HARNESS=omp, passes this guard using A, then launches against B and still reaches the credentialed-model fallback. Canonical launches have the same mismatch when the invoking process sets PI_CODING_AGENT_DIR but the persistent tmux pane inherits another value: the omp template does not forward it, and the launch-env allowlist can remove it. Resolve the actual launch's effective global-config directory at the shared validation boundary and keep role inspection, catalog inspection, and execution aligned. Related sites: bin/fm-spawn.sh:2278-2310 (raw assignments are skipped, not applied to config inspection), bin/fm-spawn.sh:2253 (catalog uses invoking-process environment), bin/fm-spawn.sh:2887 (both launch paths use this validator), docs/configuration.md:977 (claims inspection of the launch's shared Default role), tests/fm-omp-harness.test.sh:316 and :328 (custom-directory cases record launch text but do not establish which directory the launched process receives).
  • ⚠️ bin/fm-spawn.sh:2306 - Round 3's R4 fix introduces a guard bypass for ordinary raw-command redirections. With /B/config.yml containing modelRoles: {}, PI_CODING_AGENT_DIR=/B omp --auto-approve 2&gt;/B/errors.log resolves HARNESS=omp, but the redirection makes tokens.every(token =&gt; token.type === &#34;word&#34;) false. Lines 2316 and 2334 then discard the known directory and permit the launch, leaving the credentialed-model fallback reachable. The redirection does not make this literal directory uncertain. Preserve directory evidence for an otherwise supported simple command with redirections; the existing token collector already skips their targets. Related sites: bin/fm-spawn.sh:2298 skips redirections; :2316 clears the directory; :2334 bypasses validation; docs/configuration.md:981 promises that literal absolute assignments are honored.
  • 🚨 bin/fm-spawn.sh:2316 - Round 3's R4 fix still treats PI_CODING_AGENT_DIR as the launch's effective directory when omp profile selection overrides it. For example, let /A/config.yml have a listed default and ~/.omp/profiles/work/agent/config.yml have no default. The supported raw command PI_CODING_AGENT_DIR=/A omp --profile work --auto-approve passes this guard using /A, then omp activates work and launches against the missing profile default. omp 18.8.1 explicitly ignores agent-directory overrides for named profiles and replaces PI_CODING_AGENT_DIR during activation (https://github.com/can1357/oh-my-pi/blob/v18.8.1/packages/utils/src/dirs.ts); CLI bootstrap applies both profile flags and environment selection (https://github.com/can1357/oh-my-pi/blob/v18.8.1/packages/coding-agent/src/cli.ts). Remaining sibling inputs are OMP_PROFILE, PI_PROFILE, --profile, and --profile=; canonical launches also remain vulnerable when the destination pane inherits a different profile. At the shared directory-evidence boundary, mark profile-dependent identity unreadable whenever it cannot be established, as the R4 instructions authorize, rather than inspecting an unrelated directory. Related sites: bin/fm-spawn.sh:2307-2313 processes assignments without accounting for profile overrides; :2318-2325 scans arguments without profile handling; :2356 probes the catalog under the invoking process's profile environment; :2910-2913 forwards a directory without establishing the pane's profile; docs/configuration.md:981 claims alignment.
  • 🚨 bin/fm-spawn.sh:2321 - Round 4's R6 fix leaves shell-expanded profile flags behind. With OMP_PROFILE and PI_PROFILE unset, /A/config.yml containing modelRoles: {}, and the destination pane's PROFILE_FLAG set to --profile=work, the supported raw command PI_CODING_AGENT_DIR=/A omp &#34;$PROFILE_FLAG&#34; --auto-approve should pass through to the work profile. Instead, the lexer marks the argument nonliteral but the argument scan ignores that evidence, retains certain=true, reads /A, and refuses the launch. This contradicts the selected rule: "when the effective directory cannot be established with certainty, pass through." At the shared raw-command evidence boundary, treat shell-expanded option positions as unreadable rather than inspecting an unrelated directory; do not evaluate the expansion. Related sites: bin/fm-spawn.sh:2307 initializes certainty from token types only; :2319-2327 consumes argument values without their literal/expansion flags; :2328 retains the directory; :2338 and :2359 respectively read the role and probe its catalog; docs/configuration.md:981 promises shell-expansion pass-through; tests/fm-omp-harness.test.sh:423 covers only literal profile flags. Upstream confirms that the expanded --profile=work selects the profile: https://github.com/can1357/oh-my-pi/blob/v18.8.1/packages/coding-agent/src/cli/profile-bootstrap.ts.
  • 🚨 bin/fm-spawn.sh:2294 - Round 5's selected R7 fix (2c836b8) leaves tilde expansion outside the new pass-through rule. The decision requires that "any shell-expanded token in a raw launch command makes it unreadable evidence that passes through unchanged," but the added predicate checks only !token.literal or token.unquotedExpansion. The reused Lexer flags dollar/substitution and wildcard/brace forms, not unquoted tilde prefixes (bin/fm-arm-command-policy.mjs:384-385). With profiles unset, /A/config.yml containing modelRoles: {}, and raw commands enabled, PI_CODING_AGENT_DIR=/A omp --auto-approve 2&gt;~/omp-errors.log retains certain=true and is refused, although its redirection target undergoes shell expansion. With an unlisted default, it also performs the catalog probe that Option C forbids. Recognize unquoted tilde expansion at this guard's shared evidence check without evaluating it or changing canonical launches. Related changed sites: bin/fm-spawn.sh:2299-2301 skips redirection targets after classification; :2327 retains directory evidence; :2349 refuses missing roles; :2358 probes unlisted roles; docs/configuration.md:981 promises every expanded token passes through; tests/fm-omp-harness.test.sh:478 enumerates expansion cases but omits tilde-expanded arguments and redirection targets.
  • 🚨 bin/fm-spawn.sh:2295 - The latest R8 fix (1f2cae6) introduces catastrophic backtracking: the unquoted-character branch has an inner '+' inside an outer '+'. For the supported raw command PI_CODING_AGENT_DIR=/A omp --auto-approve /work/vernant/generated/reports/input*.txt, the disallowed '*' forces the matcher to explore exponentially many partitions of the preceding literal characters. [INFERENCE from static regex analysis] This can stall fm-spawn indefinitely instead of passing unreadable evidence through unchanged. Remove the inner '+' from the unquoted-character branch so each outer repetition consumes one literal character or one complete quoted segment, preserving the required allow-list. Related sites: bin/fm-spawn.sh:2297 applies this predicate to command words, assignments, arguments, and redirection targets; :2282 synchronously waits for the Node process; tests/fm-omp-harness.test.sh:508 quotes the long glob prefix, avoiding this failure; docs/configuration.md:981 promises expansion pass-through.

🔧 Fix applied.
1 error still open:

  • 🚨 tests/fm-omp-harness.test.sh:514 - Round 7's R9 fix introduces a false-positive regression test on hosts with timeout/gtimeout, including Ubuntu CI. The new Node wrapper calls fm_run_timed, whose external-timeout arm backgrounds the command without preserving stdin (bin/fm-timeout-lib.sh:157-164). Non-interactive Bash therefore supplies /dev/null instead of the validator's JavaScript heredoc from bin/fm-spawn.sh:2282. Node executes an empty program successfully; dependency is empty, agent_dir becomes empty, and validation passes through at bin/fm-spawn.sh:2338. Consequently, restoring the catastrophic regex would still pass this case without reaching the regex or timing out. Preserve the incoming script through an inherited file descriptor and restore it inside the bounded command. Related changed sites: tests/fm-omp-harness.test.sh:515 records only actual timeouts; :535 checks that marker's absence; :536-541 also accept this skipped-validation path.

🔧 Fix applied.
✅ Re-checked - no issues remain.

✅ **Test** - passed

✅ No issues found.

  • Live validation: ✅ go - 13 of 14 scenarios driven live against the product
Scenario Result Live Evidence
Spawn unpinned omp with no Default role: refuse before task creation and print the exact remedy ✅ pass live Live spawn transcript: missing-default; exit 1, no task metadata, configuration byte-identical, full remedy printed.
Spawn with an unlisted Default role and thinking suffix: refuse using the real provider catalog ✅ pass live Live spawn transcript: unlisted-default; apple/definitely-missing-model:high refused against installed omp's catalog.
Set a valid project role while the global role is missing: project settings cannot mask the refusal ✅ pass live Live spawn transcript: project-cannot-mask-global; refused with no task metadata and unchanged global configuration.
Use a literal raw omp command with a known agent directory and redirection: invalid Default role still refuses ✅ pass live Live spawn transcript: literal-raw-refused; supplemental literal-boundary checks covered all supported quoting forms and verified redirections were not executed.
Pass a long unquoted path ending in a glob: launch unchanged without inspecting the Default-role catalog ✅ pass live live-omp-long-glob-rpc.txt: actual validator execution, genuine omp launch, no models --json invocation, and successful get_state response.
Pin an explicit model while the Default role is missing: admit the canonical launch ✅ pass live Live spawn transcript: explicit-model-overrides-missing; exit 0 and published omp task metadata.
Use a listed Default role with a known thinking suffix: admit the canonical launch ✅ pass live Live spawn transcript: listed-thinking-suffix; apple/on-device:high admitted against the real catalog.
Pin the model through native raw-command arguments: do not refuse because the shared Default role is missing ✅ pass live Live spawn transcript: raw-native-model-pin; --model=apple/on-device admitted and task metadata published.
Use a Default role from an unknown provider: print a notice and admit the launch ✅ pass live Live spawn transcript: unknown-provider-notice; notice identified fixture-extension/model:high and spawn succeeded.
Use a bare fuzzy Default-role pattern: leave matching to omp ✅ pass live Live spawn transcript: bare-fuzzy-pattern; gpt-style/provider-independent matching remained delegated and spawn was admitted.
Provide malformed global YAML: preserve its bytes and admit the launch without established role evidence ✅ pass live Live spawn transcript: malformed-config-pass-through; exit 0, published task metadata, and byte-identical malformed configuration.
Select a catalog model whose id contains a colon plus a thinking suffix: preserve the id and select the intended effort ✅ pass live real-runtime-state.json: genuine get_state response reported provider lab-local, id qwen3:8b, and thinkingLevel high.
Make the real catalog listing unreadable while the configured model is unlisted: admit rather than infer a refusal ✅ pass live live-omp-unreadable-rpc.txt and unreadable-real-catalog.txt: a disposable extension emitted a catalog preamble; fm-spawn admitted the launch and actual omp printed its help surface.
Run the bounded regression with external timeout present: execute validator stdin and distinguish fixed code from catastrophic backtracking ⏸️ untested no The prior payload records only a fake-harness behavioral regression with live=false, so it did not establish a live product result for this scenario. The separately exercised real-product long-glob sc…
  • bash tests/fm-omp-harness.test.sh — initial attempt stopped at the ancestry-sensitive ompd detection check, before the changed scenarios.
  • env TMPDIR=&#34;$PWD/.nm-omp-validation/tmp&#34; FM_TEST_SKIP_ORPHAN_REAP=1 bash tests/.nm-omp-targeted.sh — model-validation, default-role refusal, and read-only/global-only selectors completed successfully; the outer deadline interrupted the remaining selectors.
  • env TMPDIR=&#34;$PWD/.nm-omp-validation/tmp&#34; FM_TEST_SKIP_ORPHAN_REAP=1 bash tests/.nm-omp-literal.sh — unquoted, single-quoted, and double-quoted literal command boundaries passed.
  • bash tests/.nm-omp-long-glob.sh and bash tests/.nm-omp-mutation.sh — after serializing validation, the unchanged three-second regression passed corrected code and failed the temporarily restored nested-quantifier regex by timeout.
  • python3 .nm-omp-validation/live.py — drove isolated real fm-spawn admission scenarios using installed omp, Treehouse, and a private tmux socket.
  • env SCENARIO=colon python3 .nm-omp-validation/handshake.py and env SCENARIO=long-glob python3 .nm-omp-validation/handshake.py — observed real omp RPC state against a disposable localhost model catalog.
  • env SCENARIO=unreadable python3 .nm-omp-validation/handshake.py — verified pass-through when a disposable extension made the real vendor catalog output unreadable.
  • Stopped owned tmux servers and the localhost endpoint, removed marked labs, temporary executables, selector runners, caches, and fixture repositories; confirmed no matching worktree fixtures remained.
✅ **Document** - passed

✅ No issues found.

🔧 **Lint** - 1 issue found → auto-fixed ✅
  • ⚠️ linter found issues (exit code 1)

🔧 Fix applied.
✅ Re-checked - no issues remain.

✅ **Push** - passed

✅ No issues found.

…isted

An omp launch with no --model reads the global modelRoles.default.
Any interactive omp session can clear it, and omp then silently runs the first credentialed model.
Here that is a free-tier model that answers every call with HTTP 429.
fm-spawn now reads the role through omp config get and the catalog through omp models, and refuses with the remedy.
…: Bash 5.2 removed inline single quotes from the expected __MODELFLAG__ replacement, causing a false mismatch against the correctly quoted launch. The test now uses literal variable-based replacement, matching production’s portable pattern. Updated coverage documentation; production behavior is unchanged. Local CI-runner verification passed the formerly failing raw-model case and all related guard cases, including the timeout-bound long glob. Executable launch smoke and bash -n passed. The full local suite subsequently stopped at the unrelated restriction against secondmate fixture homes inside the repository. Linux CI was not rerun
@MrGTV-love
MrGTV-love merged commit 18fdf6c into main Oct 9, 2026
22 checks passed
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