Remove completed alias planning and remediation documents
This commit is contained in:
@@ -11,10 +11,10 @@ The [README](../README.md) provides project orientation; the
|
|||||||
[documentation policy](policy/documentation.md#canonical-ownership) assigns
|
[documentation policy](policy/documentation.md#canonical-ownership) assigns
|
||||||
canonical documentation owners.
|
canonical documentation owners.
|
||||||
|
|
||||||
For application-owned alias scope, implementation history, and accepted
|
For application-owned aliases, use the
|
||||||
decisions, use its
|
[CLI reference](cli.md#application-owned-aliases),
|
||||||
[feature roadmap](roadmap/aliases.md), [implementation sequence](roadmap/implementation.md),
|
[Go declarations and GoDoc](../command.go), and
|
||||||
and [ADR 0013](adr/0013-application-alias-routing.md). Keep deferred capabilities in
|
[ADR 0013](adr/0013-application-alias-routing.md). Keep deferred capabilities in
|
||||||
[deferred work](roadmap/deferred.md).
|
[deferred work](roadmap/deferred.md).
|
||||||
|
|
||||||
## Initial orientation
|
## Initial orientation
|
||||||
@@ -53,7 +53,7 @@ and [ADR 0013](adr/0013-application-alias-routing.md). Keep deferred capabilitie
|
|||||||
| Task | Read |
|
| Task | Read |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Implemented CLI behavior | [CLI reference](cli.md) |
|
| Implemented CLI behavior | [CLI reference](cli.md) |
|
||||||
| Application-owned aliases | [Feature roadmap](roadmap/aliases.md), [implementation plan](roadmap/implementation.md), and [ADR 0013](adr/0013-application-alias-routing.md) |
|
| Application-owned aliases | [CLI reference](cli.md#application-owned-aliases), [Go declarations and GoDoc](../command.go), [consumer guide](consumers/guide.md#application-owned-aliases), and [ADR 0013](adr/0013-application-alias-routing.md) |
|
||||||
| Public API usage and standard-suite wiring | [Consumer guide](consumers/guide.md), [ckconfig package](../integrations/ckconfig/doc.go), [ckprompt package](../integrations/ckprompt/doc.go), and applicable ADRs |
|
| Public API usage and standard-suite wiring | [Consumer guide](consumers/guide.md), [ckconfig package](../integrations/ckconfig/doc.go), [ckprompt package](../integrations/ckprompt/doc.go), and applicable ADRs |
|
||||||
| Dispatcher, registration, or typed inputs | [Command declarations](../command.go), [bindings](../binding.go), [invocation](../execute.go), and [ADR 0001](adr/0001-command-dispatch-and-inputs.md), refined by [ADR 0011](adr/0011-captured-declarations-and-installation.md) |
|
| Dispatcher, registration, or typed inputs | [Command declarations](../command.go), [bindings](../binding.go), [invocation](../execute.go), and [ADR 0001](adr/0001-command-dispatch-and-inputs.md), refined by [ADR 0011](adr/0011-captured-declarations-and-installation.md) |
|
||||||
| Backend integration | [Internal overview](internal/overview.md), [adapter implementation](../internal/cobra/parse.go), and [ADR 0002](adr/0002-cobra-backend.md) |
|
| Backend integration | [Internal overview](internal/overview.md), [adapter implementation](../internal/cobra/parse.go), and [ADR 0002](adr/0002-cobra-backend.md) |
|
||||||
@@ -70,7 +70,8 @@ Read all applicable rows for cross-cutting work. Go declarations and GoDoc own
|
|||||||
current exported contracts; the CLI reference owns operator behavior. The
|
current exported contracts; the CLI reference owns operator behavior. The
|
||||||
[maintainer release procedure](release.md) owns current release operations.
|
[maintainer release procedure](release.md) owns current release operations.
|
||||||
Completed roadmaps and implementation evidence remain available in Git history,
|
Completed roadmaps and implementation evidence remain available in Git history,
|
||||||
including [PromptKit requirements implementation and remediation](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/40499a43608bf60d1104cd8ee24caf18ac0e9e66/docs/roadmap).
|
including [application-owned alias planning, implementation, and remediation](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/f42aefe02d84e154855ac922173e6f367180929f/docs/roadmap)
|
||||||
|
and [PromptKit requirements implementation and remediation](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/40499a43608bf60d1104cd8ee24caf18ac0e9e66/docs/roadmap).
|
||||||
These records are not assignments to restart completed work. The
|
These records are not assignments to restart completed work. The
|
||||||
[deferred-work record](roadmap/deferred.md) preserves future capability targets
|
[deferred-work record](roadmap/deferred.md) preserves future capability targets
|
||||||
and unselected proposals separately from current contracts.
|
and unselected proposals separately from current contracts.
|
||||||
|
|||||||
@@ -1,598 +0,0 @@
|
|||||||
# Application-owned aliases
|
|
||||||
|
|
||||||
Status: implementation and [review remediation](remediation.md) complete;
|
|
||||||
core v0.3.0 release note prepared and publication pending. OD-1 through OD-6
|
|
||||||
are resolved. This roadmap records the target and selected behavior. The
|
|
||||||
[completed implementation plan](implementation.md) preserves delivery sequencing
|
|
||||||
and stage-specific validation. Current contracts belong to the
|
|
||||||
[Go declarations and GoDoc](../../command.go) and
|
|
||||||
[CLI reference](../cli.md#application-owned-aliases).
|
|
||||||
[ADR 0013](../adr/0013-application-alias-routing.md) records the accepted
|
|
||||||
architectural ownership and shared installation decisions.
|
|
||||||
|
|
||||||
## Purpose and ownership
|
|
||||||
|
|
||||||
Make alternate command paths and flag spellings simple for consuming
|
|
||||||
applications to declare. CommandKit core owns alias registration, resolution,
|
|
||||||
and integration with routing and help. Applications choose their aliases.
|
|
||||||
Integrated libraries continue to own their canonical command behavior.
|
|
||||||
|
|
||||||
Aliases occupy a separate application routing layer above installed canonical
|
|
||||||
commands:
|
|
||||||
|
|
||||||
```text
|
|
||||||
CLI argument tokens
|
|
||||||
→ command-path alias resolution
|
|
||||||
→ canonical command or discovery-help context selection
|
|
||||||
→ applicable flag-alias resolution using that context's flag metadata
|
|
||||||
→ input parsing
|
|
||||||
→ ordinary invocation lifecycle or discovery help
|
|
||||||
```
|
|
||||||
|
|
||||||
Alias declarations do not install new handlers or modify the canonical command
|
|
||||||
tree. An alias spelled inside `promptkit` therefore does not add an
|
|
||||||
application-owned operation to the integration's namespace. The ownership and
|
|
||||||
placement rules in [ADR 0011](../adr/0011-captured-declarations-and-installation.md)
|
|
||||||
and the [architecture policy](../policy/architecture.md) continue to govern
|
|
||||||
canonical command installation.
|
|
||||||
|
|
||||||
Flag aliases likewise leave canonical flag definitions and typed bindings
|
|
||||||
unchanged. This is one conceptual routing layer; its internal implementation
|
|
||||||
cooperates with the existing parser to preserve token interpretation.
|
|
||||||
|
|
||||||
## Preimplementation baseline
|
|
||||||
|
|
||||||
At the planning baseline, core captured reusable `Command` declarations and
|
|
||||||
installed them through `New` and `App.Register`. Installation validated a batch
|
|
||||||
before registry mutation. Optional standard families owned their installed root
|
|
||||||
namespaces. Core routing and the internal backend coordinated parsing, help,
|
|
||||||
and execution through one invocation lifecycle.
|
|
||||||
|
|
||||||
That public model had no application alias layer. PromptKit already exposed
|
|
||||||
the collection catalog and smoke-test command used in the examples below.
|
|
||||||
`promptkit test` took a `KIND` operand, including `all`; those values were not
|
|
||||||
registered child commands. The examples illustrate alternate routes to existing
|
|
||||||
capabilities; they do not introduce new PromptKit operations.
|
|
||||||
|
|
||||||
The [CLI reference](../cli.md) owns current grammar. Options follow the complete
|
|
||||||
command path, can be interspersed with operands, and use `--` to terminate
|
|
||||||
option parsing. Aliasing preserves the target's grammar and typed binding
|
|
||||||
contracts.
|
|
||||||
|
|
||||||
## Selected declaration and registration conventions
|
|
||||||
|
|
||||||
Commands and aliases use the same installation boundary through `New` and
|
|
||||||
`App.Register`. Core validates the complete batch together while retaining
|
|
||||||
aliases as separate routing records internally. No separate alias-registration
|
|
||||||
API is needed.
|
|
||||||
|
|
||||||
### Installation types and composition
|
|
||||||
|
|
||||||
The delivered API has a common `Declaration` interface with an unexported marker
|
|
||||||
method. CommandKit supplies its implementations through public factories. `Command`
|
|
||||||
represents canonical commands; a separate opaque `RoutingRule` represents
|
|
||||||
aliases. Both satisfy `Declaration`:
|
|
||||||
|
|
||||||
```text
|
|
||||||
Declaration
|
|
||||||
├── Command → canonical command tree
|
|
||||||
└── RoutingRule → alias routing layer
|
|
||||||
```
|
|
||||||
|
|
||||||
The selected installation signatures are:
|
|
||||||
|
|
||||||
```go
|
|
||||||
func New(identity Identity, declarations ...Declaration) (*App, error)
|
|
||||||
func (a *App) Register(declarations ...Declaration) error
|
|
||||||
```
|
|
||||||
|
|
||||||
`NewCommand`, `Group`, and integration command factories return `Command`.
|
|
||||||
`Alias`, `FlagAlias`, and `FlagAliasFor` return `RoutingRule`. The common
|
|
||||||
installation boundary validates relationships across the layers atomically;
|
|
||||||
installation directs each declaration to its corresponding registry. Routing
|
|
||||||
rules reference canonical commands without becoming command nodes or owning
|
|
||||||
handlers. Preserve eager capture and retained construction errors for both
|
|
||||||
declaration kinds, without introducing deferred installation callbacks.
|
|
||||||
|
|
||||||
`Group`, `RootGroup`, and command children continue to accept only `Command`.
|
|
||||||
Install routing rules alongside the completed canonical tree through `New` or
|
|
||||||
`Register`. Alias paths remain relative to the application root; moving a
|
|
||||||
command beneath a group does not silently rebase an alias.
|
|
||||||
|
|
||||||
Use ordinary `[]Declaration` slices for reusable collections containing commands
|
|
||||||
and routing rules. Command-only helpers may return `Command` or `[]Command`.
|
|
||||||
Go does not allow expanding `[]Command` into `...Declaration`; callers assembling
|
|
||||||
installation collections should use `[]Declaration` or convert their elements.
|
|
||||||
No additional bundle abstraction is selected.
|
|
||||||
|
|
||||||
### Consumer declarations
|
|
||||||
|
|
||||||
Use space-separated strings for command paths, interpreted as sequences of
|
|
||||||
command names without shell quoting or expansion. Application-wide flag aliases
|
|
||||||
use `FlagAlias`; command-scoped aliases use `FlagAliasFor` with an explicit
|
|
||||||
canonical command path. The selected consumer-facing shape is:
|
|
||||||
|
|
||||||
```go
|
|
||||||
app, err := commandkit.New(
|
|
||||||
identity,
|
|
||||||
ckprompt.Command(suite),
|
|
||||||
commandkit.Alias("list collections", "promptkit list collections"),
|
|
||||||
commandkit.FlagAlias("--hlep", "--help"),
|
|
||||||
commandkit.FlagAliasFor("promptkit show prompt", "--fmt", "--format"),
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
These APIs are implemented. Later registration uses the same model and validation.
|
|
||||||
|
|
||||||
Accept identical duplicate alias mappings as harmless, including when reusable
|
|
||||||
helpers contribute them. Identity includes the alias kind, source, target, and
|
|
||||||
scope where applicable. Different-target command mappings for the same source
|
|
||||||
remain errors; flag scope precedence is specified below.
|
|
||||||
|
|
||||||
Alias support lives entirely in core and works with built-in commands,
|
|
||||||
application commands, optional integrations, or any combination. Validation
|
|
||||||
uses the commands and flags installed in that application. No integration
|
|
||||||
dependency is required for alias support. Core continues to supply help and
|
|
||||||
version automatically, including for applications whose other commands are
|
|
||||||
entirely application-defined.
|
|
||||||
|
|
||||||
### Shared path handling
|
|
||||||
|
|
||||||
Centralize path parsing, component validation, comparison, and formatting in
|
|
||||||
shared internal helpers with a common structured path representation. Alias
|
|
||||||
validation, routing, help lookup, and invocation metadata use those primitives.
|
|
||||||
Keep the routing and canonical command models distinct while sharing path
|
|
||||||
operations.
|
|
||||||
|
|
||||||
Declaration factories tokenize command-path strings on whitespace, accepting
|
|
||||||
leading, trailing, and repeated whitespace, then validate each component using
|
|
||||||
the canonical command-name rules. Reject empty paths and invalid components.
|
|
||||||
Normalize equivalent paths before duplicate detection. Quotes and backslashes
|
|
||||||
receive no shell interpretation; paths cannot contain flag assignments or
|
|
||||||
operand templates. Capture parsed paths once when constructing declarations.
|
|
||||||
|
|
||||||
CLI arguments are already tokenized. Preserve those boundaries: an argument
|
|
||||||
containing `list collections` is one argument, not two command components.
|
|
||||||
Do not trim or split incoming operands or flag values. Invocation routing
|
|
||||||
identifies the command portion of the supplied tokens and carries structured
|
|
||||||
paths through alias resolution and canonical selection. Format paths for
|
|
||||||
presentation when needed, avoiding repeated string joining and parsing through
|
|
||||||
alias chains.
|
|
||||||
|
|
||||||
Convert inputs at their appropriate boundaries and reuse the result where
|
|
||||||
practical. Parsing once per query is an implementation objective, not a permanent
|
|
||||||
allocation or parsing guarantee. Use an internal path package if sharing across
|
|
||||||
core and the backend adapter warrants it; otherwise private core helpers and a
|
|
||||||
path type suffice. No additional public path package is selected.
|
|
||||||
|
|
||||||
## Selected command-alias behavior
|
|
||||||
|
|
||||||
### Paths and resolution
|
|
||||||
|
|
||||||
Declare mappings between command paths relative to the application root. The
|
|
||||||
executable name is not part of either path:
|
|
||||||
|
|
||||||
| Alias path | Target path |
|
|
||||||
| --- | --- |
|
|
||||||
| `list collections` | `promptkit list collections` |
|
|
||||||
| `promptkit list bundles` | `promptkit list collections` |
|
|
||||||
| `list` | `promptkit list` |
|
|
||||||
|
|
||||||
Aliases can target individual commands or groups. A group alias preserves
|
|
||||||
remaining subcommand tokens. For example, `list collections` can reach
|
|
||||||
`promptkit list collections` through the `list` group alias.
|
|
||||||
|
|
||||||
Match exact, complete argument tokens at the beginning of the command path;
|
|
||||||
`list` does not match `listing`. Resolve overlapping alias paths using the
|
|
||||||
longest matching path, measured by the number of command-path tokens, not
|
|
||||||
character count. This rule applies at each command-alias lookup and is
|
|
||||||
independent of registration order. Sorting by descending token count and taking
|
|
||||||
the first matching prefix is one possible implementation; the algorithm remains
|
|
||||||
an implementation choice.
|
|
||||||
|
|
||||||
For example, with `list → promptkit list` and
|
|
||||||
`list collections → application collections`, the more specific mapping wins
|
|
||||||
for `list collections`, while `list prompts` uses the `list` mapping.
|
|
||||||
|
|
||||||
Once a matching alias is selected, resolve that route and apply canonical
|
|
||||||
validation. A validation failure reports an error; it does not retry a shorter
|
|
||||||
alias that could invoke a different command.
|
|
||||||
|
|
||||||
Preserve trailing arguments,
|
|
||||||
including flags, operands, explicit empty values, and `--`, for canonical
|
|
||||||
parsing. Values and operands are not searched for alias text.
|
|
||||||
|
|
||||||
The initial command-alias feature maps command paths. Preset flags, operand
|
|
||||||
transformation, and arbitrary argument rewriting are outside this delivery.
|
|
||||||
|
|
||||||
### Chains and group composition
|
|
||||||
|
|
||||||
Support alias chains and resolve them to their canonical target. At each lookup,
|
|
||||||
select the longest matching command-path prefix, replace it with its target,
|
|
||||||
and preserve the remaining tokens. Repeat command-path resolution until the
|
|
||||||
canonical route is reached, then parse its inputs normally. Flags, flag values,
|
|
||||||
and operands remain outside command-alias matching under the command/operand
|
|
||||||
boundary rules below.
|
|
||||||
|
|
||||||
A group shortcut provides access to routes beneath its target, including aliases:
|
|
||||||
|
|
||||||
```text
|
|
||||||
pk → promptkit
|
|
||||||
promptkit list bundles → promptkit list collections
|
|
||||||
```
|
|
||||||
|
|
||||||
Here, `pk list bundles` resolves through `promptkit list bundles` to
|
|
||||||
`promptkit list collections`. An explicitly declared `pk list bundles` alias
|
|
||||||
would take precedence over `pk` at the initial lookup. Ordinary chains follow the same
|
|
||||||
rules, for example `collections → list collections → promptkit list collections`.
|
|
||||||
|
|
||||||
Validate composition during installation and reject cycles and nonterminating
|
|
||||||
prefix expansion with diagnostics identifying the participating mappings.
|
|
||||||
Checking only for repeated complete paths is insufficient: `a → b extra` and
|
|
||||||
`b → a` continually expand the path without repeating it. Analyze prefix
|
|
||||||
composition so these configuration errors are caught before invocation. An
|
|
||||||
arbitrary runtime hop limit is not a substitute for installation validation
|
|
||||||
and must not reject an otherwise valid long chain.
|
|
||||||
|
|
||||||
A dependency-graph cycle or repeated use of a declaration does not by itself
|
|
||||||
establish nontermination. With canonical group `group`, the mappings `a → group`
|
|
||||||
and `group again → a` allow `a again again` to terminate: each round consumes
|
|
||||||
an `again` token. Validate actual prefix-resolution behavior, including
|
|
||||||
terminating repetitions, suffix-dependent cycles, and growing expansions.
|
|
||||||
Termination validation must distinguish these cases without conservatively
|
|
||||||
rejecting terminating repetitions.
|
|
||||||
|
|
||||||
### Installation and collisions
|
|
||||||
|
|
||||||
Use the shared declaration and installation conventions above for aliases,
|
|
||||||
application commands, and integration commands.
|
|
||||||
|
|
||||||
An alias target may already be installed or be supplied in the same installation
|
|
||||||
batch. Declaration order within that batch does not affect resolution. Missing
|
|
||||||
targets, collisions, and cycles produce installation errors with useful path
|
|
||||||
context. Failed installation preserves the existing application registry and
|
|
||||||
alias mappings under the existing batch-atomicity model.
|
|
||||||
|
|
||||||
A declared target must resolve entirely to a canonical command or group,
|
|
||||||
without leftover operand tokens. For example, reject
|
|
||||||
`Alias("fast", "run production")` when canonical `run` takes `production` as
|
|
||||||
an operand. Command aliases do not inject fixed operands.
|
|
||||||
|
|
||||||
Likewise, `promptkit test full → promptkit test all` is invalid: `all` is an
|
|
||||||
operand of canonical `promptkit test KIND`, and the source would intercept
|
|
||||||
that command's operand space. A command-path shortcut such as
|
|
||||||
`smoke → promptkit test` is valid; `smoke all` preserves the operator-supplied
|
|
||||||
`all` operand. Synonyms for operand values require a separate capability and
|
|
||||||
are outside this delivery.
|
|
||||||
|
|
||||||
An alias cannot conflict with or overload a canonical command path. Reject such
|
|
||||||
a declaration during installation as invalid application configuration. Apply
|
|
||||||
the same protection when later registration adds a canonical command conflicting
|
|
||||||
with an existing alias. Reject competing mappings from the same source path to
|
|
||||||
different targets; registration order must not select a winner. Identical
|
|
||||||
duplicate mappings are accepted under the shared registration conventions.
|
|
||||||
|
|
||||||
Aliases do not create canonical parent groups, merge integration trees, or
|
|
||||||
replace handlers.
|
|
||||||
|
|
||||||
### Prefix interactions and canonical reachability
|
|
||||||
|
|
||||||
Alias paths may share prefixes with canonical paths when they introduce a
|
|
||||||
distinct route. Preserve existing canonical invocations, including the declared
|
|
||||||
operand space of runnable commands.
|
|
||||||
|
|
||||||
| Canonical declaration | Proposed alias | Result |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| `promptkit list collections` | `promptkit list bundles` → `promptkit list collections` | Allow the distinct route beneath the shared prefix. |
|
|
||||||
| `list projects` | `list collections` → `promptkit list collections` | Allow the distinct route beneath the shared prefix. |
|
|
||||||
| `list` group | `list` → `promptkit list` | Reject replacement of the canonical group path. |
|
|
||||||
| `run` accepts an operand | `run full` → another command | Reject interception of `full` in the canonical command's operand space. |
|
|
||||||
|
|
||||||
Determine command and operand boundaries from declared command structure and
|
|
||||||
argument metadata, without executing handlers or application validation.
|
|
||||||
Longest-path matching chooses among valid aliases; it does not authorize
|
|
||||||
consumption of canonical operands. Sharing a runnable ancestor alone does not
|
|
||||||
establish a conflict: check whether the proposed route intercepts that
|
|
||||||
ancestor's operands or an existing canonical child route.
|
|
||||||
|
|
||||||
Explicit longer aliases beneath an alternate spelling still use longest-match
|
|
||||||
precedence. With canonical `run TARGET`, `r → run`, and `r full → inspect`,
|
|
||||||
`r full` invokes canonical `inspect`; canonical `run full` retains its operand
|
|
||||||
meaning. If only `r → run` exists, `r full` reaches `run` with operand `full`,
|
|
||||||
which is not searched for aliases after the route resolves. Canonical operand
|
|
||||||
protection does not reserve the operand space of every alternate spelling.
|
|
||||||
|
|
||||||
Check these conflicts against the complete candidate registry when adding
|
|
||||||
either aliases or canonical commands, including later registration. Report the
|
|
||||||
conflicting paths and preserve batch atomicity. Apply the chain and group
|
|
||||||
composition rules above when validating resolved routes.
|
|
||||||
|
|
||||||
### Execution and help
|
|
||||||
|
|
||||||
An invocation through an alias uses the canonical target's flags, operands,
|
|
||||||
defaults, typed bindings, input preparation, providers, diagnostics, and
|
|
||||||
outcomes. Execute the ordinary lifecycle once. Alias registration, resolution,
|
|
||||||
and help do not invoke application input/state factories or acquisition callbacks.
|
|
||||||
|
|
||||||
Expose the original entered command path and final resolved canonical command
|
|
||||||
path as read-only invocation metadata. Both paths exclude the executable name,
|
|
||||||
flags, and operands. For a direct canonical invocation the paths are equal;
|
|
||||||
for `app pk list bundles`, they can be `pk list bundles` and
|
|
||||||
`promptkit list collections`.
|
|
||||||
Retain the endpoints through a chain; intermediate rewrites are not part of
|
|
||||||
the selected public metadata.
|
|
||||||
|
|
||||||
Consumers can use the canonical path to identify the operation consistently
|
|
||||||
and the entered path for logging and diagnostics. CommandKit dispatch and
|
|
||||||
bindings continue to use the canonical target. Expose the paths through these
|
|
||||||
accessors, returning normalized, space-separated strings:
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (inv Invocation) EnteredPath() string
|
|
||||||
func (inv Invocation) CanonicalPath() string
|
|
||||||
```
|
|
||||||
|
|
||||||
Strings provide read-only values and match the declaration path representation.
|
|
||||||
|
|
||||||
Support both help forms:
|
|
||||||
|
|
||||||
```text
|
|
||||||
scriptorium help list collections
|
|
||||||
scriptorium list collections --help
|
|
||||||
```
|
|
||||||
|
|
||||||
Alias help describes the canonical target's inputs using the alias invocation
|
|
||||||
path and identifies the canonical command. Root help lists explicitly declared
|
|
||||||
command aliases separately from canonical commands, showing their resolved
|
|
||||||
canonical targets. Ordinary help need not show intermediate chain mappings or
|
|
||||||
enumerate every route reachable through group shortcuts.
|
|
||||||
|
|
||||||
Group help includes relevant aliases separately from canonical children. For
|
|
||||||
example, `help promptkit list` shows `bundles → promptkit list collections`.
|
|
||||||
Help reached through a group alias uses that spelling in usage examples and presents the
|
|
||||||
routes available through it, including applicable aliases beneath the target.
|
|
||||||
Account for more-specific mappings so displayed destinations match routing.
|
|
||||||
|
|
||||||
Provide discovery help for alias-only prefixes. If `list collections` and
|
|
||||||
`list prompts` are declared without a canonical `list` group, both `help list`
|
|
||||||
and `list --help` display the available routes. This help view is derived from
|
|
||||||
alias declarations and creates no canonical group or namespace ownership.
|
|
||||||
Bare `list` reports an incomplete command and points to that help.
|
|
||||||
|
|
||||||
Routing can select this discovery-help context without selecting a canonical
|
|
||||||
command. It uses core's help metadata and applicable application-wide flag
|
|
||||||
aliases, so `list --hlep` can request the same help. It neither inherits flags
|
|
||||||
from descendant commands nor creates a canonical command node.
|
|
||||||
|
|
||||||
Usage errors use the entered path and identify the canonical target when one
|
|
||||||
has been resolved, while preserving the canonical command's diagnostic content:
|
|
||||||
|
|
||||||
```text
|
|
||||||
Usage: scriptorium list collections [flags]
|
|
||||||
Alias for: scriptorium promptkit list collections
|
|
||||||
```
|
|
||||||
|
|
||||||
If resolution fails before identifying a target, report the entered route
|
|
||||||
without assigning a canonical identity.
|
|
||||||
|
|
||||||
## Selected flag-alias behavior
|
|
||||||
|
|
||||||
### Spellings and scopes
|
|
||||||
|
|
||||||
Applications can declare alternate spellings for canonical flags, including
|
|
||||||
`--hlep` mapping to `--help`. Declaring a flag alias should be as simple as
|
|
||||||
declaring a command alias, using the shared registration conventions above.
|
|
||||||
Validate each source and target as an individual flag spelling; declarations
|
|
||||||
do not accept clusters, attached values, or other argument expressions.
|
|
||||||
|
|
||||||
Support application-wide mappings and mappings scoped to a canonical command.
|
|
||||||
The selected canonical command determines the applicable flag aliases, so a
|
|
||||||
command-scoped mapping works through every command alias that reaches that
|
|
||||||
target. A command-scoped mapping takes precedence over an application-wide
|
|
||||||
mapping for the same alias spelling. Reject different-target mappings within
|
|
||||||
the same scope; identical duplicates are harmless. Registration order does not
|
|
||||||
choose a winner, and neither scope may overload an applicable canonical flag.
|
|
||||||
|
|
||||||
An application-wide mapping is available wherever its target flag exists and
|
|
||||||
contributes nothing elsewhere. For example, `--colour → --color` need not require
|
|
||||||
every command to define `--color`. On a command without that target, `--colour`
|
|
||||||
receives the ordinary unknown-flag error. Reusable application-wide declarations
|
|
||||||
are valid even when no currently installed command has their target flag.
|
|
||||||
|
|
||||||
A command-scoped mapping requires its named canonical command and target flag
|
|
||||||
to exist in the complete candidate installation batch. An unavailable explicit
|
|
||||||
destination is invalid configuration.
|
|
||||||
|
|
||||||
Application-wide mappings also apply to built-in flags at the application root
|
|
||||||
and on groups. In particular, `--hlep → --help` works wherever canonical
|
|
||||||
`--help` works, including help for alias-only prefixes.
|
|
||||||
|
|
||||||
Later registration repeats validation against the candidate registry. Newly
|
|
||||||
installed commands gain applicable application-wide aliases automatically;
|
|
||||||
canonical spelling collisions reject the batch under the collision rules below.
|
|
||||||
|
|
||||||
### Token interpretation
|
|
||||||
|
|
||||||
Resolve command aliases and select the canonical command or discovery-help
|
|
||||||
context before applying its flag aliases. Use that context's flag metadata to
|
|
||||||
distinguish flag names from values. Preserve the existing grammar, including
|
|
||||||
flags interspersed with operands.
|
|
||||||
|
|
||||||
| Input | Effect |
|
|
||||||
| --- | --- |
|
|
||||||
| `list collections --hlep` | Resolve the command path and route `--hlep` to canonical help. |
|
|
||||||
| `foo --colour=blue` | With `--colour` mapped to `--color`, preserve `blue` as the value. |
|
|
||||||
| `foo --message=--hlep` | Preserve the value `--hlep`. |
|
|
||||||
| `foo --message --hlep` | When `--message` consumes a value, preserve `--hlep` as that value. |
|
|
||||||
| `foo -- --hlep` | Preserve the operand `--hlep` after the option terminator. |
|
|
||||||
|
|
||||||
Only tokens interpreted as flag names participate in flag aliasing. Preserve
|
|
||||||
values, explicit empty strings, and operands. The routing layer cooperates with
|
|
||||||
the existing parser rather than maintaining a separate interpretation of flag
|
|
||||||
arity, boolean syntax, or option termination.
|
|
||||||
|
|
||||||
Match the complete flag name. Length precedence does not apply: `--out` and
|
|
||||||
`--output` are different names, and only `--out` participates in alias lookup in
|
|
||||||
`--out=value`. Use the scope precedence selected above. Resolution must
|
|
||||||
be deterministic and must not depend on registration order.
|
|
||||||
|
|
||||||
### Canonical flag collisions
|
|
||||||
|
|
||||||
An alias cannot conflict with or overload an applicable canonical flag spelling.
|
|
||||||
Reject conflicts during installation as invalid application configuration.
|
|
||||||
Check a command-scoped alias against that command's canonical flags, and an
|
|
||||||
application-wide alias across the commands where it applies. Apply the same
|
|
||||||
checks when later registration adds canonical declarations. Failed batches
|
|
||||||
preserve existing commands and alias mappings.
|
|
||||||
|
|
||||||
### Canonical binding behavior
|
|
||||||
|
|
||||||
An alias feeds the same typed binding as its canonical flag. The target retains
|
|
||||||
its value conversion, defaults, required-value checks, presence tracking,
|
|
||||||
repetition rules, and behavior. Mixed spellings retain invocation order:
|
|
||||||
|
|
||||||
```text
|
|
||||||
foo --color red --colour blue
|
|
||||||
```
|
|
||||||
|
|
||||||
With `--colour` mapped to singleton `--color`, the normal last-occurrence rule
|
|
||||||
selects `blue`. Earlier invalid occurrences remain errors under the existing
|
|
||||||
conversion contract. For a repeatable target, occurrences through either
|
|
||||||
spelling accumulate in order. Alias resolution adds no second conversion or
|
|
||||||
input-preparation lifecycle.
|
|
||||||
|
|
||||||
Flag aliases do not change canonical flag ownership or add new provider
|
|
||||||
capabilities.
|
|
||||||
|
|
||||||
### Chains and short spellings
|
|
||||||
|
|
||||||
Support flag-alias chains, such as `--colour → --hue → --color`. When resolving
|
|
||||||
a target, an existing canonical flag spelling terminates the chain. Otherwise,
|
|
||||||
look up the next alias using the selected context's effective mappings, with
|
|
||||||
command-scoped mappings taking precedence over application-wide mappings.
|
|
||||||
Resolve to the final canonical flag and use its binding. Validate applicable
|
|
||||||
alias-source collisions separately; a canonical endpoint does not excuse a
|
|
||||||
conflicting source declaration.
|
|
||||||
|
|
||||||
For example, given canonical `--color` and global mappings
|
|
||||||
`--color → --missing` and `--colour → --color`, the first mapping contributes
|
|
||||||
nothing while `--missing` is unavailable. The second still reaches canonical
|
|
||||||
`--color`. If later registration makes `--missing` available in that context,
|
|
||||||
the first mapping becomes a canonical spelling collision and the batch fails.
|
|
||||||
|
|
||||||
Apply target-availability rules to the final destination. An application-wide
|
|
||||||
chain contributes nothing where its final canonical flag is unavailable. A
|
|
||||||
command-scoped declaration must resolve to an available canonical flag. Reject
|
|
||||||
cycles during installation, identify the participating spellings in diagnostics,
|
|
||||||
and revalidate composition after later registration.
|
|
||||||
|
|
||||||
Support individual short alias spellings, such as `-c → --color`, alongside
|
|
||||||
long aliases. Canonical short spellings and aliases use the same cluster and
|
|
||||||
attached-value grammar and may mix freely within a cluster. Resolve each alias
|
|
||||||
to its final canonical flag before determining whether it consumes a value.
|
|
||||||
|
|
||||||
Process short spellings left to right. Boolean flags use presence as true;
|
|
||||||
explicit boolean values require `=`. The first value-taking flag consumes the
|
|
||||||
remaining suffix, removing a separating `=` when present, or consumes the next
|
|
||||||
argument if there is no suffix. Consumed values are never searched for aliases.
|
|
||||||
Unknown spellings within a cluster produce a usage error. Preserve occurrence
|
|
||||||
order for repeatable bindings and singleton last-occurrence behavior.
|
|
||||||
|
|
||||||
With boolean aliases `-v → --verbose` and `-q → --quiet`, and value-taking
|
|
||||||
`-c → --color`:
|
|
||||||
|
|
||||||
| Input | Interpretation |
|
|
||||||
| --- | --- |
|
|
||||||
| `-vq` | `--verbose --quiet` |
|
|
||||||
| `-c blue`, `-c=blue`, or `-cblue` | `--color=blue` |
|
|
||||||
| `-vqcblue` or `-vqc blue` | `--verbose --quiet --color=blue` |
|
|
||||||
| `-cvq` | `--color=vq` |
|
|
||||||
| `-v=false` | `--verbose=false` |
|
|
||||||
| `-qv=false` | `--quiet --verbose=false` |
|
|
||||||
|
|
||||||
`-vfalse` is a cluster beginning with `-v`, not an explicit false value.
|
|
||||||
A spelling such as `-color` follows short-option parsing; long aliases use
|
|
||||||
the `--` prefix. Options still follow the complete command path, and `--`
|
|
||||||
ends option parsing.
|
|
||||||
|
|
||||||
Explicit empty-value handling was corrected for both canonical short spellings
|
|
||||||
and aliases: `-c=` supplies an empty string, consistently with `--color=` and
|
|
||||||
`-c ""`. The preimplementation backend passed the literal string `"="` for `-c=`;
|
|
||||||
the delivered implementation corrects that behavior. Likewise, `-v=` supplies an
|
|
||||||
empty value to boolean conversion and fails conversion. This correction preserves the
|
|
||||||
distinction between an omitted value and an explicitly supplied empty value.
|
|
||||||
|
|
||||||
### Flag help and diagnostics
|
|
||||||
|
|
||||||
Present aliases alongside their canonical flags in help. Show only mappings
|
|
||||||
effective in the current scope, resolve chains to their final targets, and
|
|
||||||
document each canonical input once. For example:
|
|
||||||
|
|
||||||
```text
|
|
||||||
--color VALUE
|
|
||||||
Output color.
|
|
||||||
Aliases: --colour, -c
|
|
||||||
```
|
|
||||||
|
|
||||||
When identifying an invalid occurrence in diagnostics, retain the spelling
|
|
||||||
the operator supplied and identify the canonical flag where helpful. Conversion,
|
|
||||||
required-value checks, and repetition behavior continue to come from the
|
|
||||||
canonical binding.
|
|
||||||
|
|
||||||
## Future shell completion
|
|
||||||
|
|
||||||
The direction for future shell completion is canonical suggestions with
|
|
||||||
alias-aware interpretation. Suggest canonical command and flag names rather
|
|
||||||
than enumerating aliases. Resolve aliases the operator has already entered so
|
|
||||||
completion can continue using the target's command structure and input metadata.
|
|
||||||
|
|
||||||
For example, `app <TAB>` suggests canonical commands. With `pk → promptkit`,
|
|
||||||
`app pk <TAB>` can suggest canonical children available through that route.
|
|
||||||
After a complete command alias, use the target's flags and operands as the
|
|
||||||
basis for completion. Recognize manually entered flag aliases when identifying
|
|
||||||
the canonical binding whose value is being completed. Suggestions beneath a
|
|
||||||
group alias must account for more-specific mappings so their interpretation
|
|
||||||
agrees with execution routing.
|
|
||||||
|
|
||||||
Keep validated canonical metadata and alias relationships available internally
|
|
||||||
for metadata-only lookup independently of execution and help rendering. Future
|
|
||||||
completion can reuse those records and shared path operations without parsing
|
|
||||||
rendered help or invoking application input factories and acquisition callbacks
|
|
||||||
just to discover command and flag names. This does not select a lifecycle or
|
|
||||||
provider API for future dynamic operand or value suggestions.
|
|
||||||
|
|
||||||
Completion requests contain partial tokens and cursor context. A future
|
|
||||||
completion lookup must accommodate incomplete input without relaxing exact
|
|
||||||
matching for execution or requiring partial input to pass execution validation.
|
|
||||||
Preserve the distinction between structured paths and supplied argument tokens;
|
|
||||||
shell-specific tokenization and quoting belong to that future work.
|
|
||||||
|
|
||||||
Shell completion itself is outside this implementation. Do not add completion
|
|
||||||
APIs, shell scripts, partial-input lookup machinery, or completion-specific
|
|
||||||
tests in this delivery. Internal lookup separation supports the current routing
|
|
||||||
and help responsibilities; it does not require a public metadata API or a
|
|
||||||
general completion framework. Shell selection, candidate presentation, and
|
|
||||||
dynamic value completion remain future design work.
|
|
||||||
|
|
||||||
## Delivery and compatibility
|
|
||||||
|
|
||||||
The [completed implementation plan](implementation.md) records the ordered work
|
|
||||||
from the planning baseline, implementation choices, and stage evidence for the
|
|
||||||
selected behavior. The [review remediation](remediation.md) records subsequent
|
|
||||||
findings, corrections, and validation without restarting those stages.
|
|
||||||
The delivered feature includes maintained consumer examples, GoDoc, CLI and
|
|
||||||
consumer guidance, and internal documentation matching the implemented owners.
|
|
||||||
|
|
||||||
Consumer guidance and release notes explain migration from `...Command` to
|
|
||||||
`...Declaration`, including slice conversion, and the explicit short-option
|
|
||||||
empty-value correction under the
|
|
||||||
[release policy](../policy/release.md#versioning-and-compatibility). Nil and zero
|
|
||||||
declaration handling is documented in the
|
|
||||||
[Go declarations and GoDoc](../../command.go) alongside the invalid-zero and
|
|
||||||
explicit-absence command contracts.
|
|
||||||
|
|
||||||
The delivery goal was to let consumers declare alternate command paths
|
|
||||||
and flag spellings with minimal wiring and invoke canonical behavior and help
|
|
||||||
through them while canonical ownership and binding semantics stay intact. Installation
|
|
||||||
rejects conflicts with canonical commands and applicable flags in either
|
|
||||||
registration order.
|
|
||||||
@@ -1,847 +0,0 @@
|
|||||||
# Application-owned aliases implementation plan
|
|
||||||
|
|
||||||
Status: complete; Stages 1–17 completed.
|
|
||||||
|
|
||||||
## Authority, baseline, and scope
|
|
||||||
|
|
||||||
Implement [Application-owned aliases](aliases.md), governed by
|
|
||||||
[ADR 0013](../adr/0013-application-alias-routing.md),
|
|
||||||
[ADR 0011](../adr/0011-captured-declarations-and-installation.md), and the
|
|
||||||
[architecture policy](../policy/architecture.md). The feature roadmap owns the
|
|
||||||
selected behavior; this document owns the work sequence and implementation
|
|
||||||
choices. Follow the [agent](../policy/agents.md),
|
|
||||||
[testing](../policy/testing.md), and [documentation](../policy/documentation.md)
|
|
||||||
policies. Read [the developer guide](../development.md) first.
|
|
||||||
|
|
||||||
The inspected baseline is commit `f3b8a129d99d04230f998d0327ffad05f6002d7a`.
|
|
||||||
Core v0.2.0, ckconfig v0.1.0, and ckprompt v0.1.0 have been published.
|
|
||||||
`New` and `Register` currently accept `...Command`; there are no routing-rule
|
|
||||||
declarations. `Invocation` currently contains context and streams only.
|
|
||||||
The Cobra adapter selects canonical commands, parses their flags, and renders
|
|
||||||
help. Core owns typed conversion, input construction, dispatch, and outcomes.
|
|
||||||
|
|
||||||
This sprint delivers command and flag alias declarations, joint installation,
|
|
||||||
resolution, invocation identity, help, diagnostics, examples, and documentation.
|
|
||||||
It includes the selected canonical short-option empty-value correction.
|
|
||||||
It does not implement operand synonyms, preset arguments, shell completion,
|
|
||||||
new upstream operations, a replacement backend, or release publication.
|
|
||||||
|
|
||||||
## How to execute the plan
|
|
||||||
|
|
||||||
- Perform Stage 1 through Stage 17 in order. Each stage is sized as a separate
|
|
||||||
Luna implementation prompt. Add its completion evidence here and commit each
|
|
||||||
completed nonempty unit under the agent policy.
|
|
||||||
- Inspect the current tree before editing; preserve unrelated work. Prefer the
|
|
||||||
code knowledge graph for code discovery, falling back when it is insufficient.
|
|
||||||
- Reuse current behavior and tests where they express accepted contracts.
|
|
||||||
Replace mechanics when needed; do not add compatibility wrappers around the
|
|
||||||
old installation signatures or a second application parsing lifecycle.
|
|
||||||
- Stages include the focused tests needed for their work. Run those during
|
|
||||||
implementation, not during this planning pass. Do not make later stages
|
|
||||||
depend on unverified termination or token-interpretation assumptions.
|
|
||||||
- Keep tests about CommandKit adaptation, presentation, and lifetimes. Upstream
|
|
||||||
libraries own their domain tests. Use local callbacks and fixtures; no live
|
|
||||||
providers or credentials are needed.
|
|
||||||
- Preserve eager declaration capture, reusable declarations, namespace ownership,
|
|
||||||
binding identity, presence, wrapped causes, and existing outcome delivery.
|
|
||||||
Do not add concurrent-dispatch, arbitrary deep-copy, performance, or public
|
|
||||||
ordering guarantees.
|
|
||||||
- New private records and helpers described below are implementation choices.
|
|
||||||
Their names and exact organization can change without altering public behavior.
|
|
||||||
Do not expose them through the facade or add backend selection APIs.
|
|
||||||
- Keep published release records unchanged. Local source verification does not
|
|
||||||
authorize creating tags, pushing, or publishing another release.
|
|
||||||
|
|
||||||
## Implementation decisions used by the stages
|
|
||||||
|
|
||||||
### Owners and data flow
|
|
||||||
|
|
||||||
| Owner | Work |
|
|
||||||
| --- | --- |
|
|
||||||
| Root `commandkit` package | Public declarations, retained errors, candidate installation, alias records, routing coordination, invocation identity, typed conversion, and outcome presentation. |
|
|
||||||
| New `internal/commandpath` package | Shared path representation and token/path operations used by core, neutral metadata, and the adapter. It has no backend or optional-library imports. |
|
|
||||||
| New `internal/alias` package | Private command-prefix lookup and termination analysis over paths; no handlers, application factories, or backend types. Keep its model limited to the selected routing rules. |
|
|
||||||
| `internal/commandmeta` | Neutral canonical metadata and the routing, spelling-provenance, and help-view records actually needed across the adapter boundary. |
|
|
||||||
| `internal/cobra` | Canonical backend sessions, alias-aware flag interpretation, and rendering selected help views without installing alias command nodes. |
|
|
||||||
| Optional integrations | Continue returning canonical `Command` declarations and owning their providers. Only source migrations, focused composition evidence, and maintained consumer changes are needed here. |
|
|
||||||
|
|
||||||
Core retains canonical commands and routing rules separately. A candidate
|
|
||||||
installation compiles relationships against the complete prospective registry,
|
|
||||||
then publishes them together. Derived lookup metadata is reusable within an App;
|
|
||||||
parse state and entered-route provenance remain invocation-local.
|
|
||||||
|
|
||||||
Use the same private route lookup for execution, explicit help-target lookup,
|
|
||||||
and discovery-help views. It returns a canonical command identity or a distinct
|
|
||||||
alias-prefix discovery context, plus entered/canonical paths and remaining
|
|
||||||
arguments. Keep lookup independent of execution and rendering. This is current
|
|
||||||
routing/help machinery, not a completion API.
|
|
||||||
|
|
||||||
### Public declarations and invalid values
|
|
||||||
|
|
||||||
Implement the roadmap's signatures:
|
|
||||||
|
|
||||||
```go
|
|
||||||
type Declaration interface { commandkitDeclaration() }
|
|
||||||
|
|
||||||
func New(identity Identity, declarations ...Declaration) (*App, error)
|
|
||||||
func (a *App) Register(declarations ...Declaration) error
|
|
||||||
|
|
||||||
func Alias(path, target string) RoutingRule
|
|
||||||
func FlagAlias(spelling, target string) RoutingRule
|
|
||||||
func FlagAliasFor(commandPath, spelling, target string) RoutingRule
|
|
||||||
|
|
||||||
func (inv Invocation) EnteredPath() string
|
|
||||||
func (inv Invocation) CanonicalPath() string
|
|
||||||
```
|
|
||||||
|
|
||||||
`Command` and opaque `RoutingRule` implement the private marker. Their factories
|
|
||||||
capture values and retain errors; alias factories do not return errors or run
|
|
||||||
callbacks. Keep `Group`, `RootGroup`, and `CommandSpec.Children` command-only.
|
|
||||||
`WithError` and `NoCommand` keep their current command contracts; do not add an
|
|
||||||
absence rule or a general extension/plugin declaration kind.
|
|
||||||
|
|
||||||
A nil declaration, invalid zero `Command`, and zero `RoutingRule` are
|
|
||||||
installation errors, not no-ops. Handle nil pointers without panics; normalize
|
|
||||||
non-nil pointers to the supplied opaque declaration types to their values.
|
|
||||||
Dispatch only the supported CommandKit declaration kinds, without reflection or
|
|
||||||
calling application-defined assembly callbacks. `NoCommand` remains the explicit
|
|
||||||
absence case, with retained errors checked before it is skipped.
|
|
||||||
|
|
||||||
An identical normalized routing rule can be contributed repeatedly. It is
|
|
||||||
idempotent, including across calls to `Register`. Do not extend that exception
|
|
||||||
to duplicate canonical command declarations. Identity uses declared kind,
|
|
||||||
source, target, and scope, not merely the final resolved endpoint: different
|
|
||||||
declared targets remain competing mappings even if they reach the same command
|
|
||||||
or binding. Invalid later registration leaves both registries and derived
|
|
||||||
metadata intact.
|
|
||||||
|
|
||||||
Store invocation paths privately as normalized strings, populated by dispatch.
|
|
||||||
Accessors on an otherwise caller-created zero invocation return empty strings.
|
|
||||||
The original context and stream fields remain usable in keyed literals.
|
|
||||||
|
|
||||||
### Paths and provenance
|
|
||||||
|
|
||||||
Parse declaration paths on whitespace once at capture. Reuse canonical
|
|
||||||
one-token name validation; do not introduce a stricter name alphabet. Path
|
|
||||||
rendering, prefix comparison, normalized keys, and exact backend lookup use
|
|
||||||
shared helpers. Never split or trim already-tokenized argv elements.
|
|
||||||
|
|
||||||
Route tokens retain their association with the original argv prefix as aliases
|
|
||||||
replace command-path components. This is needed to identify the entered path
|
|
||||||
without guessing from the length of the final canonical path. For
|
|
||||||
`smoke all` with `smoke → promptkit test`, the entered command path is `smoke`,
|
|
||||||
the canonical path is `promptkit test`, and `all` is still an operand.
|
|
||||||
For `pk list bundles`, both original `list` and `bundles` belong to the entered
|
|
||||||
path when its resolved command is `promptkit list collections`.
|
|
||||||
|
|
||||||
Only the leading command portion participates in command rewriting. A flag or
|
|
||||||
`--` stops command-path lookup. Canonical command structure and operand metadata
|
|
||||||
establish where trailing non-option tokens become operands. Longest explicit
|
|
||||||
rules beneath an alternate spelling still take precedence as selected in the
|
|
||||||
roadmap; do not reserve all operand space beneath an alternate spelling.
|
|
||||||
|
|
||||||
### Exact termination analysis
|
|
||||||
|
|
||||||
Use a finite pushdown analysis of the deterministic longest-prefix rewriter.
|
|
||||||
This is private installation machinery. It avoids rejecting valid consuming
|
|
||||||
repetitions or accepting a growing loop that never repeats an entire path.
|
|
||||||
Keep it isolated so its correctness can be established before dispatch uses it.
|
|
||||||
|
|
||||||
The implementation has two parts, split across Stages 2 and 3:
|
|
||||||
|
|
||||||
1. Compile a prefix trie into a finite-state stack machine. The top of the
|
|
||||||
stack is the beginning of the unresolved path. Lookup remembers the deepest
|
|
||||||
matching rule, inspects only the finite source-prefix length, and restores
|
|
||||||
any inspected suffix when replacing that source with its target. A failed
|
|
||||||
longer match selects the saved shorter match; it does not invent a route.
|
|
||||||
No match halts rewriting. End-of-path and the boundary before flags are
|
|
||||||
terminal markers, never command components that a rule can consume.
|
|
||||||
2. The finite stack alphabet contains literal tokens used by rules, an `OTHER`
|
|
||||||
equivalence class for tokens not used by any rule, and an end marker.
|
|
||||||
Preserve original arbitrary tokens in the runtime resolver; this quotient
|
|
||||||
is only for proving termination. All alias sources are nonempty.
|
|
||||||
3. Normalize transitions to `(p,A) → (q,w)` with `w` of length zero, one, or two,
|
|
||||||
using finite helper states for longer pushes. Remember which original rules
|
|
||||||
participate so an error can identify mappings. The compiler's lookup and
|
|
||||||
restoration phases must be acyclic; only completing a rule can return to
|
|
||||||
the lookup start. The bottom/end marker is never popped or duplicated.
|
|
||||||
4. Compute the finite least fixed point `Pop(p,A,q)`: starting in control `p`
|
|
||||||
with top `A`, the machine can remove that symbol and finish in `q` without
|
|
||||||
inspecting the stack below it. Seed pop transitions. A one-symbol push uses
|
|
||||||
one existing pop summary; a two-symbol push composes two summaries in
|
|
||||||
left-to-right order. Retain witness information, not copies of arbitrary
|
|
||||||
stack contents.
|
|
||||||
5. Build a graph of heads `(control, top-symbol)`. A transition pushing `B`
|
|
||||||
gives an edge to `(q,B)`. One pushing `BC` gives an edge to `(q,B)` and,
|
|
||||||
for every `Pop(q,B,r)`, to `(r,C)`. A pop transition alone gives no edge.
|
|
||||||
These edges summarize nonempty paths that never pop below their starting
|
|
||||||
stack level. A directed cycle, including a self-edge, witnesses a repeatable
|
|
||||||
computation and hence nontermination.
|
|
||||||
6. Check the model's scope explicitly: installation is checking all finite
|
|
||||||
command-token suffixes, not just each bare source or target. For this
|
|
||||||
compiler, helper phases cannot run forever without returning to the lookup
|
|
||||||
start, and every finite token stack at that start is a possible input.
|
|
||||||
Therefore a repeatable computation must correspond to a possible alias
|
|
||||||
invocation; do not reject an abstract cycle introduced only by an invalid
|
|
||||||
end-marker configuration. Restrict marker transitions accordingly and
|
|
||||||
record this reasoning with the implementation tests.
|
|
||||||
|
|
||||||
For the fixed-point step, a rule `(p,A) → (r,BC)` adds `Pop(p,A,q)` only when
|
|
||||||
both `Pop(r,B,s)` and `Pop(s,C,q)` hold for some `s`. This distinction matters:
|
|
||||||
the head-graph edge to `(s,C)` requires only the first summary and represents
|
|
||||||
continuing at `C`, rather than having removed it.
|
|
||||||
|
|
||||||
Do not substitute an ordinary graph of alias declarations, a decreasing-length
|
|
||||||
rule, a maximum chain length, a fixed suffix-enumeration depth, or a timeout
|
|
||||||
for this analysis. Use a straightforward finite fixed point and cycle detector;
|
|
||||||
no external model-checker dependency or public automaton abstraction is needed.
|
|
||||||
Bounded examples are regression evidence, not the proof of universal termination.
|
|
||||||
If implementation exposes a flaw in the compiler or analysis, correct that
|
|
||||||
isolated stage before proceeding; do not weaken the selected alias contract.
|
|
||||||
|
|
||||||
After termination succeeds, resolve each declared target through the same
|
|
||||||
longest-prefix semantics and require an exact canonical command/group endpoint,
|
|
||||||
with no injected operand tokens. Validate literal canonical reachability using
|
|
||||||
the complete candidate command tree and its argument bounds, without invoking
|
|
||||||
value parsers or application checks. Follow canonical child selection before
|
|
||||||
treating unmatched tokens as operands. Do not reject a route solely because a
|
|
||||||
runnable ancestor exists: it must actually intercept that command's declared
|
|
||||||
operand space or a canonical route.
|
|
||||||
|
|
||||||
### Flag resolution and parsing
|
|
||||||
|
|
||||||
Normalize a flag declaration into a long or individual one-byte short spelling,
|
|
||||||
without a value. Reuse the existing canonical spelling rules, allowing built-in
|
|
||||||
help as a destination. Do not interpret clusters or attached values in a rule
|
|
||||||
declaration. A command-scoped path must be an exact canonical path, not an alias
|
|
||||||
or an operand-bearing invocation.
|
|
||||||
|
|
||||||
For each canonical command/group and the application root, form effective
|
|
||||||
mappings from application-wide rules plus command-local overrides. Include
|
|
||||||
canonical `--help` and `-h`. Resolve chains with canonical spellings as endpoints,
|
|
||||||
apply availability to the final endpoint, and validate active source collisions
|
|
||||||
separately. Application-wide missing destinations stay inactive; explicit scoped
|
|
||||||
missing destinations are errors. Detect mapping cycles, including in reusable
|
|
||||||
global chains, and recompute relationships when registration changes the context.
|
|
||||||
Discovery-help contexts have core help flags and global rules only.
|
|
||||||
|
|
||||||
Keep the flag-name/value interpretation in the internal adapter. Use one
|
|
||||||
metadata-driven token pass for canonical and alias spellings, including mixed
|
|
||||||
short clusters. Normalize reached spellings to canonical backend flags, retain
|
|
||||||
their original occurrence spellings, and pass values/operands unchanged.
|
|
||||||
Cobra/pflag remain the backend; this pass adapts the selected token grammar and
|
|
||||||
does not convert typed application values. Do not independently scan or rewrite
|
|
||||||
tokens in core as a second flag parser.
|
|
||||||
|
|
||||||
Once a value-taking flag consumes an attached suffix or the next token, neither
|
|
||||||
that value nor anything following `--` is searched for aliases. Explicit
|
|
||||||
boolean values require `=`; a bare boolean contributes `true`. Normalize
|
|
||||||
`-c=` as an explicitly empty value, and `-v=` as an empty value for boolean
|
|
||||||
conversion, including when these are canonical short spellings. Keep occurrence
|
|
||||||
order within each canonical binding and raw values available for the existing
|
|
||||||
typed converter; do not add a cross-binding converter-order guarantee.
|
|
||||||
|
|
||||||
Retain private per-occurrence spelling provenance through conversion. An
|
|
||||||
internal conversion error can carry a canonical binding/occurrence index and
|
|
||||||
wrap the original cause so presentation can identify the entered spelling.
|
|
||||||
Do not rerun converters or stringify and replace their errors. Preserve
|
|
||||||
`CaptureFlags`/`FlagValues` binding identity and application-input semantics.
|
|
||||||
|
|
||||||
## Stage 1: Introduce shared command-path primitives
|
|
||||||
|
|
||||||
**Work**
|
|
||||||
|
|
||||||
1. Add `internal/commandpath` with capture parsing, component validation,
|
|
||||||
equality/prefix operations, normalized keys, formatting, and owned token copies
|
|
||||||
at capture boundaries. Distinguish a root lookup path from a declaration
|
|
||||||
path: root lookup is valid; an empty alias declaration path is invalid.
|
|
||||||
2. Move or delegate the existing command-name check to the shared validator.
|
|
||||||
Migrate canonical bridge paths, exact help lookup, and core path formatting
|
|
||||||
where they currently join/split the same paths repeatedly.
|
|
||||||
3. Keep argv as tokens throughout. Do not change canonical routing, public API,
|
|
||||||
command names, or name restrictions in this refactor.
|
|
||||||
|
|
||||||
**Evidence:** focused path tests for whitespace-normalized declarations,
|
|
||||||
literal quotes/backslashes, invalid option components, empty declarations,
|
|
||||||
root lookup, and a single argv token containing whitespace. Existing routing
|
|
||||||
and help tests remain green.
|
|
||||||
|
|
||||||
**Completed:** Added shared command-path parsing, validation, relations, keys,
|
|
||||||
formatting, and token-copy helpers. Core command validation and path diagnostics,
|
|
||||||
plus adapter route comparison and exact help lookup, now use the shared package.
|
|
||||||
Verified with `go test ./internal/commandpath ./internal/cobra .`.
|
|
||||||
|
|
||||||
## Stage 2: Model deterministic prefix rewriting
|
|
||||||
|
|
||||||
**Work**
|
|
||||||
|
|
||||||
1. Add private normalized command-rule records and longest-prefix lookup under
|
|
||||||
`internal/alias`, using Stage 1 paths. A simple trie is sufficient.
|
|
||||||
2. Implement the finite stack-machine compiler described above, including saved
|
|
||||||
shorter matches, mismatch restoration, token equivalence classes, end-marker
|
|
||||||
handling, and normalized short push transitions.
|
|
||||||
3. Add a small test interpreter for the compiled machine and compare finite
|
|
||||||
cases with the direct longest-prefix resolver. Do not expose this interpreter
|
|
||||||
or use a test step bound as the production validity decision.
|
|
||||||
4. Keep compiler phase transitions explicit so lookup/restoration cannot create
|
|
||||||
an internal loop unrelated to completing alias rewrites.
|
|
||||||
|
|
||||||
**Evidence:** chains; overlap chosen by token count rather than character
|
|
||||||
count; target expansion; group suffix preservation; shorter fallback after
|
|
||||||
a failed longer token match; unknown tokens; empty suffixes. The compiler
|
|
||||||
and direct resolver agree on these terminating cases.
|
|
||||||
|
|
||||||
**Completed:** Added the independent longest-prefix resolver and compiled its
|
|
||||||
trie into a finite stack machine with literal and `OTHER` symbols, end and
|
|
||||||
flag-boundary markers, shorter-match fallback, restoration, and normalized
|
|
||||||
pushes. A test-only interpreter matches direct resolution for the recorded
|
|
||||||
finite cases. Verified with `go test ./internal/alias`.
|
|
||||||
|
|
||||||
## Stage 3: Prove and test termination validation
|
|
||||||
|
|
||||||
**Work**
|
|
||||||
|
|
||||||
1. Implement pop-summary saturation, head-graph construction, and cycle
|
|
||||||
detection from the implementation decisions. Return useful participating
|
|
||||||
rule context for a rejection. Document why the abstraction neither misses
|
|
||||||
growing loops nor invents invalid marker loops.
|
|
||||||
2. Cover direct cycles and `a → b extra`, `b → a`, whose paths grow without
|
|
||||||
repeating. Cover a suffix-dependent cycle using `a → b`, `b → group`,
|
|
||||||
`b x → a x`: bare `a` terminates but `a x` does not.
|
|
||||||
3. Accept consuming repetitions: with canonical group `group`, `a → group`
|
|
||||||
and `group again → a` must accept `a again again` and consume both suffix
|
|
||||||
tokens before ending at `group`.
|
|
||||||
4. Cover longest-match suppression of a potential shorter-rule loop: with
|
|
||||||
`a → b x`, `b → a`, `b x → group`, actual resolution terminates. A naive
|
|
||||||
rule-dependency cycle detector would incorrectly reject it.
|
|
||||||
5. Include a valid chain longer than any tempting small fixed hop limit and
|
|
||||||
vary rule registration order. Keep no artificial public alias-count limit.
|
|
||||||
|
|
||||||
**Complete when:** the exact finite analysis is justified and the focused
|
|
||||||
cases distinguish it from conservative declaration-cycle or bounded simulation
|
|
||||||
checks. Do not integrate an approximate validator and defer correctness.
|
|
||||||
|
|
||||||
**Completed:** Added worklist saturation for finite pop summaries, head-graph
|
|
||||||
construction, cycle detection, and errors naming participating mappings.
|
|
||||||
Terminal-marker transitions preserve the unique bottom marker, and tests verify
|
|
||||||
markers cannot be popped. Direct, growing, and suffix-dependent loops are
|
|
||||||
rejected; consuming repetition, longest-match suppression, and 80-rule chains
|
|
||||||
in either registration order are accepted. Verified with
|
|
||||||
`go test ./internal/alias -count=1`.
|
|
||||||
|
|
||||||
## Stage 4: Add captured declaration types and factories
|
|
||||||
|
|
||||||
**Work**
|
|
||||||
|
|
||||||
1. Add `Declaration`, opaque `RoutingRule`, the three alias factories, and
|
|
||||||
private captured rule records with retained construction errors.
|
|
||||||
2. Capture and normalize command paths and flag spellings immediately. Preserve
|
|
||||||
the existing `Command` capture, `WithError`, and absence behavior.
|
|
||||||
3. Change `New`/`Register` to `...Declaration`, normalizing supported values and
|
|
||||||
pointers at the installation boundary. Keep group children command-only.
|
|
||||||
4. Convert internal `[]Command` expansions used for installation into explicit
|
|
||||||
declaration slices where necessary, including built-in assembly and affected
|
|
||||||
consumers/tests. Do not add a bundle API or generalize `Group`.
|
|
||||||
|
|
||||||
**Evidence:** a core-only public consumer can capture mixed declarations;
|
|
||||||
invalid paths/spellings are reported at installation; nil and zero declarations
|
|
||||||
are handled as selected; canonical command-only calls continue to work. No
|
|
||||||
factories, loaders, or handlers run during capture.
|
|
||||||
|
|
||||||
**Completed:** Added the opaque `Declaration` and `RoutingRule` types, command
|
|
||||||
and flag alias factories, eager normalized capture with retained issues, and
|
|
||||||
value/pointer normalization at `New` and `Register`. Built-in and consumer
|
|
||||||
installation slices now use declarations explicitly. Verified with root and
|
|
||||||
both integration module suites under the local workspace.
|
|
||||||
|
|
||||||
## Stage 5: Install canonical commands and command aliases atomically
|
|
||||||
|
|
||||||
**Work**
|
|
||||||
|
|
||||||
1. Replace the current root-command-only pending map with a candidate containing
|
|
||||||
existing/new canonical commands and separate normalized routing records.
|
|
||||||
Reuse existing canonical placement and namespace checks.
|
|
||||||
2. Validate retained errors, exact canonical-source collisions, competing rule
|
|
||||||
mappings, prefix termination, exact resolved targets, and canonical operand
|
|
||||||
interception before publishing the candidate. Same-batch target order is
|
|
||||||
irrelevant. Missing targets and operand-bearing destinations are errors.
|
|
||||||
3. Accept identical normalized mappings, including repeated contributions across
|
|
||||||
registration calls. Revalidate existing aliases when a new canonical batch
|
|
||||||
changes reachability. Invalidate derived snapshots only on accepted changes.
|
|
||||||
4. Preserve old registry/help behavior after every failed batch. Aliases inside
|
|
||||||
an installed standard-family spelling remain routing records and never
|
|
||||||
bypass canonical root-only placement or merge command trees.
|
|
||||||
|
|
||||||
**Evidence:** both registration orders; retained wrapped errors; duplicates;
|
|
||||||
missing/forward targets; existing and same-batch collisions; canonical children
|
|
||||||
versus runnable operand space; valid longer aliases beneath `r → run`; failed
|
|
||||||
registration after a snapshot was used. Explicitly reject
|
|
||||||
`promptkit test full → promptkit test all` under a `test KIND` fixture.
|
|
||||||
|
|
||||||
**Completed:** Replaced direct registry mutation with a candidate that validates
|
|
||||||
the complete canonical tree and normalized routing rules before publishing.
|
|
||||||
Alias chains and termination, missing or operand-bearing targets, canonical
|
|
||||||
source and operand collisions, duplicate idempotence, later command conflicts,
|
|
||||||
and failed-batch preservation are covered. Verified with
|
|
||||||
`go test ./... -count=1`.
|
|
||||||
|
|
||||||
## Stage 6: Compile effective flag aliases during installation
|
|
||||||
|
|
||||||
**Work**
|
|
||||||
|
|
||||||
1. Extend the candidate with global and canonical-command-scoped flag rules.
|
|
||||||
Build effective mappings from neutral canonical flag metadata and core help
|
|
||||||
spellings, without preparing application inputs.
|
|
||||||
2. Resolve chains, apply scoped precedence, check final availability and active
|
|
||||||
canonical-source collisions, and reject cycles. Handle long-to-short,
|
|
||||||
short-to-long, and canonical short endpoints consistently.
|
|
||||||
3. Accept globals whose destinations are currently absent. Recompute all
|
|
||||||
affected contexts when later commands arrive; reject the whole batch if a
|
|
||||||
newly active global now overloads a canonical spelling.
|
|
||||||
4. Add the root and group contexts; support the restricted help context for
|
|
||||||
alias-only prefixes. Keep command-scoped aliases local to their canonical
|
|
||||||
command rather than implicitly inheriting through descendants.
|
|
||||||
|
|
||||||
**Evidence:** different-target duplicates versus identical duplicates; explicit
|
|
||||||
unknown scopes; inactive globals; scoped overrides inside a chain; cycles;
|
|
||||||
`--colour → --color` terminating at canonical `--color` even with an inactive
|
|
||||||
global `--color → --missing`; collision after `--missing` becomes available;
|
|
||||||
root/group help targets and failed-batch preservation.
|
|
||||||
|
|
||||||
**Completed:** Installation candidates now compile effective global and
|
|
||||||
canonical-command-scoped flag aliases from captured canonical metadata and
|
|
||||||
built-in help spellings. Chain resolution applies scope precedence, tracks
|
|
||||||
inactive global destinations, detects cycles, and rejects newly active
|
|
||||||
canonical-source collisions without publishing failed candidates. Root, group,
|
|
||||||
command, and alias-prefix discovery contexts retain only their applicable
|
|
||||||
spellings. Verified with root and both integration module suites using the
|
|
||||||
local workspace.
|
|
||||||
|
|
||||||
## Stage 7: Resolve entered routes to canonical commands
|
|
||||||
|
|
||||||
**Work**
|
|
||||||
|
|
||||||
1. Add alias lookup records to the App snapshot without adding alias nodes or
|
|
||||||
runners to the canonical command tree. Reuse the validated longest-prefix
|
|
||||||
semantics and Stage 1 paths.
|
|
||||||
2. Implement command/group rewriting with token provenance, remaining argv,
|
|
||||||
canonical selection, and a distinct discovery-prefix result. Stop path
|
|
||||||
matching at flag/terminator boundaries and canonical operands.
|
|
||||||
3. Retain the original entered endpoint and final canonical endpoint, not
|
|
||||||
intermediate chain names. Do not use the final path length to slice original
|
|
||||||
argv. Unknown paths retain the entered route without a fabricated target.
|
|
||||||
4. Ensure a failed longer explicit mapping never retries a shorter mapping.
|
|
||||||
Centralize this lookup for execution and help consumers in later stages.
|
|
||||||
|
|
||||||
**Evidence:** `collections → list collections → promptkit list collections`;
|
|
||||||
`pk → promptkit` composed with `promptkit list bundles`; longest explicit
|
|
||||||
`pk list bundles` override; `smoke all` retaining its operand; `r full` choosing
|
|
||||||
an explicit longer route while canonical `run full` remains unchanged;
|
|
||||||
flags/values/space-containing argv tokens never becoming command components.
|
|
||||||
|
|
||||||
**Completed:** Routing snapshots now retain canonical path metadata and the
|
|
||||||
separate command-alias resolver. Execution resolves command prefixes before
|
|
||||||
parsing, tracks the original input-token origins through alias chains, and
|
|
||||||
preserves the remaining argv. Canonical operands, flags, terminators, unknown
|
|
||||||
paths, and alias-only discovery prefixes receive distinct route results.
|
|
||||||
Verified with root and both integration module suites using the local workspace.
|
|
||||||
|
|
||||||
## Stage 8: Integrate parser-aware flag aliasing and short grammar
|
|
||||||
|
|
||||||
**Work**
|
|
||||||
|
|
||||||
1. Pass the selected canonical/discovery context's effective spellings to the
|
|
||||||
internal adapter through neutral records. Keep Cobra/pflag imports internal.
|
|
||||||
2. Implement the single alias-aware token interpretation pass described above.
|
|
||||||
Canonical and aliased short flags use the same cluster logic. Preserve raw
|
|
||||||
values, explicit empties, `--`, and interspersed operands.
|
|
||||||
3. Feed canonical backend flags without invoking a typed parser twice. Collect
|
|
||||||
original spelling provenance per occurrence alongside canonical raw values.
|
|
||||||
4. Correct canonical `-c=` and boolean `-v=` at this same boundary; do not patch
|
|
||||||
aliases alone or pre-rewrite every token beginning with a dash in core.
|
|
||||||
|
|
||||||
**Evidence:** every token example in the roadmap's flag sections; mixed
|
|
||||||
canonical/alias clusters; `-cvq` consuming `vq`; `-qv=false`; explicit empty
|
|
||||||
values for long, short, and aliased spellings; missing values; unknown cluster
|
|
||||||
members; `--message --hlep` as a value; `--message=--hlep`; post-`--` operands.
|
|
||||||
|
|
||||||
**Completed:** The routed flag context now reaches the adapter through neutral
|
|
||||||
flag-alias records. One adapter pass interprets canonical and alternate long
|
|
||||||
and short spellings, preserves option values and terminator operands, and feeds
|
|
||||||
only canonical flags to pflag. Raw values retain per-occurrence source
|
|
||||||
spellings. Canonical short empty values now follow the same long-form boundary.
|
|
||||||
Verified with root and both integration module suites using the local workspace.
|
|
||||||
|
|
||||||
## Stage 9: Wire execution and invocation identity
|
|
||||||
|
|
||||||
**Work**
|
|
||||||
|
|
||||||
1. Use the route result to select the existing canonical payload and its input
|
|
||||||
preparation. Populate both Invocation accessors for ordinary and alias
|
|
||||||
invocations, including callbacks reached by private built-in plumbing.
|
|
||||||
2. Replace the current directly constructed Invocation in the typed runner with
|
|
||||||
the coordinated context so metadata reaches handlers without changing their
|
|
||||||
signature. Retain caller context and streams.
|
|
||||||
3. Keep canonical parsing/conversion, required checks, input/state lifetimes,
|
|
||||||
`CaptureFlags`, provider acquisition, and domain outcome classification on
|
|
||||||
their existing paths. No handler delegates to another alias handler.
|
|
||||||
4. Keep failed routing, invalid flags, and help from constructing application
|
|
||||||
input or running acquisition. Preserve the existing distinction that help
|
|
||||||
still converts supplied values but skips execution-required checks.
|
|
||||||
|
|
||||||
**Evidence:** a canonical handler observes equal endpoints directly and distinct
|
|
||||||
endpoints through aliases; operands are absent from both path strings; alias
|
|
||||||
and canonical forms reach the same binding/callback once; repeated calls and
|
|
||||||
declaration reuse do not leak invocation values; zero Invocation accessors
|
|
||||||
are empty. Existing cancellation and domain outcome checks remain green.
|
|
||||||
|
|
||||||
**Completed:** Invocation now retains the entered and canonical route paths
|
|
||||||
alongside the caller's context and streams. Public typed handlers and private
|
|
||||||
callbacks receive the same resolved identity. Tests cover canonical and alias
|
|
||||||
calls with operands, repeated calls, declaration reuse across Apps, private
|
|
||||||
callback plumbing, and zero-value accessors. Verified with the root, ckconfig,
|
|
||||||
and ckprompt suites under the local workspace.
|
|
||||||
|
|
||||||
## Stage 10: Add alias-aware help and discovery views
|
|
||||||
|
|
||||||
**Work**
|
|
||||||
|
|
||||||
1. Route `help COMMAND...` targets through the shared metadata lookup, despite
|
|
||||||
those tokens being operands of the built-in help command. Do not globally
|
|
||||||
rewrite arbitrary operands to obtain this special help-target behavior.
|
|
||||||
Keep the help command's invocation identity separate from its requested
|
|
||||||
view: `help list collections` invokes canonical `help`, while rendering the
|
|
||||||
entered target `list collections` and its resolved canonical command.
|
|
||||||
2. Coordinate `ALIAS --help`, bare canonical groups, and aliases to groups with
|
|
||||||
the same help selection. Render canonical inputs with entered usage paths
|
|
||||||
and a canonical-target annotation when the paths differ.
|
|
||||||
3. List explicit root aliases separately from canonical commands. Group views
|
|
||||||
include relevant aliases separately from children, accounting for more-specific
|
|
||||||
overrides. Do not enumerate every possible composed shortcut or chain hop.
|
|
||||||
4. Implement help for alias-only prefixes without canonical nodes or namespaces.
|
|
||||||
Bare incomplete prefixes are usage failures pointing to help. Global help
|
|
||||||
flag aliases work on these views; descendant flags do not become available.
|
|
||||||
5. Add only effective flag aliases to each canonical input's help, resolving
|
|
||||||
chains to endpoints and describing the canonical input once. Keep lookup
|
|
||||||
records independent of rendering and provider callbacks.
|
|
||||||
|
|
||||||
**Evidence:** root/group/alias/discovery help; `help list collections` and
|
|
||||||
`list collections --hlep`; `help promptkit list` showing `bundles`; group
|
|
||||||
shortcut help with a more-specific destination override; inactive/scoped flag
|
|
||||||
visibility; no input/state factories or providers called. Preserve existing
|
|
||||||
help output-delivery handling.
|
|
||||||
|
|
||||||
**Completed:** Help targets and `--help` routes now use shared command-alias
|
|
||||||
resolution. Canonical help views render entered usage paths with canonical
|
|
||||||
target annotations; root and group views list applicable declared aliases and
|
|
||||||
effective flag aliases. Alias-only prefixes render discovery help through
|
|
||||||
`help PREFIX` or global help spellings, while bare incomplete prefixes return a
|
|
||||||
usage failure pointing to help. Verified help selection, scoped/global
|
|
||||||
visibility, more-specific group overrides, and input/run callback lifetimes
|
|
||||||
with root and both integration module suites under the local workspace.
|
|
||||||
|
|
||||||
## Stage 11: Preserve entered spellings in errors and delivery outcomes
|
|
||||||
|
|
||||||
**Work**
|
|
||||||
|
|
||||||
1. Thread flag occurrence provenance into private conversion-error context.
|
|
||||||
Identify the actual failing occurrence, including an earlier invalid value
|
|
||||||
followed by a valid overwrite. Wrap rather than replace application causes.
|
|
||||||
2. Update usage presentation to use entered command paths, identify a resolved
|
|
||||||
canonical target, and preserve the target's diagnostic content. An unresolved
|
|
||||||
route does not acquire an invented canonical label.
|
|
||||||
3. Use existing usage/operational/domain classifications and diagnostic-delivery
|
|
||||||
ownership. Route aliases must not duplicate already delivered diagnostics.
|
|
||||||
Preserve writer errors, short writes, cause identity, and incomplete reports.
|
|
||||||
4. Check alias-related help/usage presentation against failed and successful
|
|
||||||
registration so a stale snapshot does not mislabel the selected operation.
|
|
||||||
|
|
||||||
**Evidence:** malformed aliased scalar and repeatable occurrences; mixed
|
|
||||||
spellings; wrapped `errors.Is`/`errors.As`; usage paths with canonical annotation;
|
|
||||||
unknown routes and flags; cancellation; output and diagnostic failures. Assert
|
|
||||||
semantic fragments and identities, not entire backend wording snapshots.
|
|
||||||
|
|
||||||
**Completed:** Flag conversion failures now retain the binding, entered
|
|
||||||
spelling, occurrence number, and original wrapped cause. Usage diagnostics use
|
|
||||||
entered alias paths and identify resolved canonical commands; unresolved routes
|
|
||||||
receive no invented canonical label. Successful and failed registration during
|
|
||||||
execution preserve the selected route. Verified with root, ckconfig, and
|
|
||||||
ckprompt suites under the local workspace, including existing cancellation,
|
|
||||||
diagnostic deduplication, writer failure, short-write, and incomplete-report
|
|
||||||
coverage.
|
|
||||||
|
|
||||||
## Stage 12: Verify registration and routing interactions end to end
|
|
||||||
|
|
||||||
**Work**
|
|
||||||
|
|
||||||
1. Extend public external-package tests with command-only and simulated
|
|
||||||
root-only family fixtures. Exercise construction, later registration,
|
|
||||||
retained declaration errors, reuse across Apps, and failed-batch recovery.
|
|
||||||
2. Verify canonical invocations retain their declared operand space in both
|
|
||||||
installation orders, while longer mappings beneath alternate spellings work.
|
|
||||||
Cover optional, required, and repeated operand metadata without calling
|
|
||||||
domain value converters at installation.
|
|
||||||
3. Verify same-batch alias chains and globals see the entire candidate, and
|
|
||||||
later command additions trigger full relationship validation. Check cached
|
|
||||||
lookup/help before and after successful and failed registration.
|
|
||||||
4. Include a core-only consumer proving alias infrastructure needs no optional
|
|
||||||
integration imports. Keep alias records out of the canonical handler tree.
|
|
||||||
|
|
||||||
**Evidence:** run the focused external registration, routing, and help suites.
|
|
||||||
Fill missing cross-boundary cases rather than duplicating the private algorithm
|
|
||||||
test inventory. No concurrent-dispatch contract is introduced.
|
|
||||||
|
|
||||||
**Completed:** External-package tests now exercise command-only and root-group
|
|
||||||
consumers using only the core import. They cover declaration ordering, alias
|
|
||||||
chains and global flags in one installation batch, canonical operand retention,
|
|
||||||
optional/required/repeated operands without installation-time conversion,
|
|
||||||
declaration reuse, retained construction errors, later registration, failed
|
|
||||||
relationship validation, failed-batch recovery, and refreshed help. The root
|
|
||||||
suite passes with `go test ./... -count=1`.
|
|
||||||
|
|
||||||
## Stage 13: Verify typed bindings and integration composition
|
|
||||||
|
|
||||||
**Work**
|
|
||||||
|
|
||||||
1. Cover singleton last-occurrence behavior, conversion of every supplied
|
|
||||||
occurrence, repeatable ordering, explicit false/zero/empty presence, required
|
|
||||||
checks, and fresh invocation state with mixed flag spellings.
|
|
||||||
2. Verify captured selector bindings still reach selected typed integration
|
|
||||||
inputs. Test a command-scoped flag alias reached through a command shortcut,
|
|
||||||
and global help on standard families, without rechecking upstream semantics.
|
|
||||||
3. Add focused ckprompt composition cases for actual installed collection and
|
|
||||||
named-inspection commands, plus the valid `smoke → promptkit test` shortcut.
|
|
||||||
Use local callbacks; smoke tests should assert forwarded kind and returned
|
|
||||||
report/outcome, not perform network requests.
|
|
||||||
4. Reject the invalid smoke operand-synonym mapping against the actual
|
|
||||||
`promptkit test KIND` declaration. Preserve ordinary canonical calls in the
|
|
||||||
same application. Use a small ckconfig alias case for selector forwarding.
|
|
||||||
|
|
||||||
**Evidence:** root binding suites and affected integration suites under the
|
|
||||||
local workspace. Do not claim nested modules' pinned core v0.2.0 graph validates
|
|
||||||
new alias APIs. See Stage 17 for independent local-source graph verification.
|
|
||||||
|
|
||||||
**Completed:** Root binding coverage now verifies every singleton occurrence
|
|
||||||
is converted, the last value wins, repeated values retain order, explicit
|
|
||||||
false/zero/empty values remain present, required selectors are checked, and
|
|
||||||
each invocation receives fresh defaults and input state across canonical and
|
|
||||||
alternate spellings. Integration tests exercise scoped selector aliases on
|
|
||||||
installed PromptKit collection and prompt-inspection commands, the `smoke`
|
|
||||||
shortcut and returned report, failed operand-alias registration with later
|
|
||||||
canonical and shortcut calls, and global help aliases for both standard
|
|
||||||
families. Verified with the root, ckconfig, and ckprompt suites under the local
|
|
||||||
three-module workspace.
|
|
||||||
|
|
||||||
## Stage 14: Update maintained consumer examples
|
|
||||||
|
|
||||||
**Work**
|
|
||||||
|
|
||||||
1. Extend `examples/core` with application command shortcuts, a group shortcut,
|
|
||||||
a global help typo alias, and a scoped flag alias. Demonstrate a mixed
|
|
||||||
`[]Declaration` collection and the two Invocation path accessors with small
|
|
||||||
application-owned behavior.
|
|
||||||
2. Extend the composed ckprompt consumer with
|
|
||||||
`list collections → promptkit list collections`,
|
|
||||||
`promptkit list bundles → promptkit list collections`, and `pk → promptkit`.
|
|
||||||
Add scoped `--fmt → --format` for named prompt inspection and
|
|
||||||
`--hlep → --help` globally. Keep canonical suite loading and domain commands
|
|
||||||
unchanged; install aliases alongside the complete canonical declarations.
|
|
||||||
3. Add the valid smoke command-path shortcut if useful for the existing local
|
|
||||||
smoke fixture. Do not represent `all` as a child command or alias target.
|
|
||||||
4. Update example tests to show aliases reaching canonical operations, help
|
|
||||||
without acquisition, and ordinary canonical commands still working. Keep
|
|
||||||
outputs local and deterministic.
|
|
||||||
|
|
||||||
**Evidence:** root and composed-example tests pass against the new local core;
|
|
||||||
the examples remain complete, copyable artifacts. Explain local source testing
|
|
||||||
and forthcoming core dependency adoption in their developer-facing guidance;
|
|
||||||
do not claim published core v0.2.0 has alias support.
|
|
||||||
|
|
||||||
**Completed:** The core example now installs command and group shortcuts,
|
|
||||||
global and scoped flag aliases in a mixed declaration slice, and prints entered
|
|
||||||
and canonical invocation paths. The composed example installs collection,
|
|
||||||
PromptKit group, bundle, smoke, scoped format, and global help aliases alongside
|
|
||||||
its complete canonical declarations. Example tests cover shortcut and
|
|
||||||
canonical operations, help with zero PromptKit engine loads, and local smoke
|
|
||||||
report delivery. Both example READMEs explain local-source use and that
|
|
||||||
published core v0.2.0 lacks alias support. Verified with `go test ./... -count=1`
|
|
||||||
at the root and the complete ckprompt module suite under the local workspace;
|
|
||||||
all newly documented alias commands also ran successfully.
|
|
||||||
|
|
||||||
## Stage 15: Reconcile public and internal documentation
|
|
||||||
|
|
||||||
**Work**
|
|
||||||
|
|
||||||
1. Add GoDoc for `Declaration`, `RoutingRule`, factories, installation changes,
|
|
||||||
and Invocation accessors. Explain eager capture, factory errors retained for
|
|
||||||
installation, nil/zero handling, duplicate rules, and canonical scope paths.
|
|
||||||
2. Update `docs/cli.md` with implemented alias routing, command/operand
|
|
||||||
boundaries, flag scope/availability, short grammar and empty-value correction,
|
|
||||||
entered-path diagnostics, and help/discovery behavior. Preserve canonical
|
|
||||||
upstream command and report contracts.
|
|
||||||
3. Update the consumer guide and example READMEs for `[]Declaration`, direct
|
|
||||||
`Command` calls, slice conversion, and explicit root installation of rules.
|
|
||||||
Include a minimal real integration composition example and links to the
|
|
||||||
maintained complete consumers.
|
|
||||||
4. Update the internal overview and applicable architecture provisions for the
|
|
||||||
separate canonical/routing layers and joint installation. ADR 0013 already
|
|
||||||
authorizes this architecture; do not rewrite accepted decisions or add an ADR
|
|
||||||
for incidental algorithm or presentation details.
|
|
||||||
5. Update developer navigation to the roadmap/plan while work is active and
|
|
||||||
preserve `deferred.md`. Keep shell completion as future direction only.
|
|
||||||
|
|
||||||
**Evidence:** local links and fragments resolve; volatile behavior has its
|
|
||||||
canonical owner; no future alias APIs are described as existing before their
|
|
||||||
implementation is present. Prose checks and relevant examples agree.
|
|
||||||
|
|
||||||
**Completed:** GoDoc now distinguishes canonical `Command` declarations from
|
|
||||||
root-installed routing rules and documents captured errors, invalid nil/zero
|
|
||||||
values, idempotent duplicates, canonical flag scopes, and invocation paths. The
|
|
||||||
CLI reference, consumer guide, maintained example READMEs, internal overview,
|
|
||||||
architecture policy, and active developer navigation describe the implemented
|
|
||||||
contracts and integration wiring. Local Markdown links and fragments resolved;
|
|
||||||
`git diff --check -- '*.md' COPYRIGHT` and the cached equivalent passed. The
|
|
||||||
deferred-work record and accepted ADR were left unchanged.
|
|
||||||
|
|
||||||
## Stage 16: Record compatibility impact for the next core release
|
|
||||||
|
|
||||||
**Work**
|
|
||||||
|
|
||||||
1. Prepare the next core minor release note, `docs/releases/v0.3.0.md`, with
|
|
||||||
the product title, short summary, migration guidance, and required immutable
|
|
||||||
licensing footer under the release procedure. Do not edit published notes.
|
|
||||||
2. Explain the `...Command` to `...Declaration` change, especially `[]Command`
|
|
||||||
expansion and function-value signature changes; command/group factories
|
|
||||||
still return `Command`. Note private Invocation path storage's impact on
|
|
||||||
positional struct literals and recommend keyed construction when needed.
|
|
||||||
3. Explain command/flag aliases and the explicit short-option empty-value
|
|
||||||
correction. Go 1.26.0 and the current upstream/backend selections need not
|
|
||||||
change for this feature.
|
|
||||||
4. Keep publication and real integration dependency bumps separate. The next
|
|
||||||
core must be published before dependent module release preparation downloads
|
|
||||||
that version and records actual sums, as required by `docs/release.md`.
|
|
||||||
Do not invent core v0.3.0 sums, commit local replacements, or rewrite the
|
|
||||||
integrations' existing v0.1.0 release notes. Report this release-preparation
|
|
||||||
dependency in the final implementation handoff.
|
|
||||||
|
|
||||||
**Evidence:** note explains consumer action and candidate-local link paths and
|
|
||||||
footer are correct. No release launcher, remote push, or tag operation occurs
|
|
||||||
as part of implementing this plan.
|
|
||||||
|
|
||||||
**Completed:** Added `docs/releases/v0.3.0.md` with the `...Declaration`
|
|
||||||
migration, command-slice conversion, function-value signature impact,
|
|
||||||
positional `Invocation` guidance, alias behavior, and `-c=` empty-value
|
|
||||||
correction. The note retains Go 1.26.0 and maintainer Go 1.26.8 and includes
|
|
||||||
candidate-tag links plus the required immutable licensing footer. No published
|
|
||||||
release note, dependency version, sum file, tag, or remote was changed. Prepare
|
|
||||||
integration dependency adoption only after core v0.3.0 is published.
|
|
||||||
|
|
||||||
## Stage 17: Verify the complete target and finish
|
|
||||||
|
|
||||||
**Work**
|
|
||||||
|
|
||||||
1. Format changed Go sources and run the complete deterministic root suite and
|
|
||||||
both integration suites using the local three-module workspace described by
|
|
||||||
the developer guide. Use the documented Go 1.26.8 maintainer toolchain; this
|
|
||||||
feature does not raise the consumer minimum.
|
|
||||||
2. Root independent validation uses `GOWORK=off` and its actual module graph.
|
|
||||||
For nested modules needing unpublished local core APIs in tests/examples,
|
|
||||||
use disposable copies of each `go.mod`/`go.sum` through `-modfile`, with a
|
|
||||||
local core replacement; replace ckconfig with its local source for composed
|
|
||||||
verification where needed. Run `GOWORK=off` module suites against those
|
|
||||||
copies. Permit only disposable metadata to change and inspect it separately.
|
|
||||||
This verifies local source composition, not published-version availability.
|
|
||||||
3. Leave committed dependency constraints and genuine sums intact until their
|
|
||||||
separately authorized release preparation. Do not run nested suites against
|
|
||||||
old published core and count failures as feature failures or count old code's
|
|
||||||
success as evidence for new aliases. Do not publish dependencies to make
|
|
||||||
this implementation sprint's checks pass.
|
|
||||||
4. Confirm core still has no optional-library dependency, backend imports stay
|
|
||||||
internal, integration factories remain canonical `Command` factories, and
|
|
||||||
alias lookup requires no application/provider initialization.
|
|
||||||
5. Audit every roadmap behavior against the evidence index below. Verify
|
|
||||||
metadata paths, help views, errors, and failed-registration recovery, not
|
|
||||||
only successful alias execution. Reuse existing focused evidence rather
|
|
||||||
than creating an additional redundant test framework or release gate.
|
|
||||||
6. Run prose whitespace and local-link checks; inspect all diffs and intended
|
|
||||||
files. Mark stages complete with actual evidence, update the feature
|
|
||||||
roadmap's status, commit remaining intended work, and report validation plus
|
|
||||||
any release-preparation steps still required. Preserve completed planning
|
|
||||||
records until cleanup is requested.
|
|
||||||
|
|
||||||
After selecting the documented toolchain and preparing the existing dependency
|
|
||||||
cache, the independent graph checks can be performed from the repository root
|
|
||||||
as follows. The workspace checks above are still needed; these commands exercise
|
|
||||||
each module's own metadata with only the indicated local source substitutions.
|
|
||||||
The temporary-file updates accommodate unpublished source without changing
|
|
||||||
tracked version requirements or synthesizing published checksums.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
(
|
|
||||||
set -eu
|
|
||||||
commandkit_alias_repo=$(pwd)
|
|
||||||
commandkit_alias_verify=$(mktemp -d /tmp/commandkit-alias-verify.XXXXXX)
|
|
||||||
trap 'rm -rf "$commandkit_alias_verify"' EXIT
|
|
||||||
export GOTOOLCHAIN=local GOWORK=off
|
|
||||||
export GOPROXY=off GONOPROXY=none GOSUMDB=off
|
|
||||||
|
|
||||||
go test -mod=readonly ./...
|
|
||||||
|
|
||||||
cp integrations/ckconfig/go.mod "$commandkit_alias_verify/ckconfig.mod"
|
|
||||||
cp integrations/ckconfig/go.sum "$commandkit_alias_verify/ckconfig.sum"
|
|
||||||
go mod edit -modfile="$commandkit_alias_verify/ckconfig.mod" \
|
|
||||||
-replace="gitea.maximumdirect.net/eric/CommandKit=$commandkit_alias_repo"
|
|
||||||
(cd integrations/ckconfig &&
|
|
||||||
go test -mod=mod -modfile="$commandkit_alias_verify/ckconfig.mod" ./...)
|
|
||||||
|
|
||||||
cp integrations/ckprompt/go.mod "$commandkit_alias_verify/ckprompt.mod"
|
|
||||||
cp integrations/ckprompt/go.sum "$commandkit_alias_verify/ckprompt.sum"
|
|
||||||
go mod edit -modfile="$commandkit_alias_verify/ckprompt.mod" \
|
|
||||||
-replace="gitea.maximumdirect.net/eric/CommandKit=$commandkit_alias_repo"
|
|
||||||
go mod edit -modfile="$commandkit_alias_verify/ckprompt.mod" \
|
|
||||||
-replace="gitea.maximumdirect.net/eric/CommandKit/integrations/ckconfig=$commandkit_alias_repo/integrations/ckconfig"
|
|
||||||
(cd integrations/ckprompt &&
|
|
||||||
go test -mod=mod -modfile="$commandkit_alias_verify/ckprompt.mod" ./...)
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
If an offline command reports an absent dependency, prepare that dependency
|
|
||||||
separately and rerun the affected check. Do not turn an offline suite into a
|
|
||||||
network-enabled test run or silently substitute older published implementation.
|
|
||||||
These local-source graph checks do not add a permanent release gate.
|
|
||||||
|
|
||||||
**Complete when:** the accepted feature works through the public consumer
|
|
||||||
boundary, the selected checks pass against local source, documentation matches
|
|
||||||
the implementation, and no unresolved feature decisions or implementation work
|
|
||||||
remain. Publishing and dependent-version availability are separate operations.
|
|
||||||
|
|
||||||
**Completed:** All workspace suites passed on Go 1.26.8: root, ckconfig, and
|
|
||||||
ckprompt, including maintained examples. Independent `GOWORK=off` checks also
|
|
||||||
passed for all three modules using the root module graph and disposable local
|
|
||||||
source replacements; only replacement directives changed in temporary module
|
|
||||||
files, with no sum changes. The final review confirmed core has no optional
|
|
||||||
integration dependency, backend imports remain internal, integration factories
|
|
||||||
return canonical commands, and alias composition is covered without provider
|
|
||||||
loads during help. Routing, flag interpretation, help, diagnostics, identity,
|
|
||||||
installation recovery, typed bindings, and consumer composition are covered by
|
|
||||||
the focused evidence recorded in Stages 1–14. Documentation links and
|
|
||||||
candidate-note paths resolve; prose whitespace checks passed. The alias feature
|
|
||||||
roadmap now records completed implementation while leaving core publication
|
|
||||||
and dependent integration release preparation separate.
|
|
||||||
|
|
||||||
## Target evidence index
|
|
||||||
|
|
||||||
| Accepted behavior | Primary stages |
|
|
||||||
| --- | --- |
|
|
||||||
| Public factories, capture, absence/zero/nil handling, slices | 1, 4, 5, 12, 15, 16 |
|
|
||||||
| Exact chains, longest matches, group composition, universal termination | 2, 3, 5, 7, 12 |
|
|
||||||
| Canonical ownership, operand boundaries, no preset operands | 5, 7, 12, 13 |
|
|
||||||
| Same-batch and later installation, duplicates, rollback | 5, 6, 12 |
|
|
||||||
| Global/scoped flag aliases, chains, endpoints, availability, collisions | 6, 8, 12, 13 |
|
|
||||||
| Values, operands, clusters, empty values, presence, repeat order | 8, 9, 11, 13 |
|
|
||||||
| Entered/canonical identity and ordinary lifecycle | 7, 9, 11, 13 |
|
|
||||||
| Root/group/alias-prefix help, effective flag help, target-aware usage | 7, 10, 11, 12 |
|
|
||||||
| Error identity, cancellation, report/diagnostic delivery | 9, 11, 13 |
|
|
||||||
| Real consumer composition and module boundaries | 12, 13, 14, 17 |
|
|
||||||
| Future-completion lookup separation without completion delivery | 7, 10, 15 |
|
|
||||||
| Migration, current references, release-note preparation | 14, 15, 16, 17 |
|
|
||||||
@@ -1,320 +0,0 @@
|
|||||||
# Alias implementation review remediation
|
|
||||||
|
|
||||||
Status: complete; R-1 through R-8 are addressed and marked individually below.
|
|
||||||
|
|
||||||
## Review scope and evidence
|
|
||||||
|
|
||||||
Reviewed commit `a54a9354b1a563849c31dfda906c602950016b02` against the accepted
|
|
||||||
[alias roadmap](aliases.md), [implementation plan](implementation.md),
|
|
||||||
[ADR 0013](../adr/0013-application-alias-routing.md), and applicable architecture,
|
|
||||||
testing, and documentation policies. The implementation range is
|
|
||||||
`d7cc12a..a54a935`.
|
|
||||||
|
|
||||||
The root module's default suite passed independently with `GOWORK=off`.
|
|
||||||
Both integration default suites, including their maintained examples, passed
|
|
||||||
in the existing three-module workspace against the current local core.
|
|
||||||
These checks used Go 1.26.8 with network resolution disabled. Passing suites
|
|
||||||
do not cover the reproductions below: those failures were confirmed separately
|
|
||||||
through the public API using a disposable consumer outside the repository.
|
|
||||||
No production code or tracked tests were changed during review.
|
|
||||||
|
|
||||||
Unless stated otherwise, reproduction commands below assume an application
|
|
||||||
named `demo`, ordinary string operand conversion, and local success callbacks.
|
|
||||||
They describe fixtures to construct through the public API, not commands
|
|
||||||
already installed by the example applications. Use semantic assertions and
|
|
||||||
supported causes when adding regression tests; do not freeze diagnostic prose
|
|
||||||
or private representations unnecessarily.
|
|
||||||
|
|
||||||
## R-1: Protect prefixes of canonical operand space during installation
|
|
||||||
|
|
||||||
Status: complete. Priority: P1. Category: canonical command reachability.
|
|
||||||
|
|
||||||
**Evidence:** [traceCanonicalPath](../../registry.go#L318) uses
|
|
||||||
[acceptsOperandCount](../../registry.go#L337), which requires the source's entire
|
|
||||||
remaining token count to meet the command's minimum. This misses an alias
|
|
||||||
source that becomes a prefix of a valid invocation when more operands follow.
|
|
||||||
|
|
||||||
With canonical `run ARG{2..2}` and a separate runnable `inspect` accepting an
|
|
||||||
optional repeated operand, installation accepts:
|
|
||||||
|
|
||||||
```go
|
|
||||||
commandkit.Alias("run first", "inspect")
|
|
||||||
```
|
|
||||||
|
|
||||||
`demo run first second` then runs `inspect`, passing `second` as its operand;
|
|
||||||
the original valid `run` invocation is no longer reachable with that input.
|
|
||||||
The public probe returned status 0 from the wrong handler.
|
|
||||||
|
|
||||||
**Required work:** Check whether a source can intercept a valid canonical
|
|
||||||
invocation, including prefixes completed by later operands, after normal
|
|
||||||
canonical child selection. Do not require that the alias source already
|
|
||||||
satisfy the command's minimum operand count. Apply this against the complete
|
|
||||||
candidate in both registration orders and preserve failed-batch atomicity.
|
|
||||||
Keep the selected distinction between canonical operand space and explicit
|
|
||||||
longer aliases beneath alternate spellings such as `r → run`.
|
|
||||||
|
|
||||||
**Completion evidence:** Reject the example at construction and when either
|
|
||||||
side is added later; preserve the preexisting registry on rejection. Include
|
|
||||||
multi-required and repeated operands and a valid distinct child/shortcut case
|
|
||||||
so the correction does not reserve every route beneath any runnable ancestor.
|
|
||||||
|
|
||||||
**Completed:** Installation now protects operand prefixes that can be completed
|
|
||||||
by later arguments without requiring the minimum count immediately. New
|
|
||||||
regressions failed before the correction and pass for fixed/repeated operands,
|
|
||||||
construction, both later registration orders, and rollback. Existing child and
|
|
||||||
longer-shortcut cases and the complete offline root suite passed on Go 1.26.8.
|
|
||||||
|
|
||||||
## R-2: Select canonical routing context before validating operand counts
|
|
||||||
|
|
||||||
Status: complete. Priority: P2. Category: unintended parsing restriction and identity.
|
|
||||||
|
|
||||||
**Evidence:** [resolveEnteredRoute](../../route.go#L25) also uses the complete
|
|
||||||
operand-count predicate from R-1, but it examines only tokens before the first
|
|
||||||
flag. This is not enough information to determine execution arity when flags
|
|
||||||
and operands are interspersed. A known canonical command can therefore become
|
|
||||||
`routeUnknown`, disabling its aliases and discarding its identity.
|
|
||||||
|
|
||||||
With canonical `run ARG{2..2}`, `r → run`, and scoped
|
|
||||||
`--fmt → --format`:
|
|
||||||
|
|
||||||
| Invocation | Observed result |
|
|
||||||
| --- | --- |
|
|
||||||
| `demo r first --fmt=yaml second` | Status 2: unknown `--fmt`, although both operands are supplied. |
|
|
||||||
| `demo r first --format=yaml second` | Handler succeeds but sees `EnteredPath() == "r first"` and `CanonicalPath() == ""`. |
|
|
||||||
| `demo r first --help` | Status 0 with application-root help instead of `run` help. |
|
|
||||||
|
|
||||||
This introduces an unrequested prerequisite: enough operands must appear
|
|
||||||
before the first option for routing metadata and flag aliases to work.
|
|
||||||
It also contradicts the selected exclusion of operands from invocation paths.
|
|
||||||
|
|
||||||
**Required work:** Separate structural canonical selection from execution
|
|
||||||
operand-cardinality validation and from installation's operand-interception
|
|
||||||
check. Retain the selected command, its spelling context, and the actual
|
|
||||||
entered command span even when execution operands are incomplete or invalid.
|
|
||||||
Let the existing parser/input-preparation boundary validate operands after all
|
|
||||||
tokens are interpreted. Help must continue to skip missing execution-required
|
|
||||||
operands without constructing application inputs.
|
|
||||||
|
|
||||||
**Completion evidence:** The valid interspersed invocation succeeds with
|
|
||||||
entered path `r` and canonical path `run`; partial-operand help describes that
|
|
||||||
command and recognizes its applicable aliases. Test canonical and shortcut
|
|
||||||
forms, and ensure genuinely invalid execution arity still produces usage errors.
|
|
||||||
|
|
||||||
**Completed:** Canonical tracing now selects runnable commands structurally;
|
|
||||||
installation alone applies the operand-prefix capacity check. Runtime routing
|
|
||||||
keeps command identity and applicable flag aliases for partial or excess
|
|
||||||
operands, while input preparation retains arity validation. Regressions cover
|
|
||||||
interspersed canonical/alias flags, incomplete help, invalid arity, path metadata,
|
|
||||||
and discovery beneath a zero-operand runnable command. The excess-operand
|
|
||||||
regression failed before this change; the full offline root suite and the
|
|
||||||
additional discovery check passed on Go 1.26.8.
|
|
||||||
|
|
||||||
## R-3: Preserve exact target lookup for the explicit help command
|
|
||||||
|
|
||||||
Status: complete. Priority: P2. Category: help grammar regression.
|
|
||||||
|
|
||||||
**Evidence:** [renderHelpTargets](../../execute.go#L155) reuses execution lookup
|
|
||||||
and accepts `routeCanonical` results even when remaining target tokens are
|
|
||||||
ordinary operands. It then renders the canonical view and drops those tokens.
|
|
||||||
For the `run` fixture above:
|
|
||||||
|
|
||||||
```text
|
|
||||||
demo help r first second
|
|
||||||
```
|
|
||||||
|
|
||||||
returns status 0 and the help for `run`. `first second` are not registered
|
|
||||||
command components. This contradicts the [exact help-path contract](../cli.md#help)
|
|
||||||
and conflates execution operands with a help target's command path.
|
|
||||||
|
|
||||||
**Required work:** Use an exact-target mode or explicit consumed-token result
|
|
||||||
for help lookup. After alias resolution, all target tokens must identify a
|
|
||||||
canonical command/group or a supported alias-prefix discovery view. Do not
|
|
||||||
silently accept execution operands as part of an explicit help path. Preserve
|
|
||||||
ordinary `r first second --help` behavior and help for commands whose execution
|
|
||||||
requires operands.
|
|
||||||
|
|
||||||
**Completion evidence:** Canonical and aliased operand-bearing explicit help
|
|
||||||
targets fail with usage status 2; exact aliases, group shortcuts, and discovery
|
|
||||||
prefixes still render help without application initialization.
|
|
||||||
|
|
||||||
**Completed:** Explicit help now requires all resolved target tokens to form
|
|
||||||
the selected path; execution operands no longer disappear into a help view.
|
|
||||||
New public-boundary regressions failed before the fix and now reject canonical
|
|
||||||
and aliased operand-bearing targets while preserving exact command/group aliases,
|
|
||||||
discovery help, and ordinary execution-form help without input initialization.
|
|
||||||
The complete offline root suite passed on Go 1.26.8.
|
|
||||||
|
|
||||||
## R-4: Resolve discovery-help contexts through group shortcuts
|
|
||||||
|
|
||||||
Status: complete. Priority: P2. Category: incomplete alias composition.
|
|
||||||
|
|
||||||
**Evidence:** Discovery contexts are indexed by declared source prefixes in
|
|
||||||
[discoverFlagContexts](../../flag_aliases.go#L157), while
|
|
||||||
[resolveEnteredRoute](../../route.go#L49) searches them using the original entered
|
|
||||||
path only. A group shortcut can reach a valid alias-only prefix whose entered
|
|
||||||
spelling has no separate context entry.
|
|
||||||
|
|
||||||
With canonical group `box`, canonical `inspect`, and:
|
|
||||||
|
|
||||||
```text
|
|
||||||
pk → box
|
|
||||||
box admin pick → inspect
|
|
||||||
```
|
|
||||||
|
|
||||||
`demo box admin --help` succeeds and lists `pick → inspect`, but both
|
|
||||||
`demo pk admin --help` and `demo help pk admin` fail with status 2.
|
|
||||||
The complete `pk admin pick` route remains available through composition.
|
|
||||||
|
|
||||||
**Required work:** Select discovery metadata through resolved group-prefix
|
|
||||||
composition while retaining the entered spelling for presentation. Reuse the
|
|
||||||
same rule precedence as execution, including more-specific mappings. Keep
|
|
||||||
discovery contexts separate from canonical command nodes and restrict their
|
|
||||||
flags to core help plus applicable global aliases.
|
|
||||||
|
|
||||||
**Completion evidence:** Both help forms work through the group shortcut,
|
|
||||||
show `pk admin` in usage, and list the routes actually reachable there.
|
|
||||||
Cover the global help alias and a more-specific route override; do not add
|
|
||||||
canonical groups or inherit descendant flags to make discovery work.
|
|
||||||
|
|
||||||
**Completed:** Discovery selection now checks the resolved prefix and retains
|
|
||||||
the entered route; help merges applicable entered/resolved routes and resolves
|
|
||||||
each destination through actual shortcut precedence. Regressions first failed
|
|
||||||
for the missing composed context and omitted inherited routes. Both help forms,
|
|
||||||
global help aliases, more-specific overrides, entered-only prefixes, expanded
|
|
||||||
group paths, bare-prefix usage, and descendant-flag exclusion now pass. No
|
|
||||||
canonical nodes were added. The full offline root suite and added path cases
|
|
||||||
passed on Go 1.26.8.
|
|
||||||
|
|
||||||
## R-5: Include alias routes in help for groups without canonical children
|
|
||||||
|
|
||||||
Status: complete. Priority: P2. Category: help discovery gap.
|
|
||||||
|
|
||||||
**Evidence:** [routeHelpAliases](../../help_view.go#L48) returns immediately when
|
|
||||||
the selected canonical node has no canonical children. Alias records are
|
|
||||||
separate from those children, so this suppresses valid routes beneath an
|
|
||||||
otherwise empty group.
|
|
||||||
|
|
||||||
With `Group("box", "Box group.")`, canonical `inspect`, and
|
|
||||||
`box pick → inspect`, `demo box pick` is available, but `demo box --help`
|
|
||||||
lists no `pick` route. The same problem affects help through `pk → box`.
|
|
||||||
|
|
||||||
**Required work:** Determine relevant help aliases independently of whether the
|
|
||||||
canonical group has children. Preserve the separate display of canonical
|
|
||||||
commands and routing records; do not install fake children to fill the view.
|
|
||||||
|
|
||||||
**Completion evidence:** Canonical and shortcut help for an empty group list
|
|
||||||
its explicit alias routes and their resolved destinations, while groups with
|
|
||||||
no such routes retain their ordinary help behavior.
|
|
||||||
|
|
||||||
**Completed:** Group alias discovery no longer depends on canonical child
|
|
||||||
count. A new regression failed for canonical and shortcut help before the
|
|
||||||
correction, and now both help forms list the separate alias route. An unrelated
|
|
||||||
empty group's help remains unchanged and the complete route still executes.
|
|
||||||
No synthetic command children were introduced. The complete offline root suite
|
|
||||||
passed on Go 1.26.8.
|
|
||||||
|
|
||||||
## R-6: Keep the flag interpretation pass consistent with value consumption
|
|
||||||
|
|
||||||
Status: complete. Priority: P2. Category: canonical/alias parsing divergence.
|
|
||||||
|
|
||||||
**Evidence:** [interpretFlagTokens](../../internal/cobra/flags.go#L28) refuses to
|
|
||||||
consume a following `--` as the value of a value-taking flag in both the long
|
|
||||||
and short branches. It subsequently treats that token as the option terminator
|
|
||||||
and stops resolving aliases. The backend still consumes `--` as the pending
|
|
||||||
flag's value, so subsequent tokens are interpreted differently by the two passes.
|
|
||||||
|
|
||||||
For value flag `--format` and alias `--fmt → --format`:
|
|
||||||
|
|
||||||
```text
|
|
||||||
demo show --format -- --fmt red # status 2: unknown --fmt
|
|
||||||
demo show --format -- --format red # status 0
|
|
||||||
```
|
|
||||||
|
|
||||||
The canonical and aliased second occurrences should feed the same binding.
|
|
||||||
|
|
||||||
**Required work:** Preserve value-taking arity consistently between alias
|
|
||||||
interpretation and backend parsing, including when the consumed value is `--`.
|
|
||||||
Treat a token as an option terminator only when it occupies that grammatical
|
|
||||||
role. Do not address this by banning a previously accepted flag value or by
|
|
||||||
introducing a different operand/option convention.
|
|
||||||
|
|
||||||
**Completion evidence:** The paired invocations have equivalent outcomes and
|
|
||||||
values. Cover canonical and aliased long/short spellings, and preserve ordinary
|
|
||||||
termination when `--` occurs after a completed value or boolean flag.
|
|
||||||
|
|
||||||
**Completed:** The alias interpretation pass now consumes the next token for
|
|
||||||
value-taking long and short flags even when that value is `--`, matching backend
|
|
||||||
arity. All four canonical/alias long/short regressions failed before the fix and
|
|
||||||
now retain the value, later alias occurrences, original spellings, and genuine
|
|
||||||
post-value terminators. Boolean/value termination cases also pass. No accepted
|
|
||||||
value was prohibited. The complete offline root suite passed on Go 1.26.8.
|
|
||||||
|
|
||||||
## R-7: Retain entered flag spellings in parser-level usage failures
|
|
||||||
|
|
||||||
Status: complete. Priority: P3. Category: incomplete diagnostic adaptation.
|
|
||||||
|
|
||||||
**Evidence:** Typed flag conversion uses occurrence provenance, but
|
|
||||||
[Session.Parse](../../internal/cobra/parse.go#L89) returns normalized backend
|
|
||||||
failure text directly, and [rawValue.lastBool](../../internal/cobra/parse.go#L474)
|
|
||||||
hardcodes `--help`. Verified examples:
|
|
||||||
|
|
||||||
- Through `r → run`, a missing value for `--fmt → --format` reports only
|
|
||||||
`flag needs an argument: --format`, omitting the entered flag spelling.
|
|
||||||
- With `--hlep → --help`, `demo show --hlep=bad` reports an invalid value for
|
|
||||||
`--help`, omitting `--hlep`; canonical short `-h=bad` likewise loses `-h`.
|
|
||||||
|
|
||||||
The roadmap and [CLI reference](../cli.md#application-owned-aliases) require
|
|
||||||
usage diagnostics to retain the entered spelling, not only for the later
|
|
||||||
typed-conversion path.
|
|
||||||
|
|
||||||
**Required work:** Carry the relevant occurrence context through missing-value
|
|
||||||
and built-in-help conversion failures. Retain the entered spelling, optionally
|
|
||||||
identifying the canonical target, using neutral adapter records rather than
|
|
||||||
exposing backend error types or making brittle whole-message substitutions.
|
|
||||||
Keep the existing usage classification and delivery behavior.
|
|
||||||
|
|
||||||
**Completion evidence:** Check entered spellings for missing long/short alias
|
|
||||||
values and invalid help values, including an earlier invalid occurrence followed
|
|
||||||
by a valid overwrite. Assert the identifying fragments and existing causes
|
|
||||||
where supported; no new exact diagnostic format is required.
|
|
||||||
|
|
||||||
**Completed:** Missing-value failures now carry the entered long/short spelling
|
|
||||||
through a neutral adapter record; earlier backend failures retain precedence.
|
|
||||||
Built-in help conversion uses the failing occurrence's original spelling,
|
|
||||||
including when a later valid value follows it. Adapter and public-boundary
|
|
||||||
regressions failed before the fix and now cover alias values, clusters, help
|
|
||||||
occurrences, entered usage paths, and input-initialization avoidance. Existing
|
|
||||||
usage classification is unchanged. The complete offline root suite passed on
|
|
||||||
Go 1.26.8.
|
|
||||||
|
|
||||||
## R-8: Reconcile the completed feature roadmap's historical descriptions
|
|
||||||
|
|
||||||
Status: complete. Priority: P3. Category: documentation drift.
|
|
||||||
|
|
||||||
**Evidence:** [aliases.md](aliases.md) now declares implementation complete
|
|
||||||
but still has a `Current baseline` section saying the public model has no alias
|
|
||||||
layer, calls the implemented declarations `planned APIs`, and describes the
|
|
||||||
old `-c=` behavior as current. The consumer guide also calls the temporary
|
|
||||||
roadmap the routing-contract record despite linking the maintained CLI reference
|
|
||||||
next to it.
|
|
||||||
|
|
||||||
**Required work:** Label the preimplementation baseline and old behavior as
|
|
||||||
historical, distinguish delivered implementation from this open review work,
|
|
||||||
and describe the now-implemented APIs accurately. Point consumer contract
|
|
||||||
navigation to GoDoc/CLI owners; retain the roadmap as planning/history, not a
|
|
||||||
second contract owner. Keep completed stage evidence historical and do not
|
|
||||||
restart completed implementation stages or rewrite published release notes.
|
|
||||||
|
|
||||||
**Completion evidence:** Roadmap status, baseline, and API wording agree;
|
|
||||||
consumer navigation identifies the canonical owners and the open remediation
|
|
||||||
work is discoverable without claiming that these findings are already fixed.
|
|
||||||
|
|
||||||
**Completed:** The feature roadmap now labels its preimplementation baseline
|
|
||||||
and former short-option behavior as historical, identifies the APIs as
|
|
||||||
implemented, and links this completed review separately from the completed
|
|
||||||
implementation stages. Consumer navigation points to GoDoc and the maintained
|
|
||||||
CLI contract. Published release records and completed stage evidence were left
|
|
||||||
unchanged. Local links and fragment destinations in all three affected documents
|
|
||||||
resolve, and whitespace checks pass. Final uncached offline suites passed on
|
|
||||||
Go 1.26.8: root with the workspace disabled, plus both integration modules and
|
|
||||||
their maintained examples in the existing workspace against the local core.
|
|
||||||
Reference in New Issue
Block a user