Browse Source
Both user-approved after a review of the intended plugin facility (punk::mix::init pluginmgr todos, the punk::pluginmgr 0.5.1 tcllib fork, punk::cap provider/handler system, punk::cap::handlers::templates pathtype resolution, punk::overlay commandset composition and its toml-CLI todo). - G-042: a named subshell declares help topics (name/aliases/summary/text) in punk::config stored configuration, registered into the ::punk::helptopic registry on entry and restored on exit, with an explicit shadowing policy. Text-content only - config is data; code-bearing topics belong to the plugin path where the trust story lives. Detail file records the registry seam (punk 0.2.0), dependencies (hard on G-014; beneficial G-040/G-008/G-009), and the plugin-facility relationship from the review. - G-043: the umbrella for that plugin path - a punk.subshell capability whose providers supply commandset bindings (punk::overlay import), help topics (G-042's registry API) and config defaults per named subshell, with a validating punk::cap handler, an equivalent data-only stored-config declaration path (absorbing punk::overlay's ".toml configuration files for defining CLI configurations" todo), and punk::pluginmgr as the discovery/ safe-interp trust layer for untrusted providers. Also absorbs punk::cap housekeeping found in the review: pkg_unregister api-object cleanup and unhandled-capability discoverability (the deliberate punk.isbogus silence). Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.commaster
3 changed files with 244 additions and 0 deletions
@ -0,0 +1,120 @@
|
||||
# G-042 Subshell-declared help topics via punk::config with defined shadowing policy |
||||
|
||||
Status: proposed |
||||
Scope: src/modules/punk-999999.0a1.0.tm (::punk::helptopic registry), src/modules/punk/config-0.1.tm (stored declaration source), src/modules/punk/repl-999999.0a1.0.tm (subshell entry/exit hooks) |
||||
Acceptance: a subshell whose configuration declares at least one custom topic shows it in 'help topics' and renders its configured content via 'help <topic>' inside that subshell, and 'i help' lists it as a documented choice; on quit/switch-away the parent's topic set is restored (no leakage, proven by declaring a topic in a subshell and checking the parent after exit); configuration is read through punk::config (toml per G-014 - no ad-hoc parsing) and a shell with no topic configuration behaves unchanged; config-declared topics are text-content only - they cannot name code to execute (or a recorded design decision to the contrary with its sandboxing rationale in the detail file); the shadowing policy is implemented and documented: a declared topic colliding with a built-in topic is rejected (or explicitly overrides per a documented rule), a topic name shadowing a command name wins over command fallthrough as today with 'i <cmd>'/'s <cmd>' documented as the command-help escape hatch; depends on G-014 for the stored-config substrate - the registry-side registration/restore mechanism may land earlier behind a programmatic API, with the config binding completing when G-014 lands. |
||||
|
||||
## Context |
||||
|
||||
Arose from the 2026-07-08 punk::help restructure (punk module 0.2.0), which replaced the |
||||
monolithic help_chunks switch with the ::punk::helptopic registry: each topic is a handler |
||||
proc plus a punk::args definition, and registering a topic (re)generates the ::punk::help / |
||||
::punk::help_chunks definitions so 'help topics' and the 'i help' documented choice table |
||||
can never drift from the registered set. That registry was explicitly built as the seam for |
||||
this goal: adding a topic at runtime already updates every documentation surface for free. |
||||
|
||||
The user's intent (2026-07-08, during the restructure): the help system should be usable as |
||||
a default for customised (punk::config-enabled) subshells with their own topics. Today the |
||||
topic set is small and largely orthogonal to command names, so topic-vs-command shadowing |
||||
is a non-issue; once subshells declare arbitrary topics, the precedence between a topic |
||||
word and the command-info fallthrough (help <cmdname>) becomes a policy that must be |
||||
explicit rather than accidental. |
||||
|
||||
## Approach (sketch - to be refined when activated) |
||||
|
||||
1. Registry side (can land ahead of G-014, programmatic API): |
||||
- a generic text-topic handler: config-declared topics carry name, aliases, summary and |
||||
body text; the handler renders the body as chunks (frametype-aware wrapping optional). |
||||
No code execution from configuration - a topic cannot name a proc to run. This is |
||||
deliberate: G-003/G-009 restricted subshells must be able to carry custom help without |
||||
the config becoming an interp-escape vector. If handler-proc topics are ever wanted, |
||||
record the sandboxing rationale here first. |
||||
- register/deregister with scoping: subshell entry registers its declared topics, |
||||
quit/switch-away restores the prior registry state. Natural shape: save/restore of the |
||||
registry dict rides the same lifecycle as the G-008 console state sets (activatable |
||||
per-subshell state), but the registry is punk-side data - no terminal interaction - |
||||
so it need not wait for G-008. |
||||
- collision rule at registration time: reject (or per documented rule, override) a |
||||
declared topic whose name or alias matches a built-in topic; the existing register |
||||
proc already errors on a missing handler - extend it to police names. |
||||
2. Config binding (gated on G-014): |
||||
- declaration lives in punk::config stored configuration under the named-subshell |
||||
scoping G-014 defines (a subshell resolves its own topics; unconfigured shells |
||||
inherit nothing extra). All reading via punk::config API backed by tomlish. |
||||
- shape sketch (indicative only): [subshell.<name>.helptopic.<topic>] with keys |
||||
aliases, summary, body. |
||||
3. Shadowing policy: registered topics win over command fallthrough (unchanged); the |
||||
escape hatch for a shadowed command name is 'i <cmd>' / 's <cmd>' (the first-class |
||||
command-help route) - document it where the topic set is presented ('help topics' |
||||
footer or the ::punk::help -help text). |
||||
4. Display: alias folding for declared topics inherits whatever G-040 lands |
||||
(-choicealiases); until then aliases appear as separate documented choices, as the |
||||
built-ins do today. |
||||
|
||||
## Relationship to the intended plugin facility (code review 2026-07-08) |
||||
|
||||
Reconnaissance of punk::mix::init, punk::cap, punk::pluginmgr and punk::overlay maps the |
||||
plugin stack the codebase already intends, which this goal must slot into: |
||||
|
||||
1. Discovery/loading + trust boundary: tcllib pluginmgr-style safe-interp plugin loading. |
||||
punk::pluginmgr-0.5.1.tm is a vendored fork of tcllib pluginmgr with initial divergence |
||||
("JN - diverging from tcllib" in LoadPlugin: direct plugin.tcl sourcing from plugin |
||||
paths); punk::mix::init's todos record the known gaps (tcllib 0.5 bugs around .tm |
||||
modules vs packages - reports submitted upstream - and control of module/library path |
||||
ordering inside the safe interps). |
||||
2. Capability registration/validation: punk::cap - in-process and cooperative (its own |
||||
doctools position tcllib pluginmgr as "an alternative which uses safe interpreters"). |
||||
Provider packages declare (capname capdict) pairs via a registration object; handlers |
||||
validate at registration (pkg_register veto) and expose api_<capname> objects. |
||||
punk.templates is the only handled capability today. |
||||
3. Capability-specific handler APIs: punk::cap::handlers::templates, whose pathtype |
||||
vocabulary (module / adhoc / currentproject* / shellproject* / absolute) is the |
||||
existing answer to from-kit vs from-src-tree resolution. |
||||
|
||||
Implications adopted for this goal: |
||||
|
||||
- The ::punk::helptopic programmatic registry API is the convergence point. Stored-config |
||||
topics (this goal - text only) and any future plugin-provided topics (code-bearing, |
||||
arriving as provider packages through the punk::cap layer - e.g. a punk.subshell or |
||||
punk.helptopics capability - where provider trust is the plugin facility's concern) land |
||||
in the same registry, under the same collision policy, with the same punk::args |
||||
regeneration. Nothing in this goal's mechanism needs reworking for plugins later. |
||||
- The text-only stance is reinforced, and the boundary is now principled rather than just |
||||
cautious: punk::config declarations are data; code-bearing topic handlers belong to the |
||||
plugin path where a validation/trust story (cap handler veto, pluginmgr safe interps) |
||||
exists. |
||||
- Subshell definitions as plugins: punk::overlay::import_commandset is the existing |
||||
commandset composition mechanism (rename-imports a commandset namespace's exported |
||||
commands under a prefix; explicitly designed so one commandset can serve multiple CLIs |
||||
simultaneously), and its own documentation already records the intent "Todo - .toml |
||||
configuration files for defining CLI configurations". A future subshell-definition |
||||
plugin/profile would compose: commandset imports + help topics + config defaults |
||||
(+ G-009 restrictions/theme). This goal deliberately builds only the help-topic slice, |
||||
with the registration/restore API shaped so a composite subshell-definition capability |
||||
can drive it. |
||||
|
||||
## Alternatives considered |
||||
|
||||
- Handler-proc topics declared in config - rejected as the default: stored configuration |
||||
must not be a code-execution vector, especially for restricted subshells (G-003/G-009). |
||||
Text-only content covers the motivating use (subshell-specific guidance); revisit with a |
||||
sandboxing design if real demand appears. |
||||
- Per-subshell complete replacement of the help command itself - rejected: loses the |
||||
registry's guarantee that 'help topics'/'i help' match reality, and every subshell would |
||||
reinvent the overview/fallthrough machinery. |
||||
- Waiting for G-008/G-009 profiles to carry topics as part of themed profiles - not |
||||
required: the registry save/restore is plain data and can precede the theming goals; |
||||
profiles can later bundle topic declarations as one more profile aspect. |
||||
|
||||
## Notes |
||||
|
||||
- Dependencies: G-014 (punk::config toml + named-subshell scoping - the config substrate; |
||||
itself gated on tomlish argdoc work upstream). Beneficial, not required: G-040 (alias |
||||
display folding), G-008/G-009 (profile bundling), G-002/G-010 (non-nested subshells - |
||||
the restore-on-switch semantics should be specified to survive that rework). |
||||
- Seam already in place (punk 0.2.0): ::punk::helptopic::register / resolve / define_docs; |
||||
'help topics' derives from the registry; per-topic punk::args ids follow the |
||||
::punk::helptopic::<topic> convention consumed by 'i help <topic>' subhelp choiceinfo. |
||||
- Related session records: goals/G-040-punkargs-choicealiases.md (choice display folding), |
||||
the 2026-07-08 CHANGELOG entries for punk 0.2.0 (registry) and punk::ns 0.1.1 |
||||
(doc-lookup trace cleanup). |
||||
@ -0,0 +1,112 @@
|
||||
# G-043 Subshell definition plugins: punk.subshell capability composing commandsets, help topics and config defaults |
||||
|
||||
Status: proposed |
||||
Scope: src/modules/punk/cap-999999.0a1.0.tm (+ new punk.subshell handler), src/modules/punk/overlay-999999.0a1.0.tm (commandset composition), src/modules/punk/pluginmgr-0.5.1.tm (discovery/trust layer), src/modules/punk/mix-999999.0a1.0.tm (init wiring precedent), src/modules/punk/repl-999999.0a1.0.tm (subshell entry/exit), src/modules/punk/config-0.1.tm (data-declaration overlap with G-014/G-042) |
||||
Acceptance: a provider package declaring the punk.subshell capability supplies at least a commandset binding (namespace + prefix) and a help-topic set for a named subshell, and entering that subshell composes them (prefixed commands callable, topics in 'help topics'/'i help') with quit/switch-away restoring the parent surface (no leakage); the punk.subshell punk::cap handler validates declarations (malformed declarations vetoed with a useful message); a subshell's commandset composition can equivalently be declared in stored config without a provider package (G-014 substrate), and the existing hardcoded 'dev' CLI composition keeps working unchanged; declarations for capabilities with no registered handler are discoverable (query or report - closing the silent punk.isbogus gap); punk::cap pkg_unregister leaves no stale handler state (the 'destroy api objects?' review resolved); punk::pluginmgr-based discovery/loading of a provider is either demonstrated end-to-end (including .tm module loading in the safe interp) or explicitly deferred with the remaining pluginmgr gaps recorded in the detail file; G-042's registry mechanism is consumed, not duplicated. |
||||
|
||||
## Context |
||||
|
||||
Drafted from the 2026-07-08 code review of the intended plugin facility (conducted while |
||||
reviewing G-042). The codebase already contains a deliberate three-layer plugin stack, |
||||
two-thirds built: |
||||
|
||||
1. Discovery/loading + trust boundary (placeholder): punk::mix::init records the intent - |
||||
"todo: use tcllib pluginmgr to load all modules that provide 'punk.templates'" - |
||||
blocked on tcllib pluginmgr 0.5 bugs (.tm modules vs packages; bug reports submitted |
||||
upstream) and on controlling module/library path ordering in its safe interps, with |
||||
the stated plan "develop punk::pluginmgr to fix these issues". |
||||
punk::pluginmgr-0.5.1.tm is that development's start: a vendored fork of tcllib |
||||
pluginmgr (snit type; safe-interp loading; -pattern/-api/-check/-cmds/-setup contract) |
||||
with one marked divergence (LoadPlugin sources a bare plugin.tcl dropped in a plugin |
||||
path) and the .tm gap still commented in place. |
||||
2. Capability registration/validation (working): punk::cap - in-process, cooperative |
||||
(its doctools position tcllib pluginmgr as "an alternative which uses safe |
||||
interpreters"). Providers declare (capname capdict) pairs via a |
||||
capprovider.registration object; a handler registered for the capability name can |
||||
veto each declaration (pkg_register) and exposes an api_<capname> object. Handlers |
||||
are registered by the application (punk::mix::init), deliberately not at package |
||||
load. punk.templates is the only handled capability. |
||||
3. Capability-specific handler APIs (one real instance): punk::cap::handlers::templates, |
||||
whose pathtype vocabulary (module / adhoc / currentproject* / shellproject* / |
||||
absolute) is the existing pattern for kit-vs-srctree resource resolution. |
||||
|
||||
Commandset composition already exists and is multi-consumer by design: |
||||
punk::overlay::import_commandset rename-imports a commandset namespace's exported |
||||
commands under a prefix into a CLI ensemble, explicitly supporting the same commandset |
||||
serving multiple CLIs simultaneously. Its punk::args documentation records the intent |
||||
this goal absorbs: "This is part of the punk::mix CLI commandset infrastructure - design |
||||
in flux. Todo - .toml configuration files for defining CLI configurations." Today's `dev` |
||||
CLI is composed by hardcoded import_commandset calls in punk::mix::cli::_init |
||||
(catch-guarded optional sets) - the shape a declarative composition replaces. |
||||
|
||||
The user's direction (2026-07-08): support plugins for subshell definitions including |
||||
help, and plugin commandsets that may apply to particular subshells. |
||||
|
||||
## Approach (sketch - to be refined when activated) |
||||
|
||||
Two declaration paths with distinct trust models, one composition mechanism: |
||||
|
||||
- Config path (data): stored configuration (G-014 toml) declares a named subshell's |
||||
composition - which commandset packages to import (with prefix/separator), which help |
||||
topics (G-042 text topics), which config defaults. Config can only NAME already |
||||
installed/locatable packages; requiring/importing them is an explicit trust decision |
||||
equivalent to today's hardcoded init. No code is carried in config (G-042 stance). |
||||
- Plugin path (code): a provider package declares the punk.subshell capability with a |
||||
capdict describing what it offers per subshell name (commandset namespace(s) + prefix, |
||||
help topics via the ::punk::helptopic programmatic API, config defaults). The |
||||
punk.subshell handler validates shape at registration (veto malformed). Providers not |
||||
already trusted arrive via punk::pluginmgr discovery/safe-interp loading; in-process |
||||
registration remains available for providers the app requires directly (the |
||||
punk::cap norm today). |
||||
|
||||
Phases: |
||||
1. punk.subshell capability handler (validation + api object) and the composition step |
||||
at subshell entry/exit: import_commandset into the subshell's command resolution |
||||
scope, register topics, apply config defaults; restore on quit/switch-away. The |
||||
restore semantics should be specified to survive the G-002/G-010 non-nested subshell |
||||
rework (same consideration as G-042's registry save/restore and G-008's state sets). |
||||
2. Config-declared composition (G-014-gated) reusing exactly the same composition step. |
||||
3. punk::cap housekeeping absorbed here: pkg_unregister completing handler cleanup |
||||
(api-object lifecycle), and unhandled-capability discoverability (a query or report |
||||
for declarations that no registered handler accepted - the deliberate punk.isbogus |
||||
demonstration in punk::mix::templates documents the current silence). |
||||
4. punk::pluginmgr integration: .tm loading in the safe interp, controlled module/library |
||||
path ordering, and the api-contract check wired to the punk.subshell registration. |
||||
May be deferred as a whole (acceptance allows it) if the fork needs more work than the |
||||
composition machinery justifies at the time - record remaining gaps here if so. |
||||
|
||||
## Alternatives considered |
||||
|
||||
- Hardcoding per-subshell composition in repl init code (status quo pattern from |
||||
punk::mix::cli::_init) - rejected as the end state: it is exactly what the punk::overlay |
||||
toml todo and the punk::mix::init pluginmgr todo set out to replace. |
||||
- Config-only (no provider packages): insufficient - commandsets are code; config can |
||||
name them but a third-party subshell definition needs a carrier for code plus a trust |
||||
story, which is the capability + pluginmgr stack's purpose. |
||||
- Plugin-only (no config path): rejected - the common case (compose existing local |
||||
commandsets into a project- or task-specific subshell) should not require authoring a |
||||
provider package; data-only declaration must stay first-class. |
||||
- Extending tcllib pluginmgr in place upstream rather than forking - upstream reports are |
||||
filed, but the path-ordering customisation punk needs was already judged (punk::mix::init |
||||
note) to need punk-side control; the fork exists. Re-converge upstream if tcllib takes |
||||
the fixes. |
||||
|
||||
## Notes |
||||
|
||||
- Dependencies/relations: G-042 (help-topic registry API - consumed by this goal), |
||||
G-014 (toml stored config - gates the config path), G-009 (themed profiles - a profile |
||||
is a natural bundle of this goal's composition plus theme/restrictions), G-002/G-010 |
||||
(non-nested subshells - restore-on-switch semantics), G-003 (restricted subshells - |
||||
a restricted subshell composing plugin commandsets needs the expose/hide interaction |
||||
considered), G-033 (visitor binaries - shellproject-anchored resources vs cwd-project |
||||
resources, same anchor question as the templates pathtypes). |
||||
- Rough edges catalogued 2026-07-08 (this goal's acceptance covers the first two): |
||||
punk::cap pkg_unregister "destroy api objects?" review; silent unhandled-capability |
||||
declarations (punk.isbogus); hardcoded _multivendor whitelist in the templates handler |
||||
(not this goal's to fix - noted for the templates/layout update-story work under |
||||
G-012/G-027). |
||||
- The templates handler's registration-time vs call-time path resolution split (and its |
||||
documented staleness edge for long-running shells) is the precedent for deciding when |
||||
a punk.subshell declaration's resources are resolved. |
||||
- Related review record: goals/G-042-subshell-help-topics.md "Relationship to the |
||||
intended plugin facility" section (same 2026-07-08 review). |
||||
Loading…
Reference in new issue