diff --git a/GOALS.md b/GOALS.md index 4d51c650..8184af3f 100644 --- a/GOALS.md +++ b/GOALS.md @@ -296,3 +296,15 @@ Scope: src/modules/punk/args-999999.0a1.0.tm (parse form selection, arg_error/us Detail: goals/G-041-punkargs-form-matching.md Goal: for multi-form definitions punk::args determines which form(s) an argument list matches - parse without -form attempts all permitted forms instead of effectively form 0, -form accepts the documented list-of-forms restriction, and the documentation surface indicates the match ('i after cancel ' presents the cancel form; 's after cancel someid' marks the closest synopsis) - with explicit single-form restriction retained for callers that require it. Acceptance: parsing a multiform definition (after-like fixture) without -form succeeds when the args match exactly one form (the pinned GAP tests in forms.test flip to auto-selected results); an argument list matching no form (or several) produces an error naming the candidate forms rather than a form-0 type error; -form with a list of form names/indices restricts parsing to that subset (currently an 'Expected int 0-N or one of ...' error); 'i ' and synopsis output indicate the best-matching form(s) for supplied args; explicit -form behaviour is unchanged; the full punk::args and punk::ns suites pass. + +### G-042 [proposed] Subshell-declared help topics via punk::config with defined shadowing policy +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) +Detail: goals/G-042-subshell-help-topics.md +Goal: a named subshell can declare its own help topics (name, aliases, summary, text content) in punk::config stored configuration - registered into the ::punk::helptopic registry on subshell entry and removed/restored on exit - so 'help' inside a customised subshell presents that subshell's topics with 'help topics' and 'i help' staying accurate (the registry already regenerates the punk::args definitions), under a defined precedence policy between topics and command-name fallthrough. +Acceptance: a subshell whose configuration declares at least one custom topic shows it in 'help topics' and renders its configured content via 'help ' 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 '/'s ' 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. + +### G-043 [proposed] Subshell definition plugins: punk.subshell capability composing commandsets, help topics and config defaults +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) +Detail: goals/G-043-subshell-definition-plugins.md +Goal: a named subshell's definition - commandset imports (punk::overlay), help topics (the G-042 registry API) and config defaults - can be supplied by provider packages registered through a punk.subshell capability (punk::cap handler validating declarations) and/or declared in stored config (toml per G-014, naming already-installed commandset packages - absorbing punk::overlay's "toml configuration files for defining CLI configurations" todo), with punk::pluginmgr as the discovery/safe-interp trust layer for providers not already trusted - so entering a subshell composes its command surface and help from declarations instead of hardcoded init code. +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. diff --git a/goals/G-042-subshell-help-topics.md b/goals/G-042-subshell-help-topics.md new file mode 100644 index 00000000..32fc1a8f --- /dev/null +++ b/goals/G-042-subshell-help-topics.md @@ -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 ' 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 '/'s ' 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 ) 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..helptopic.] 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 ' / 's ' (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_ 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:: convention consumed by 'i help ' 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). diff --git a/goals/G-043-subshell-definition-plugins.md b/goals/G-043-subshell-definition-plugins.md new file mode 100644 index 00000000..69e71e52 --- /dev/null +++ b/goals/G-043-subshell-definition-plugins.md @@ -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_ 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).