Repository navigation
lore adopts the output convention, and search stops cutting descriptions mid-rune - #779
Merged
Merged
Conversation
…ons mid-rune Closes #775 Closes #741 lore registered the common set on `inspect` alone -- a stub -- so the convention was learnable on one command out of fourteen, and `lore search -o json` was an unknown flag. Every other command invented its own output, and the one real table in the tree was hand-rolled. Five phases; zero stdout writes remain. THE ROOT REGISTERS THE SET. AddOutputFlags moves from inspect to the root, so every subcommand inherits --output, --filter, --jq and --store, and a fix in cmd/internal/cli reaches all of them at once. emitResult and the package-level outputOptions mirror writ's. TestRoot_EverySubcommandAcceptsTheCommonSet walks the tree and refuses any command that registers --output, --format or --json of its own. SEARCH IS A RESULT. runSearch's four fmt.Print become searchRows -> emitResult: a row per result with json-tagged fields, rendered by -o table through the shared TableFormatter, which aligns by rune and truncates nothing. That is where #741 goes away -- the old loop cut descriptions at desc[:47], through the middle of any multi-byte character that landed there. TestSearchRows_KeepsMultiByteDescriptions puts 47 bytes of ASCII and then an e-acute through the row and the table, and requires both intact. It was red by construction: searchRows did not exist, and the loop it replaced truncated. `installed` is a column rather than an asterisk glued to the name. A DESTINATION IS A POSITIONAL OPERAND. bundle becomes `bundle @<manifest> <output>` and onboard `onboard --from <source> [<dir>]`, the directory defaulting to `.` -- per the ruling recorded in 10-command-line-interface.md §4 two commits ago. Both were stubs or nearly so; the flags that collided with -o are gone. list's --format is gone with them. ONBOARD'S --format WAS DEAD, and is deleted rather than renamed: generateManifest took it as `_` and always wrote packages-manifest.yaml. The Format field is gone from loreOnboardConfig and onboard.Options, the parameter from generateManifest, and the assertion from the test that carried it. ONBOARD EMITS ITS RESULT. onboard.Result -- product, vendor, version, complexity, concerns, slots, the manifest text -- was narrated to stderr and stdout was silent. The file write is the side effect; the Result now goes to emitResult, so `-o json` yields the discovery and `--jq '.product'` selects it. TestOnboardResult_EmitsThroughThePipeline pins the shape; the two-line wiring is read by eye, because onboard.Run needs an AI provider. THE NINE OTHER fmt.Print ARE NARRATION: "Resolving packages...", the resolution status table, the LOW-confidence warning, the y/N prompt, "Deploying packages...", and builder.go's Starlark [print] -- progress and interaction during commands whose result is their exit. All to cli.* on stderr. The two lore guides that taught --format now say -o. The status document ticks lore's box; the conformance table moves lore to "none". The plan carries the acceptance criteria; one row is CI's. make build, make vet, make test (104 ok, 0 FAIL), gofmt -l and Test-GuideFrontmatter.sh are green. Claude-Session: https://claude.ai/code/session_01SqQVFZz7AdiLZkGoAcUqRW
David-Noble-at-work
pushed a commit
that referenced
this pull request
Sep 2, 2026
…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
David-Noble-at-work
added a commit
that referenced
this pull request
Sep 3, 2026
…mands as commands (#783) * Add the plan for #743: star adopts the output convention 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 * Plan #743 is a draft until it is reviewed 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 * Charter the plan for #743: LKG taken, three more collisions, three rulings 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 * Config spec and plan: the command surface is one set on four programs 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 * Delete cmd/star/cli, the dead copy of cmd/internal/cli 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 * Align the CLI and config design docs with #743 phase 2 and the three 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 * star moves onto the shared root, and its extension commands become commands 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 * star's last eight stdout sites: narration narrates, a result emits, a 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 * Ambient, not non-hermetic 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 * CI: the dry-run test hands the generator a slash-separated package, and 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 --------- Co-authored-by: David Noble <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #775
Closes #741
loreregistered the common set oninspectalone — a stub — so the convention was learnable on onecommand out of fourteen. Every other command invented its own output, and the one real table in the tree
was hand-rolled. Five phases; zero stdout writes remain in
cmd/lore.Acceptance criteria
The canonical copy is the plan's own section —
775-lore-adoption.md§ Acceptance criteria.Every box is checked before merge.
Goals
lore's root registers the common set, so every subcommand accepts every flag —TestRoot_EverySubcommandAcceptsTheCommonSetwalks the treelorecommand carries an output flag of its own — the same test, on each command's local flagssearchRowsthroughTableFormatterTest rows
TestRoot_EverySubcommandAcceptsTheCommonSet(unit)lore search -o tablerenders throughTableFormatter:TestSearchRows_KeepsMultiByteDescriptions(unit)
é— lore search truncates descriptions by byte count, cutting multi-byte characters mid-rune #741'sverification, red by construction before the fix
lorecommand registers--output,--formator--json: the root test (unit); tree-wide isEnforcement: two tests that fail when a command leaves the output convention #776's by design
lore <cmd> -o nonewrites nothing to stdout: zerofmt.Print/os.Stdoutremain non-test; theper-package test is Enforcement: two tests that fail when a command leaves the output convention #776's by design
onboardhas no--format/--output; the directory is its positional: the twoParseLoreOnboardConfigtests (unit)onboard -o jsonemits the discovery,-o noneleaves only the file:TestOnboardResult_EmitsThroughThePipelinepins the shape (unit); the two-line wiring is read by eye,since
onboard.Runneeds an AI providertest (darwin-arm64), test (linux-amd64), test (linux-arm64), test (windows-amd64), test (windows-arm64) — all green
Gates, every phase:
make build,make vet,make test,gofmt -lempty,Test-GuideFrontmatter.sh.The five phases
inspectstops being the one adopter.emitResultandoutputOptionsmirror
writ's.fmt.PrintbecomesearchRows→ the shared table, which aligns by rune andtruncates nothing. That is where lore search truncates descriptions by byte count, cutting multi-byte characters mid-rune #741's
desc[:47]cut goes away.bundle @<manifest> <output>;onboard --from <source> [<dir>].The ruling is in
10-command-line-interface.md§4.onboard's--formatwas dead — the parameter itfed was
_— and is deleted, not renamed.list's--formatgoes too.onboardemits its result. The file write is the side effect;onboard.Resultis what-orenders.Before this, stdout was silent.
fmt.Printare narration — progress and a y/N prompt during mutating commands, andbuilder.go's Starlark[print]— all tocli.*on stderr.Also here
loreguides that taught--formatnow say-olore's box; the conformance table movesloreto "none"Informational
The search table's columns are alphabetical now —
confidence, description, installed, name, source, version— because stage-1 normalization sorts map keys, the same aswrit reconcile's table. The oldPACKAGE SOURCE CONF …order was the hand-rolled formatter's and went with it.https://claude.ai/code/session_01SqQVFZz7AdiLZkGoAcUqRW