Skip to content

star adopts the output convention: the shared root, and extension commands as commands - #783

Merged
David-Noble-at-work merged 10 commits into
developfrom
feature/743-star-adoption
Sep 3, 2026
Merged

David-Noble-at-work merged 10 commits into
developfrom
feature/743-star-adoption

Conversation

@David-Noble-at-work

@David-Noble-at-work David-Noble-at-work commented Sep 3, 2026 •

Copy link
Copy Markdown
Contributor

Closes #743. Plan: docs/plans/feature/743-star-adoption.md — every phase complete.

star built a bare cobra.Command and inherited nothing from cmd/internal/cli; it carried a dead second
cli package; and it had ten stdout sites. Five commits:

  1. cmd/star/cli deleted. Nothing imported it. The three design documents that described the copy as live
    now say it was dead and is gone.
  2. star on the shared root. cli.NewRootCmd supplies the common set and config, man, self, version;
    star wraps the shared pre-run for --dry-run, its flag map and the one narrator. RootConfig gains
    post-install and post-uninstall hooks so the extension install survives the move; the shared root sets
    SilenceUsage; schema.StarDefaultConfig seeds config.d/star.yaml. Three Starlark extension commands
    bound --output and --format of their own: the loader now refuses a reserved name, a script's return
    value is its result through the pipeline, generate takes the provider's package as its one operand with
    --dry-run as its preview (the 30 Makefile recipes follow), validate returns its report, extract
    writes both artifacts. The LKG was taken before the first edit and retired in that commit's gates.
  3. The last eight stdout sites. Starlark print narrates; docs starlark is a result; three key leaves
    fail rather than print a note and exit 0.
  4. Ambient, not non-hermetic, in eleven lines and one definition.

Rulings recorded (2026-09-02): one config set on all four programs with a program's additions beneath;
man the one route to man pages; no usage text on any error; extension commands are commands. Found on the
way and filed for their own worktrees: #780 (every app's install manifest claims every man page) and #781
(validate's stale path). The prose-result question is logged on #740.

Acceptance criteria

The canonical checklist lives in the plan; this is its copy. Every box is checked before merge, and the
one that cannot be checked from this branch says what checks it.

Goals — the four from #743, and the five the survey, the charter and the rulings added

  • cmd/star/cli no longer exists — phase 2
  • star registers the common set through cmd/internal/cli.AddOutputFlags — by way of
    cli.NewRootCmd; TestRoot_EverySubcommandAcceptsTheCommonSet walks the tree — phase 3
  • renderTable lives in pkg/result as the suite's one table formatter — done in Epic: Command line interface — one output convention, every app #740 phase 4 as
    TableFormatter; ticked with that pointer, no work in this branch
  • No exported name is defined in two CLI packages — follows from the deletion, phase 2
  • No star command writes to stdout directly — the ten sites, grep clean — phase 4
  • star's version, self, config and man are the shared commands; config carries show and
    sync beneath, docs carries starlark alone — the shared route on all four programs — phase 3
  • No usage text on any error, on all four programs — set once on the shared root — phase 3;
    devlore-test keeps its own setting until it moves onto the shared root
  • Extension commands bind no reserved name, the loader refuses one, and a script's return value is its
    result; generate's operand is the package and --dry-run its preview; both --format flags are
    gone — phase 3
  • star continues to run — LKG taken before the first edit (from 1aaba0fd), retired by phase 3's
    script after the tree built on its own, make regenerate no diff, make install succeeded

Test rows

  • 1 — cmd/star/cli does not exist: make build green with the directory gone, phase 2
  • 2 — every subcommand accepts the common set: TestRoot_EverySubcommandAcceptsTheCommonSet (unit)
  • 3 — no command registers its own output flag: the same test, on local flags (unit)
  • 4 — --dry-run reaches starruntime.DryRun (unit)
  • 5 — --silent wires one narrator (unit)
  • 6 — star config is the shared set plus show and sync (unit)
  • 7 — star self install still installs the extensions (unit)
  • 8 — no usage text on any error, all four roots (unit)
  • 9 — star docs has starlark alone; star man is the shared command (unit)
  • 10 — reserved flag names refused, others accepted (unit)
  • 11 — a script's return value is the result (unit)
  • 12 — generate <package> reproduces the committed files; --dry-run writes nothing (make regenerate, unit)
  • 13 — no fmt.Print/os.Stdout in cmd/star non-test (grep) — phase 4
  • 14 — LKG removed, star builds from source, make regenerate no diff (build)
  • 15 — the installed star runs a command end to end (smoke)
  • 16 — the suite passes on all five platforms: darwin-arm64 locally, and on the pull request
    test (darwin-arm64), test (linux-amd64), test (linux-arm64), test (windows-amd64), test (windows-arm64) — all green

https://claude.ai/code/session_01SqQVFZz7AdiLZkGoAcUqRW

David Noble added 9 commits September 1, 2026 20:59
The survey changed its shape: cmd/star/cli is dead (main.go imports cmd/internal/cli), renderTable's
promotion already happened in #740 phase 4, and the real work is moving star's hand-built root onto
cli.NewRootCmd, which has no pre-run hook and so is wrapped. Ten stdout sites the issue did not list are
classified; star docs starlark is the epic's json-default question made concrete and is logged, not
decided.

740's thread table and 776's related documents now link the plan file, as they do for 775.

Refs #743

Claude-Session: https://claude.ai/code/session_01SqQVFZz7AdiLZkGoAcUqRW
The plan landed with status in-progress because the worktree script was rewritten while it was being run.
A plan that has not been reviewed is a draft; it moves to chartered on review.

Refs #743

Claude-Session: https://claude.ai/code/session_01SqQVFZz7AdiLZkGoAcUqRW
…lings

Reviewed 2026-09-02. star is the code generator every make target runs through, so the plan carries the
last-known-good process the Makefile documents: build/star.lkg taken before the first edit (done, from
1aaba0f, then `star self install`), retired after the tree builds from source, make regenerate no diff,
make install. Phase 1 is complete.

Checking the install found three collisions with the shared root the survey missed: star registers
version and self itself, and its config group comes from two Starlark extensions. RootConfig gains
post-install and post-uninstall hooks so star's extension install survives the move.

Three rulings, one rule -- the shared route on all four programs, a program's own additions attached
beside it:
  config: the shared set on all four; star's show and sync attach beneath.
  man: the shared `man` is the one route; star's docs man and docs markdown go; docs starlark stays.
  usage text: never on an error, not even a bad flag or an unknown subcommand -- cobra's dump is not
    context-aware; SilenceUsage: true on the shared root, once, for all four programs.

Taking the install also exposed #780, its own worktree.

Refs #743

Claude-Session: https://claude.ai/code/session_01SqQVFZz7AdiLZkGoAcUqRW
The 2026-09-02 ruling from #743, recorded where configuration is designed: devlore-test, lore, star and
writ carry the same `config` command, the shared root's, and star's show and sync attach beneath it. The
spec gains a "command surface" section stating the ruling, the two sources star's config reads today, and
that `self install` produces each program's default config (#780). The 441 plan gains the status row, the
observation that the surface is uniform before the model beneath it is, and one open question: do show and
sync join the shared set.

Refs #441, #743

Claude-Session: https://claude.ai/code/session_01SqQVFZz7AdiLZkGoAcUqRW
Nothing imported it: main.go imports cmd/internal/cli, and star's root bound no output flags from either
package. The two comments that named it are corrected. The renderTable it carried had already been promoted
to pkg/result.TableFormatter in #740 phase 4.

#743 phase 2; the plan's Phase 2 is complete.

Refs #743

Claude-Session: https://claude.ai/code/session_01SqQVFZz7AdiLZkGoAcUqRW
…rulings

The CLI design said star bound its own cmd/star/cli.AddOutputFlags; nothing imported the copy, and star's
root bound no output flags at all. Section 15 still analyzed writ reconcile's one-bool bridge as a live
defect two paragraphs after its own table said writ had none; #774 removed the bridge on 2026-08-31, and the
passage is now history with what pins it. Section 7's domain-rendering example, lore list --format manifest,
went with #779. Sections 2, 9 and 12 and decisions 7-9 now carry the 2026-09-02 rulings:
the shared root's commands are one set on the four programs with a program's additions attached beneath;
no usage text follows any error; man is the one route to man pages. star-extensions.md listed a
cmd/star/cli/selfinstall.go that never existed. The status doc and the 740 epic plan record lore's three
phase-4 boxes as landed in #779 and star's deletion as landed in phase 2. The config status doc gains the
command-surface row, the show/sync question, and the two-source discrepancy; the phase-8 implementation plan's
star-unification item records that the command surface was ruled ahead of it and what the fold adds beneath.

Refs #740, #743, #441

Claude-Session: https://claude.ai/code/session_01SqQVFZz7AdiLZkGoAcUqRW
…mmands

The hand-built root goes: cli.NewRootCmd supplies the common set, --dry-run and --silent, and config, man,
self and version. star wraps the shared pre-run to copy --dry-run into starruntime.DryRun, refresh its flag
map and point the runtime's status at the one narrator. RootConfig gains post-install and post-uninstall
hooks so star's extension install survives the move; the shared root sets SilenceUsage, so no program prints
the usage block after an error; schema.StarDefaultConfig seeds config.d/star.yaml like the other three.

Three Starlark extension commands bound flags the common set owns. The loader now refuses a reserved name.
A script's return value is its result: Command.Run returns it as JSON-shaped Go and the leaf emits it through
the pipeline. generate takes the provider's package as its one operand -- the files land inside it, so
--source, --output, --write and --gen all go, and --dry-run is the preview; the 30 Makefile recipes follow.
validate returns its report and --format goes with its markdown printers. extract writes both artifacts
and --format goes. Extension commands register in name order, so setup no longer appears twice by chance.

The LKG is retired in this commit's gates: build from source, regenerate with no diff, test, install.

#743 phase 3; the plan's Phase 3 is complete.

Refs #743

Claude-Session: https://claude.ai/code/session_01SqQVFZz7AdiLZkGoAcUqRW
… stub fails

The two Starlark print handlers narrate through cli.Note, as lore's does, so --silent gates a script's
print() with everything else. docs starlark returns its guide as a result and emits it through the pipeline;
whether a prose result should default to value is logged on #740. The three key leaves, unimplemented until
ADR-040, fail with an error that says so rather than printing a note and exiting 0 -- the plan had classed
them as narration, and the checklist's rule against stubs that report success overrides that.

No fmt.Print or os.Stdout remains in cmd/star outside tests.

#743 phase 4; the plan's Phase 4 is complete.

Refs #743

Claude-Session: https://claude.ai/code/session_01SqQVFZz7AdiLZkGoAcUqRW
The opposite of hermetic is ambient: a runtime that takes its context from what surrounds it. "Non-hermetic"
named an absence. Eleven lines in six files -- the scripting runtime's banner and its comment, the execution
runtime's note and comment, two test names, the method-classification table, and two plan documents -- now
say ambient, and 2.4-hermeticity-guarantees.md defines the pair once beside hermetic.

#743 phase 5; every phase of the plan is complete.

Refs #743

Claude-Session: https://claude.ai/code/session_01SqQVFZz7AdiLZkGoAcUqRW
@David-Noble-at-work David-Noble-at-work self-assigned this Sep 3, 2026
…nd goValue asserts no type

Both Windows test legs failed because the test built the operand with filepath.Join, and the generator
wrote pkg\op\provider\json into the package clause. A Go package path is slash-separated on every
platform; the test says so and reads the files through the platform separator. quality-gate flagged the
one unchecked type assertion in goValue; the list and tuple cases are now separate and assert nothing.

Refs #743

Claude-Session: https://claude.ai/code/session_01SqQVFZz7AdiLZkGoAcUqRW
@David-Noble-at-work
David-Noble-at-work merged commit 4c8c62e into develop Sep 3, 2026
12 checks passed
@David-Noble-at-work
David-Noble-at-work deleted the feature/743-star-adoption branch September 3, 2026 04:00
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.

cmd/star/cli duplicates cmd/internal/cli, and the two now disagree on the flag surface

1 participant