Skip to content

fix: keep the Attractor expert prompt in its owning profile - #360

Merged
Brian Krabach (bkrabach) merged 1 commit into
mainfrom
lane/expert-persona
Sep 16, 2026
Merged

Brian Krabach (bkrabach) merged 1 commit into
mainfrom
lane/expert-persona

Conversation

@bkrabach

Copy link
Copy Markdown
Collaborator

Summary

The packaged Attractor expert can now start from outside its repository. Previously its relative system_prompt_file was looked up under the separate Dot Runner package and raised FileNotFoundError before its first model request.

Move the expert's existing Layer-1 persona into the already-supported literal system_prompt field in its owning agent profile. Retire the separate copy so there remains one owner of that text.

  • The parsed prompt is byte-identical to the previous asset: 12,120 UTF-8 bytes across 204 lines.
  • The agent Markdown body and explicit loop-agent mount are unchanged.
  • The expert remains a pipeline-design consultant, not a generic provider coding agent.
  • No new path resolver, private runtime API, Foundation/Core change, or silent missing-file fallback is introduced.

Spec and vision fit

StrongDM's coding-agent-loop spec §§6.1–6.2 assigns Layer-1 instructions to the provider/profile construction and specifies required topics rather than complete wording. The Attractor spec §1.4 preserves the backend boundary. This is a packaging repair inside that boundary, not a change to graph semantics.

The repository's vision and profile-owned Layer-1 design retain the expert's non-coding consultant persona. This change preserves that text exactly through an existing public configuration channel. Frozen and historical documents were not rewritten.

Verification

  • The baseline failure was reproduced against the real installed resolver and through a registered Attractor bundle's actual CLI delegation.
  • The new profile guards were RED before the change: 5 failed, 2 passed.
  • Candidate guards: 7 passed.
  • Independently repeated root guard suite: 275 passed, 2 skipped. The two pre-existing unrelated skips are not claimed as exercised.
  • Orchestrator source-pin guard: 8 passed, none skipped.
  • In a DTU with the exact candidate installed, the real expert delegation succeeded. Native session evidence showed one successful child model request and response; the baseline child had failed before making a model request.
  • The installed parsed prompt matches the original asset's byte count and SHA-256; the unchanged Markdown agent body was also compared byte-for-byte. This is an asset-preservation check plus a live startup check, not a claim that captured telemetry exposed the entire wire prompt.
  • Dot Runner's unchanged system-prompt and wiring tests passed 50/50 in the same DTU, including missing explicit-file errors and inline-prompt precedence.
  • A real nested/parallel CLI pipeline also ran and resumed successfully in the shared integration environment.
  • Independent source review passed after checking persona preservation, the anti-recursion mount, and diff scope.

The diff has four paths: the agent profile, its former asset, a directly affected behavior comment, and new regression tests. Raw session output and operational paths remain outside source control.

Verification checklist

  • Repository vision, principles, and relevant StrongDM sections considered
  • Profile persona and explicit orchestrator ownership preserved
  • Root guard suite and source-pin guard run
  • Real packaged runtime verification completed
  • Independent review completed
  • No unrelated runtime, provider, or frozen-document changes

The packaged attractor-expert could not start.  Its profile declared

    system_prompt_file: context/system-attractor-expert.md

and loop-agent resolves a RELATIVE system_prompt_file against ITS OWN
installed bundle root (parents[3] of its __init__.py, then an upward
ancestor walk) -- never against the bundle that declared the value.
This agent's session.orchestrator.source deliberately mounts loop-agent
from the SEPARATE amplifier-bundle-dot-runner package (that mount is what
stops a pipeline parent's loop-pipeline from recursing into the child),
so the anchor is the dot-runner install, where an Attractor-owned
context/ asset does not exist.  Measured against the real installed
resolver:

    FileNotFoundError: system_prompt_file 'context/system-attractor-expert.md'
    (relative) could not be resolved to an existing file. Expected it at the
    bundle root: <dot-runner-root>/context/system-attractor-expert.md

The repair uses the channel loop-agent already supports at HIGHER
precedence (explicit system_prompt > explicit system_prompt_file >
provider default > fail-loud): the persona is carried INLINE as a YAML
literal block, so there is no path left to anchor wrongly.

The persona is MOVED, not rewritten -- spliced programmatically, never
re-typed.  The parsed value is byte-identical to the retired asset:
sha256 07e24526081f0b76888e984895f44d753b381f4cf1de66e4f2c4c8c01404b487,
12120 bytes, 204 lines.  The side-file is retired rather than kept
beside it: two independently-maintained Layer-1 owners is the drift
class this repo names in docs/designs/RECURRING-BUG-CLASSES.md.

Preserved deliberately: the non-coding consultant persona (a provider
coding base here is explicitly rejected -- see
docs/designs/layer-1-profile-owned-system-prompt.md, which records this
as the ONE agent keeping a persona override), the separate Markdown
expert body, and the explicit git+ loop-agent mount.

Scope: this is packaging restoration, not an engine or nlspec change.
No Dot Runner / Foundation / Core edit, no new resolver, no namespace
lookup, no provider pin.  StrongDM coding-agent-loop-spec 6.1/6.2 puts
system instructions in the profile/backend layer and does not prescribe
wording; attractor-spec 1.4 leaves backend internals to implementors.
Decision-matrix tier: toward-spec (restores the profile-owned Layer-1
the spec assigns to the backend layer).

Verification -- parse-level, and honest about its ceiling:
  * RED captured against the REAL installed loop-agent resolver
    (FileNotFoundError, above), and the 7 new guards proven RED on the
    pre-fix declaration (5 failed, 2 invariants held) before the fix.
  * Root guards: 275 passed, 2 skipped (both pre-existing namespaced-ref
    skips in test_context_include_paths.py), keys unset.
  * tests/test_orchestrator_source_pin_guard.py: 8 passed, 0 skipped.
  * These are PARSE-level guards.  Parsing was never the broken thing,
    so they do NOT prove the packaged expert now SPAWNS.  That needs a
    real packaged public-path run; the DTU probe is handed to the
    manager with this candidate.  "The test passes" is not "it works".

Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
@bkrabach
Brian Krabach (bkrabach) merged commit 981b4be into main Sep 16, 2026
6 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