Skip to content

🚚 Rename xmd prompt to xmd plan (#670) - #671

Merged
taras merged 3 commits into
mainfrom
agent/issue-670-plan-rename
Aug 31, 2026
Merged

🚚 Rename xmd prompt to xmd plan (#670)#671
taras merged 3 commits into
mainfrom
agent/issue-670-plan-rename

Conversation

@taras

@taras taras commented Aug 31, 2026

Copy link
Copy Markdown
Owner

Closes #670.

Why

The authorship command was named for its input rather than its result. It takes a Prompt — what you describe — and produces a Plan: an executable Markdown document with reader-facing prose beside the components that carry it out. xmd plan says that.

Nothing is published under the old name. The latest release is v0.9.2, which predates the command entirely, so this is a rename with no compatibility surface — no alias, no deprecation, no tombstone.

What changes

Before:

$ xmd plan "ask me for my age and write it to a file"
error: unrecognized command

After:

$ xmd plan "ask me for my age and write it to a file"
# Ask for and save your age

xmd --help now lists:

plan  Create an executable Plan from a Prompt and review it before writing or running it.

and lists no prompt command. The four result modes are unchanged: source on stdout by default, --output <path>, --run, or --output followed by --run.

How it works

Identity-bearing values only:

Old New
xmd prompt xmd plan
prompt-command.md plan-command.md
<prompt-command> <plan-command>
final supplied source <prompt> <plan>
xmd-prompt:<UUID> xmd-plan:<UUID>
~/.xmd/prompt/sessions ~/.xmd/plan/sessions
prompt profile authorship profile

No authorship policy, authority, property behavior, output mode, failure ordering, cancellation or teardown behavior changes.

Review guide

Start with: the packages/cli/src/documents/plan-command.md diff — it should be exactly six lines.

Then review: plan-args.ts and cli.ts for command selection and help; authorship-profile.ts for the renamed ceiling and directory namespace; plan.ts for the phase graph and <plan> identity.

Look carefully at:

  • <Prompt> is a different concept and had to survive. It is the ordinary one-turn Agent component. installPromptFailurePolicy, agent_prompt records, the fake's prompts, the request prop and the capitalized Prompt in authored text all stay. The residual-terminology classification below is the evidence that nothing genuine was renamed to make a text search come back empty.
  • <plan> is the final supplied-source identity, not the person's input. Fifteen uses name that identity — retainedSource("<plan>", source), PLAN_IDENTITY, (<plan>:5:1) positions, diagnostics, journals. A blind rename would have corrupted them.
  • The retired token is refused, not absorbed. An earlier version of this description claimed the default run grammar safely absorbed an unregistered token. That was wrong: prompt was read as a document path, so xmd prompt beside a file named prompt rendered it, exited 0 and wrote a file. runXmd() now refuses the exact first token prompt as its very first operation — before eval-flag reading, command selection or any document lookup — and xmd run ./prompt still runs a document by that name. prompt is registered nowhere, aliased to nothing and absent from help.

What must stay true

  • The packaged document's policy is untouched — enforced by a name-only diff, verified by comparing the two blobs directly: six line pairs, all xmd promptxmd plan (title, one explanatory sentence, four authored <Fail> messages). Headings, props, schemas, both loop bounds, <CheckDraft> placement, review choices, <Return> and every branch are identical.
  • Core <Prompt> and the Agent API do not change — no file under packages/core, packages/acp or packages/test-agent appears in either commit.
  • The retired namespace is never touched — nothing reads, migrates, aliases, empties or removes ~/.xmd/prompt.
  • The old spelling reaches nothing — no catalog, Agent, Session, Elicitation, output, journal or Plan execution, and no local document execution either. Enforced by a fail-closed preflight refusal rather than by fall-through, and checked by a subprocess regression that plants an executable document named prompt, proves it is neither rendered nor run and writes no sentinel, then proves xmd run ./prompt still executes it.

How to verify it

deno task test packages/cli/tests/plan-args.test.ts packages/cli/tests/plan-command-document.test.ts packages/cli/tests/plan.test.ts packages/cli/tests/plan-cli.test.ts packages/cli/tests/packaged-document.test.ts
deno task test scripts/tests/packaged-document.test.ts scripts/tests/cli-npm-bin.test.ts

At 613a4075: five suites 5 passed (46 steps) — the 43 that made #260 acceptable, two rename cases and the retired-token refusal; the adjacent dispatch suites (cli-help, command, inline-cli, syntax-cli) 6 passed (53 steps), run because the refusal sits at the top of runXmd(); packaged-document 1 passed; npm byte-identity 1 passed (46s); loader pass 2 under Node and 2 pass under Bun; deno task check, lint, build and git diff --check all clean.

Because the rename moves a compiled asset and both deno compile --include sites, the compiled binary was rebuilt and probed from a temporary cwd with a temporary HOME:

$ /abs/path/dist/xmd plan "write a greeting" --default-agent xmd-nonexistent-agent
agent "xmd-nonexistent-agent" is unavailable … cwd=…/.xmd/plan/sessions/bb516eb1…
EXIT=1

It fails at the first Agent turn, not with a missing packaged document — so the embedded asset loaded, expanded under <plan-command>, opened its Session and reached the turn. The temporary home held .xmd/plan/sessions and no .xmd/prompt, and the invocation-unique leaf was handed back.

Three regressions were confirmed to fail without their subject, since one that passes either way proves nothing: the retired-namespace sentinel fails when releaseSessionDirectory is made to remove the sibling recursively; the loader case fails if a conflicting plan-command.md planted in the working directory could answer for the packaged one; and both retired-token cases fail with the preflight disabled.

Scope

Included

  • a fail-closed preflight refusal of the exact retired first token, with the specifications, architecture inventory and test commentary corrected to describe it;
  • ten git mv renames — four source modules, four test suites, one harness, one spec — all detected as renames (77–93% similarity);
  • symbol renames across the command surface, including PromptDiagnosticDraftDiagnostic where the name meant a finding owned by the command rather than an Agent Prompt;
  • both compile sites, the npm asset test and the packaged-document drift guard;
  • terminology in architecture.md and five specs.

Intentionally unchanged

  • Core Agent files, <Prompt>, Prompt failure policy and agent_prompt durable vocabulary.
  • plan-command.md's policy, structure, bounds and wording beyond the command name.
  • ~/.xmd/prompt, which is left exactly as any existing installation has it.
  • The three separate --run=<value> proofs, kept as three cases rather than collapsed during the move.

Risks and limitations

  • An existing ~/.xmd/prompt becomes inert. Nothing migrates it. A caller who had used --session <name> gets a fresh directory under the new namespace, so an ACPX session established under the old one will not be continued. Acceptable because nothing is published, but it is a real behavioral consequence rather than a pure rename.
  • test-weights.json has no entry for the renamed suites, so they keep the corpus fallback until the next dispatched measurement.
  • The plan-cli.test.ts suite title was chosen to keep its describe call multi-line: shortening it dropped the call under the formatter's column threshold, which reindented ~700 lines and destroyed rename detection. The title is taken verbatim from that file's own module comment; no assertion or contract changed.

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • Generated or mechanical changes are clearly identified.
  • The description matches the final diff and test results.

https://claude.ai/code/session_015HcqB9kJM9KFnMNToAuZF6

taras added 2 commits August 30, 2026 20:11
The authorship command is named for its result. `xmd plan "<Prompt>"` takes
one Prompt and delivers the Plan it produced, and `xmd --help` describes it
as "Create an executable Plan from a Prompt and review it before writing or
running it."

The rename carries the identities that name the command: the packaged root is
`plan-command.md` and runs under `<plan-command>`, the constrained trusted-host
assembly is the authorship profile, generated logical sessions are
`xmd-plan:<UUID>` under `~/.xmd/plan/sessions`, and the approved Plan runs
under `<plan>`.

Nothing about authorship policy, authority, property behavior, output mode,
failure ordering, cancellation or teardown changes. The packaged Markdown
document's only edits are its title, its one explanatory sentence and its four
authored `<Fail>` messages. `<Prompt>` remains the ordinary one-turn Agent
component: its API, failure policy, `agent_prompt` records and the capitalized
Prompt in authored instructions are untouched.

The old spelling is not registered, aliased or kept as a tombstone. A token
naming no command continues through the existing default-run grammar, and
nothing reads, migrates or removes `~/.xmd/prompt`.
…670)

The spec's four result-mode rows wrote `xmd plan "<plan>"`, borrowing the
final supplied-source identity for the argument the command receives. The
command takes the person's Prompt and produces a Plan, so the rows now read
`xmd plan "<Prompt>"`. Every other `<plan>` names the identity approved bytes
run under and is unchanged.

The retired-namespace sentinel sat at a `-retired` sibling of the harness's
own root — a path no production code consults, so it proved nothing about
`.xmd/prompt`. It now sits at a literal `.xmd/prompt/sessions` beside the
`.xmd/plan/sessions` the command is given, both under one temporary tree the
case owns and removes whole. The case observes that the conversation really
ran under the plan namespace before reading the sibling back, so an empty
listing cannot stand in for a command that reached neither tree.

No production source, and no part of the packaged Markdown document, changes.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 1 redundant comment. Inline suggestions to remove them below.

Comment thread packages/cli/src/cli.ts
const provisional = xmd.parse({ args: helpRequest.args });
const selected = provisional.ok ? provisional.value.config : undefined;
// The two commands that end in a document execution. `xmd prompt`'s deadline
// The two commands that end in a document execution. `xmd plan`'s deadline

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// The two commands that end in a document execution. `xmd plan`'s deadline

@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown

PR #671: 🚚 Rename xmd prompt to xmd plan (#670)

26 files, +893 / -604

Scope

🔴 PR has 1497 lines changed. Split into focused PRs.

🟡 1497 lines changed. PRs under 400 receive more thorough review.

🟡 26 files changed. Are all changes related?

🟡 Changes span 9 directories.

🟡 PR mixes config and source changes.

Structural

Oxlint structural signals:

  • no-unnecessary-type-arguments ×10: packages/cli/src/props.ts
  • no-unused-vars ×2: packages/cli/src/cli.ts
  • no-empty-function ×1: packages/cli/src/cli.ts

Slop

  • packages/cli/src/cli.ts:2173 (removed)
  • packages/cli/src/cli.ts:2193// The two commands that end in a document execution. xmd plan's deadline

Oxlint slop signals:

  • no-console ×3: packages/cli/src/cli.ts

Static Analysis

Oxlint: 26 diagnostics across 6 files (12 rules)
Density: 0.029 violations/added-line

no-unnecessary-type-arguments (10): packages/cli/src/props.ts
no-console (3): packages/cli/src/cli.ts
no-unused-vars (2): packages/cli/src/cli.ts
unbound-method (2): packages/cli/tests/support/plan-harness.ts, packages/cli/src/plan.ts
no-unsafe-type-assertion (2): packages/cli/src/cli.ts, packages/cli/src/plan.ts
consistent-function-scoping (1): packages/cli/src/authorship-profile.ts
no-useless-concat (1): packages/cli/src/plan-args.ts
no-empty-function (1): packages/cli/src/cli.ts
no-array-sort (1): packages/cli/src/props.ts
no-base-to-string (1): packages/cli/src/authorship-profile.ts
no-floating-promises (1): packages/cli/src/cli.ts
consistent-return (1): packages/cli/src/cli.ts

Correctness

No extraneous code patterns detected.

@taras
taras marked this pull request as ready for review August 31, 2026 00:33
#670)

`prompt` names no command, and a first token that names none is a document
reference to the default `run` command. So an executable document called
`prompt` in the working directory was rendered and executed by `xmd prompt` —
exit 0, and a file written — by a caller who wrote what they believed was a
command. That is authorship-adjacent execution and a durable effect from the
spelling this rename retired.

An invocation whose exact first token is `prompt` is now refused at the top of
`runXmd()`: before the inline-document scan, before command selection, and
before anything reads a path. It fails closed, establishing no catalog, Agent,
Session, authorship directory, output, journal or execution:

    xmd prompt is not a command — use `xmd plan "<Prompt>"` to create a Plan, or
    `xmd run ./prompt` to run a document named `prompt`

The message answers both readings, because the token is ambiguous by
construction. `prompt` is still not registered, aliased or listed in help — this
is a preflight refusal, not a command. Only the exact first token is recognized,
so `xmd run ./prompt`, `xmd run prompt` and `xmd ./prompt` still execute a
document legitimately called that; refusing the bare token must not cost the
ability to run a file with that name.

The earlier claim that falling through to default run satisfied the retired
spelling was wrong, and it was written down in the suite commentary, the command
spec, the mdx acceptance row and the architecture inventory. All four now
describe the fail-closed preflight instead.

No production behaviour outside that preflight changes, and the packaged
Markdown document is untouched.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 1 redundant comment. Inline suggestions to remove them below.

Comment thread packages/cli/src/cli.ts
const provisional = xmd.parse({ args: helpRequest.args });
const selected = provisional.ok ? provisional.value.config : undefined;
// The two commands that end in a document execution. `xmd prompt`'s deadline
// The two commands that end in a document execution. `xmd plan`'s deadline

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// The two commands that end in a document execution. `xmd plan`'s deadline

@taras
taras merged commit 912ae87 into main Aug 31, 2026
30 checks passed
@taras
taras deleted the agent/issue-670-plan-rename branch August 31, 2026 01:05
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.

♻️ Rename xmd prompt to xmd plan

1 participant