goal-editing policy: proposal-first with user approval; G-038 console-anchor finding + acceptance clause
Policy (GOALS.md maintenance rules, mirrored in root AGENTS.md and goals/AGENTS.md):
- agents apply goal-entry adds/edits only on user request, proposal-first: show the
proposed wording and get explicit approval before writing (replaces "only the user
adds or edits goals" - the user was applying agent-drafted edits by hand anyway)
- suggesting candidate goals is welcome and encouraged when grounded in the work at
hand; a suggestion is a flagged proposal, never a file edit; bulk goal surveys stay
out of bounds
- detail-file updates from user-directed work on a goal proceed without pre-approval,
reported in the completion summary; index stays canonical
- unchanged: achieved-flip on met acceptance (reported), no proposed->active flips
G-038 (user-approved):
- Acceptance gains a post-restart terminal-query clause: a code-interp query (e.g.
'help console') must succeed instead of being refused by the stale settled
can_respond=0 anchor
- detail file records the proven mechanism for the post-restart console failure
(piped phase settles can_respond=0; punkshell.tcl opens CONIN$ as a new channel
leaving the repl thread's stdin as the exhausted pipe; the anchored default console
keeps the dead pair; forced resettle honestly re-settles 0 via layer-1 eof), the
rebind requirements (re-point {in out} AND unsettle), and the hidden-console
repro/regression harness
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
@ -200,4 +200,4 @@ The project version is fully independent of module versions. A module bump (even
- Source-tree build, testing, linting, and file-resolution workflow lives in `src/AGENTS.md`.
- Tcl module authoring conventions live in `src/modules/AGENTS.md` and closer module child docs.
- If AGENTS.md conflicts with CLAUDE.md, AGENTS.md wins.
- Technical project goals live in root `GOALS.md` (index) with optional detail prose in `goals/G-<id>-<slug>.md`. Only the user adds or edits goals. Agents auto-flip a goal to `achieved <date>` when its stated acceptance criterion is met as part of the DOX closeout pass, and must flag `proposed`→`active` transitions in their completion report for user confirmation. See `GOALS.md` for the full workflow, including how to author a new goal when asked.
- Technical project goals live in root `GOALS.md` (index) with optional detail prose in `goals/G-<id>-<slug>.md`. Goals are user-owned: agents add or edit goal entries only at the user's request, proposal-first (show the proposed wording, get explicit approval before writing - see the `GOALS.md` maintenance rules); never on their own initiative. Suggesting candidate goals when work surfaces something goal-worthy is welcome and encouraged - as a flagged proposal, not a file edit. Detail-file updates from user-directed work need only be reported in the completion summary. Agents auto-flip a goal to `achieved <date>` when its stated acceptance criterion is met as part of the DOX closeout pass, and must flag `proposed`→`active` transitions in their completion report for user confirmation. See `GOALS.md` for the full workflow, including how to author a new goal when asked.
- `superseded by G-<id>` — replaced; do not delete the old entry
### Maintenance rules
- Only the user adds or edits goals. Agents must not invent goals.
- An agent whose work satisfies a goal's `Acceptance:` must flip that goal to `achieved <date>` as part of its DOX closeout pass, and report the flip in its completion summary.
- Goals are user-owned. Agents add or edit goal entries only at the user's request or with the user's explicit approval - never on their own initiative, and never in bulk from an agent's own survey of what "should" be goals.
- Suggesting is always allowed and encouraged when grounded in the work at hand: a discovered gap, a recurring manual step, a deferred design decision, or a natural follow-on that fits what is currently being worked on. Flag it as a candidate goal in conversation or the completion report, optionally with a drafted block ready for approval. A suggestion is not an edit - nothing is written to this file or `goals/` until the user approves per the proposal-first rule.
- Proposal-first: before writing a new goal entry or changing an existing entry's contract (title, status tag, Scope, Goal, Acceptance), show the user the proposed wording - the full block for a new goal, the changed clause(s) for an edit - and get explicit approval. If the user already supplied or approved the exact wording this session, apply it and report what was written.
- Exception (sanctioned autonomous edit): an agent whose work satisfies a goal's `Acceptance:` must flip that goal to `achieved <date>` as part of its DOX closeout pass, and report the flip in its completion summary.
- Agents must not flip `proposed` → `active`. They flag it in their completion report for the user to confirm.
- Detail files under `goals/` may be updated without pre-approval when recording findings, decisions, or verification artifacts from work the user directed on that goal or its subject matter; report such updates in the completion summary. The index entry is canonical - a detail edit must never contradict it.
- The `Goal:` line must stay self-contained enough that an agent who skips the detail file still does no harm. Detail files are enrichment, not load-bearing for safety.
- When the achieved section grows past ~30 entries, the oldest are moved to `GOALS-archive.md` and their detail files to `goals/archive/`.
- If a goal cannot be safely summarized in one line, that is a signal it is really two goals — split it.
@ -42,7 +45,7 @@ When the user asks to "write a goal for X" or "help me draft a goal for Y", do t
- **Acceptance:** What is the measurable, verifiable pass/fail criterion an agent can check against? If the user cannot state one, propose 2-3 candidate criteria and ask them to pick or refine.
- **Status:** Default to `proposed` unless the user says it is already in progress (`active`).
- **Detail file?** Only if the goal has non-obvious rationale, a multi-phase plan, alternatives worth recording, or needs more than ~3 lines of prose to state properly. If yes, propose a slug and offer to draft the detail file too. If no, omit the `Detail:` line.
3. Draft the goal block in this file's format and show it to the user for review and edit. Do not commit it as`active` unless the user confirms.
3. Draft the goal block in this file's format and show it to the user for review, applying it only after approval (per the maintenance rules). Do not set it`active` unless the user confirms.
4. If a detail file is warranted and the user approves, create `goals/G-<id>-<slug>.md` using the structure in `goals/AGENTS.md`.
5. Do not delete or rewrite existing goals to make room for a new one. Append with the next free ID.
@ -274,7 +277,7 @@ Acceptance: with a newer package version placed under src/vendorlib_tcl9/<platfo
Goal: when piped stdin ends and app-punkshell opens the interactive console shell, the session continues rather than restarts - the piped phase's codethread/code interp survives (variables, procs, namespaces, loaded packages, cwd, ::errorInfo/::errorCode) and only the input channel and repl reader are renewed - so `'set ::jjj blah' | <punkexe> shell` leaves ::jjj inspectable at the prompt, replacing today's silent fresh-session swap (least-surprise violation; motivating transcripts in the detail file) and obsoleting the standalone piped-error-record mechanism this goal described before its 2026-07-08 rework.
Acceptance: after `'set ::jjj blah;error xxxx' | <punkexe> shell` reaches the interactive prompt: `set ::jjj` returns blah; the xxxx message, errorInfo traceback and errorCode are inspectable (via preserved ::errorInfo if nothing in the handover overwrites it, else a documented record - the chosen mechanism noted in the detail file); a proc defined and a package required during the piped phase remain available; a cwd change from the piped phase persists; a one-line notice at the restart says the session continued from piped input (mentioning the error when the last piped command errored, quiet otherwise); interactive exit/quit teardown afterwards is clean (the G-036 regression harness still passes); PUNK_PIPE_EOF policy semantics and the script subcommand are unchanged; verified on both Tcl generations.
Acceptance: after `'set ::jjj blah;error xxxx' | <punkexe> shell` reaches the interactive prompt: `set ::jjj` returns blah; the xxxx message, errorInfo traceback and errorCode are inspectable (via preserved ::errorInfo if nothing in the handover overwrites it, else a documented record - the chosen mechanism noted in the detail file); a proc defined and a package required during the piped phase remain available; a cwd change from the piped phase persists; a one-line notice at the restart says the session continued from piped input (mentioning the error when the last piped command errored, quiet otherwise); after the restart a terminal query from the code interp succeeds (e.g. `help console` runs its cursor-position test instead of being refused by the stale settled can_respond=0 anchor); interactive exit/quit teardown afterwards is clean (the G-036 regression harness still passes); PUNK_PIPE_EOF policy semantics and the script subcommand are unchanged; verified on both Tcl generations.
### G-039 [proposed] Investigate the orphaned-shell one-core spin on a dead console
Scope: src/modules/punk/repl-999999.0a1.0.tm (console reader/event loop and EOF/error paths), src/modules/punk/console-999999.0a1.0.tm; investigation-first
@ -7,7 +7,8 @@ Holds optional detail prose for goals in the root `GOALS.md` index that need mor
## Ownership
- Files here are owned by the goal authoring workflow described in root `GOALS.md`.
- Only the user adds or edits goals. Agents may draft detail files for user review but must not invent goals.
- Goals are user-owned: agents add or edit goals only at the user's request or with explicit approval, proposal-first for index-entry changes (see the root `GOALS.md` maintenance rules). Agents must not write goals on their own initiative - suggesting candidate goals for user approval is welcome and encouraged.
- Detail files may be updated without pre-approval when recording findings, decisions, or verification artifacts from user-directed work on the goal or its subject matter; report such updates in the completion summary.
- The root `GOALS.md` index entry is the source of truth. If index and detail disagree, the index wins; fix the detail.
Acceptance: after `'set ::jjj blah;error xxxx' | <punkexe> shell` reaches the interactive prompt: `set ::jjj` returns blah; the xxxx message, errorInfo traceback and errorCode are inspectable (via preserved ::errorInfo if nothing in the handover overwrites it, else a documented record - the chosen mechanism noted in the detail file); a proc defined and a package required during the piped phase remain available; a cwd change from the piped phase persists; a one-line notice at the restart says the session continued from piped input (mentioning the error when the last piped command errored, quiet otherwise); interactive exit/quit teardown afterwards is clean (the G-036 regression harness still passes); PUNK_PIPE_EOF policy semantics and the script subcommand are unchanged; verified on both Tcl generations.
Acceptance: after `'set ::jjj blah;error xxxx' | <punkexe> shell` reaches the interactive prompt: `set ::jjj` returns blah; the xxxx message, errorInfo traceback and errorCode are inspectable (via preserved ::errorInfo if nothing in the handover overwrites it, else a documented record - the chosen mechanism noted in the detail file); a proc defined and a package required during the piped phase remain available; a cwd change from the piped phase persists; a one-line notice at the restart says the session continued from piped input (mentioning the error when the last piped command errored, quiet otherwise); after the restart a terminal query from the code interp succeeds (e.g. `help console` runs its cursor-position test instead of being refused by the stale settled can_respond=0 anchor); interactive exit/quit teardown afterwards is clean (the G-036 regression harness still passes); PUNK_PIPE_EOF policy semantics and the script subcommand are unchanged; verified on both Tcl generations.
## Context
@ -21,6 +21,25 @@ did in the code interp - variables, procs, namespaces, package requires, cwd, er
is silently discarded. The user's mental model is "my session continues interactively",
i.e. the same expectation a tclsh user has typing those commands then continuing.
A third symptom class (user report 2026-07-08, mechanism proven same day - see Notes for
the harness): after the restart, `help console` and EVERY terminal query (get_cursor_pos,
dec_get_mode, test_char_width, ...) fail with "console object for 'stdin' 'stdout' is
settled as unable to respond (can_respond=0) - refusing to emit query". Chain:
1. During the piped phase the anchored `default` opunk console ({stdin stdout}) settles
can_respond=0 - correct at the time, stdin is a pipe (punk::console 0.7.1 settling).
2. At EOF, punkshell.tcl (~l.501-517) opens CONIN$ as a NEW channel (name `file...`) and
SetStdHandle's the process stdin handle, but never closes or replaces the repl thread's
Tcl channel `stdin` - it remains the exhausted pipe (chan eof = 1), and the anchored
default console instance still references {stdin stdout}.
3. The fresh codethread's code interp DOES get a real console stdin (new thread std
channels initialise from the process handles), but its queries route (G-007) to the
console-owning repl thread, where the stale anchor refuses them.
4. Recovery is impossible without re-anchoring: `settle_can_respond -force default` in the
owner thread honestly re-settles 0 via layer 1 (input at eof) because the object's
input IS a dead channel. The stale anchor, not just the stale verdict, is the defect -
exactly the gap flagged by the review comment at repl-999999.0a1.0.tm ~l.3168.
Precedent in the codebase: the repl-internal restart path (`repl::reopen_stdin`) is
context-preserving by design - it reuses the live codethread and restarts the repl on the
reopened console channel. Its problem is structural, not conceptual, and this goal should
@ -66,6 +85,16 @@ The caller-driven restart already identified during G-036 as the clean fix direc