From 7250a7de8d974cbecfd06673fc2f06fb45591b46 Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Fri, 16 Oct 2026 22:38:02 -0400 Subject: [PATCH 1/2] docs: preserve accumulated architecture decisions and review records --- .agents/agent-writing.md | 76 + .agents/architect.md | 2 + .agents/architecture-rules.md | 5 + .agents/planner.md | 23 + .agents/product-interface.md | 3 + .reviewer/README.md | 23 + .reviewer/api-selection-pattern-proposal.md | 101 + .reviewer/issue-881/README.md | 97 + .reviewer/issue-881/architecture-review.md | 309 +++ .reviewer/issue-881/assessment.md | 78 + .reviewer/issue-881/capture-runbook.md | 138 ++ .reviewer/issue-881/comparison-matrix.md | 128 + .reviewer/issue-881/fail-entry.md | 1 + .reviewer/issue-881/final-gallery-matrix.md | 175 ++ .reviewer/issue-881/generated-readme.md | 32 + .reviewer/issue-881/image-review-log.md | 35 + .reviewer/issue-881/implementation-plan.md | 39 + .reviewer/issue-881/json-entry.md | 5 + .reviewer/issue-881/permission-entry.md | 1 + .reviewer/issue-881/plan-entry.md | 8 + .reviewer/issue-881/planning-measurement.md | 74 + .../issue-881/pr1-architecture-review.md | 86 + .reviewer/issue-881/pr1-handoff.md | 336 +++ .../issue-881/pr1-implementation-handoff.md | 137 ++ .reviewer/issue-881/pr1-planner-acceptance.md | 76 + .reviewer/issue-881/pr1-planner-review.md | 153 ++ .reviewer/issue-881/pr2-architecture-draft.md | 503 ++++ .../issue-881/pr2-architecture-review.md | 178 ++ ...r2-fatal-precedence-architecture-review.md | 98 + ...atal-precedence-implementation-handback.md | 249 ++ ...fatal-precedence-implementation-handoff.md | 134 + ...pr2-fatal-precedence-planner-acceptance.md | 78 + .../issue-881/pr2-implementation-handback.md | 564 +++++ .../issue-881/pr2-implementation-handoff.md | 348 +++ .../pr2-independent-architecture-review.md | 122 + .../issue-881/pr2-invocation-contract.md | 188 ++ .reviewer/issue-881/pr2-planner-acceptance.md | 154 ++ .reviewer/issue-881/pr2-planner-handoff.md | 352 +++ .reviewer/issue-881/pr2-planner-rereview.md | 189 ++ .reviewer/issue-881/pr2-planner-review.md | 159 ++ .../issue-881/pr2-product-verification.md | 97 + .../pr2-published-architecture-rereview.md | 112 + .../pr2-published-architecture-review.md | 158 ++ .reviewer/issue-881/pr2-source-inspection.md | 310 +++ .../issue-881/pr2-source-presentation.md | 331 +++ .reviewer/issue-881/pr3-history-contract.md | 525 ++++ .../pr3-implementation-handback-r2.md | 330 +++ .../issue-881/pr3-implementation-handback.md | 149 ++ .../issue-881/pr3-implementation-handoff.md | 300 +++ .reviewer/issue-881/pr3-planner-acceptance.md | 50 + .reviewer/issue-881/pr3-planner-handoff.md | 343 +++ .reviewer/issue-881/pr3-planner-review-r2.md | 97 + .reviewer/issue-881/pr3-planner-review.md | 254 ++ .../issue-881/pr3-product-verification.md | 117 + .../pr3-published-architecture-review.md | 132 + .../issue-881/pr3-r2-evidence-correction.md | 82 + .../issue-881/pr4-implementation-handback.md | 199 ++ .reviewer/issue-881/pr4-planner-acceptance.md | 55 + .reviewer/issue-881/pr4-planner-review.md | 126 + .../pr4-published-architecture-review.md | 104 + .reviewer/issue-881/pr886-planner-review.md | 85 + .reviewer/issue-881/pr887-planner-review.md | 49 + .reviewer/issue-881/pr889-planner-review.md | 46 + .reviewer/issue-881/stack-and-evidence.md | 149 ++ .reviewer/issue-881/story-draft.md | 86 + .reviewer/issue-883/README.md | 1081 ++++++++ .reviewer/issue-883/acceptance-proposal.md | 112 + .reviewer/issue-883/architect-handoff.md | 411 ++++ .reviewer/issue-883/architecture-review.md | 991 ++++++++ .reviewer/issue-883/base-refresh.md | 88 + .../issue-883/core-interfaces-proposal.md | 628 +++++ ...enerated-root-syntax-architect-decision.md | 78 + .reviewer/issue-883/implementation-plan.md | 208 ++ .reviewer/issue-883/implementor-handback.md | 415 ++++ .../parse-failure-follow-up-issue.md | 81 + .reviewer/issue-883/planner-handoff.md | 2181 +++++++++++++++++ .../issue-883/pr1-planner-review-05d03afb.md | 88 + .../issue-883/pr1-planner-review-2765a76b.md | 116 + .reviewer/issue-883/pr1-planner-review.md | 133 + ...mission-gate-increment-1-working-review.md | 51 + ...-admission-gate-planner-review-14ebf82d.md | 67 + ...-admission-gate-planner-review-9bb1d465.md | 109 + ...2-admission-pause-a1-architect-decision.md | 146 ++ ...2-admission-pause-a1-implementor-prompt.md | 102 + ...r2-admission-pause-architect-assessment.md | 144 ++ .../pr2-admission-pause-architect-handoff.md | 143 ++ ...-admission-pause-implementation-handoff.md | 292 +++ .../pr2-admission-pause-planner-handoff.md | 136 + ...admission-pause-planner-review-29fb689f.md | 96 + ...admission-pause-planner-review-cf3c6526.md | 63 + ...admission-pause-planner-review-f156f2c3.md | 126 + ...dmission-pause-startup-architect-return.md | 83 + ...pr2-admission-prefix-implementor-prompt.md | 89 + ...dmission-prefix-planner-review-32bbd7cc.md | 95 + ...on-prefix-settlement-implementor-prompt.md | 81 + ...sion-settlement-planner-review-55e5d4a7.md | 98 + ...pr2-chat-flow-planner-addendum-d634b28b.md | 148 ++ ...-configuration-agent-implementor-prompt.md | 115 + ...uration-implementor-correction-57773de0.md | 74 + ...uration-implementor-correction-d4f38f6e.md | 94 + ...uration-implementor-correction-ef68c71c.md | 61 + ...onfiguration-p2-planner-review-08c95ca2.md | 68 + ...2-configuration-planner-review-00a19527.md | 102 + ...2-configuration-planner-review-2cd17192.md | 109 + ...2-configuration-planner-review-57773de0.md | 128 + ...2-configuration-planner-review-81523318.md | 91 + ...2-configuration-planner-review-d4f38f6e.md | 179 ++ ...2-configuration-planner-review-ef68c71c.md | 141 ++ ...nfiguration-precommit-result-correction.md | 49 + ...tion-request-routing-architect-decision.md | 523 ++++ ...ration-request-routing-architect-return.md | 138 ++ ...ration-result-architect-review-08c95ca2.md | 127 + ...nfiguration-result-implementor-handback.md | 125 + .../pr2-configuration-staged-inspection.md | 37 + ...ion-writer-progress-correction-bb60ca35.md | 107 + ...ontrols-profile-planner-review-80a2c4b6.md | 93 + ...ontrols-profile-planner-review-dc87c5fd.md | 118 + ...pr2-core-syntax-planner-review-66d330dd.md | 129 + .../pr2-correction-planner-review-8b4efe91.md | 63 + ...ation-policy-architect-handoff-b01bbe6c.md | 132 + .../pr2-direct-provider-architect-handoff.md | 378 +++ ...rect-provider-architect-review-004de839.md | 177 ++ ...r2-direct-provider-implementor-handback.md | 288 +++ .../pr2-direct-provider-implementor-prompt.md | 137 ++ .../pr2-direct-provider-planner-handoff.md | 356 +++ .../pr2-direct-provider-planner-prompt.md | 88 + ...direct-provider-planner-review-004de839.md | 152 ++ ...2-documentation-planner-review-8be2d2bc.md | 95 + ...2-documentation-planner-review-91eb10bd.md | 106 + ...r2-elicit-owner-planner-review-3d363e38.md | 89 + .../pr2-elicit-pinning-planner-handoff.md | 90 + ...-elicit-pinning-planner-review-32fc3c2a.md | 67 + ...-environment-plugins-implementor-prompt.md | 70 + .../pr2-feedback-implementor-prompt.md | 126 + .../pr2-feedback-planner-review-2fddcf6b.md | 88 + .../pr2-feedback-planner-review-97f8cb79.md | 104 + .../pr2-feedback-planner-review-f5b60c99.md | 113 + ...r2-feedback-receipts-implementor-prompt.md | 94 + .../pr2-guidance-padding-planner-amendment.md | 179 ++ .../pr2-guide-examples-implementor-prompt.md | 83 + .../pr2-guide-planner-review-9a9d2a04.md | 96 + .../pr2-guide-planner-review-c8c689e7.md | 105 + .../issue-883/pr2-latency-39c24f37-report.md | 72 + ...r2-metadata-delivery-implementor-prompt.md | 82 + .../pr2-metadata-planner-review-8b45ee24.md | 75 + .../pr2-metadata-planner-review-c5bec458.md | 87 + ...mounted-implementor-correction-86debcb9.md | 133 + ...mounted-initial-focus-m1-flake-39c24f37.md | 41 + ...r2-mounted-permission-u2-flake-a438905f.md | 78 + .../pr2-mounted-planner-review-86debcb9.md | 122 + .../pr2-mounted-planner-review-a438905f.md | 136 + .../pr2-name-planner-review-6e3a7b37.md | 30 + .../pr2-owner-failures-implementor-prompt.md | 92 + .../pr2-owner-planner-review-94acc66c.md | 90 + .../pr2-owner-planner-review-e3aaa61e.md | 144 ++ ...-pane-width-guidance-planner-assessment.md | 99 + .../pr2-pane-width-implementor-conflict.md | 156 ++ ...pr2-pending-submission-product-decision.md | 115 + ...preview-implementor-correction-b44098ff.md | 110 + ...preview-implementor-correction-f8b4e035.md | 92 + .../pr2-preview-planner-review-10b17a40.md | 126 + .../pr2-preview-planner-review-b44098ff.md | 170 ++ .../pr2-preview-planner-review-f8b4e035.md | 147 ++ ...projection-root-planner-review-fdf67b04.md | 130 + ...rojector-output-planner-review-1ba2c48a.md | 129 + ...uestion-implementor-correction-2f3af332.md | 130 + .../pr2-question-planner-review-2f3af332.md | 149 ++ .../pr2-question-planner-review-bb60ca35.md | 124 + ...2-r2-completion-reconciliation-004de839.md | 143 ++ .../pr2-reads-planner-review-356f1b51.md | 64 + .../pr2-reads-planner-review-68d10d7d.md | 118 + ...cording-implementor-correction-8fec6316.md | 58 + .../pr2-recording-planner-review-8fec6316.md | 100 + .../pr2-recording-planner-review-a66c5d8a.md | 63 + ...very-creation-policy-architect-decision.md | 285 +++ ...covery-creation-policy-architect-return.md | 51 + .../pr2-recovery-implementor-correction.md | 125 + ...essage-correlation-architect-assessment.md | 112 + ...-message-correlation-architect-decision.md | 157 ++ ...ry-message-correlation-architect-return.md | 61 + ...ery-message-correlation-planner-handoff.md | 178 ++ ...2-recovery-message-vocabulary-decisions.md | 75 + ...2-recovery-message-vocabulary-interview.md | 175 ++ ...-message-vocabulary-planner-disposition.md | 73 + .../pr2-recovery-planner-review-14ee0d8e.md | 141 ++ .../pr2-recovery-planner-review-68547603.md | 93 + .../pr2-recovery-planner-review-87b25a40.md | 121 + .../pr2-recovery-turn-vocabulary-decisions.md | 88 + .../pr2-recovery-turn-vocabulary-interview.md | 147 ++ ...recovery-unknown-implementor-correction.md | 65 + .../pr2-repl-lifecycle-l2-flake-10b17a40.md | 83 + ...pl-validation-architect-review-a49229e9.md | 82 + ...r2-repl-validation-implementor-handback.md | 149 ++ .../pr2-repl-validation-planner-handoff.md | 92 + ...-evidence-implementor-handback-25227d38.md | 116 + .../pr2-retained-requests-name-interview.md | 73 + ...oot-documentation-wiring-planner-review.md | 112 + .../pr2-root-documentation-wiring-proposal.md | 105 + ...root-evaluation-planner-review-01abab27.md | 88 + ...root-evaluation-planner-review-3e6329f7.md | 113 + ...root-evaluation-planner-review-ddf3f6f9.md | 175 ++ .../pr2-section2-planner-review-43d53df7.md | 62 + .../issue-883/pr2-section2-planner-review.md | 158 ++ ...ection5-configuration-architect-handoff.md | 127 + ...ction5-configuration-implementor-prompt.md | 108 + ...-section5-configuration-planner-handoff.md | 398 +++ ...2-section5-configuration-planner-prompt.md | 63 + ...ection5-configuration-product-decisions.md | 50 + ...configuration-timing-architect-decision.md | 279 +++ ...ion5-mounted-message-implementor-prompt.md | 80 + ...ection5-mounted-message-planner-handoff.md | 315 +++ ...pr2-section5-preview-architect-decision.md | 324 +++ .../pr2-section5-preview-architect-handoff.md | 211 ++ .../pr2-section5-preview-architect-prompt.md | 46 + ...pr2-section5-preview-implementor-prompt.md | 155 ++ .../pr2-section5-preview-planner-handoff.md | 377 +++ .../pr2-section5-preview-planner-prompt.md | 60 + ...ion5-question-drawer-implementor-prompt.md | 74 + ...ection5-question-drawer-planner-handoff.md | 292 +++ ...5-selection-routing-implementor-handoff.md | 170 ++ ...r2-section5-sessions-architect-decision.md | 376 +++ ...pr2-section5-sessions-architect-handoff.md | 205 ++ .../pr2-section5-sessions-architect-prompt.md | 29 + ...r2-section5-sessions-implementor-prompt.md | 124 + .../pr2-section5-sessions-planner-handoff.md | 399 +++ .../pr2-section5-sessions-planner-prompt.md | 55 + ...election-example-implementor-correction.md | 48 + .../pr2-selection-planner-review-1d373a61.md | 86 + .../pr2-selection-planner-review-b01bbe6c.md | 31 + ...configuration-architect-review-ef68c71c.md | 121 + ...sion-configuration-implementor-handback.md | 234 ++ ...nfiguration-placement-vocabulary-return.md | 154 ++ ...2-session-configuration-planner-handoff.md | 504 ++++ ...ion-recording-architect-review-8fec6316.md | 114 + ...-session-recording-implementor-handback.md | 214 ++ .../pr2-session-recording-planner-handoff.md | 105 + ...ession-rename-architect-review-9f15dc51.md | 80 + ...pr2-session-rename-implementor-handback.md | 167 ++ .../pr2-session-rename-implementor-handoff.md | 157 ++ .../pr2-session-rename-planner-disposition.md | 183 ++ ...-session-rename-planner-review-9f15dc51.md | 89 + ...2-session-vocabulary-architect-decision.md | 389 +++ ...r2-session-vocabulary-architect-handoff.md | 247 ++ ...essions-implementor-correction-4ee4f448.md | 139 ++ ...essions-implementor-correction-5ce2e2d2.md | 112 + .../pr2-sessions-planner-review-4ee4f448.md | 224 ++ .../pr2-sessions-planner-review-5ce2e2d2.md | 199 ++ .../pr2-sessions-planner-review-ab681d4a.md | 124 + ...ick-message-composer-implementor-prompt.md | 128 + ...ekick-message-composer-planner-addendum.md | 206 ++ ...r2-sidekick-pane-width-planner-addendum.md | 143 ++ ...iveness-implementor-correction-13c4900d.md | 73 + ...ick-responsiveness-implementor-handback.md | 215 ++ ...ekick-responsiveness-implementor-prompt.md | 163 ++ ...-responsiveness-planner-review-13c4900d.md | 147 ++ ...-responsiveness-planner-review-25227d38.md | 87 + .../pr2-stop-planner-review-01990ca4.md | 82 + .../pr2-stop-planner-review-88c482b7.md | 108 + .../pr2-stop-startup-implementor-prompt.md | 104 + ...pletion-implementor-correction-39c24f37.md | 104 + ...pletion-implementor-correction-d634b28b.md | 148 ++ ...pletion-implementor-handback-correction.md | 269 ++ ...erminal-completion-implementor-handback.md | 245 ++ ...-terminal-completion-implementor-prompt.md | 133 + ...pr2-terminal-completion-planner-handoff.md | 342 +++ ...inal-completion-planner-review-39c24f37.md | 160 ++ ...inal-completion-planner-review-d634b28b.md | 160 ++ .../pr2-validation-planner-review-a49229e9.md | 81 + .reviewer/issue-883/pr890-architect-review.md | 128 + .../issue-883/pr890-planner-correction.md | 79 + .../pr890-planner-review-79d404d0.md | 88 + .reviewer/issue-883/pr890-planner-review.md | 21 + ...890-pr921-delivery-implementor-handback.md | 336 +++ ...-pr921-delivery-planner-return-c10a2062.md | 110 + ...21-final-delivery-continuation-c2536dd0.md | 82 + ...l-delivery-implementor-handoff-27da762b.md | 247 ++ ...921-main-integration-architect-decision.md | 469 ++++ ...r921-main-integration-architect-handoff.md | 180 ++ ...21-main-integration-architect-interview.md | 121 + ...921-main-integration-implementor-prompt.md | 93 + ...-pr921-main-integration-planner-handoff.md | 354 +++ ...in-integration-planner-release-d4b0e326.md | 143 ++ .../issue-883/pr890-rebase-attempt-finding.md | 119 + ...-replacement-correction-prompt-fdcef428.md | 46 + ...890-replacement-planner-review-85da74b9.md | 86 + ...890-replacement-planner-review-fdcef428.md | 173 ++ ...ement-pr1-implementor-handback-85da74b9.md | 270 ++ ...ement-pr1-implementor-handback-fdcef428.md | 181 ++ ...eedback-scope-architect-return-940249af.md | 202 ++ .../pr921-architect-review-d906c636.md | 160 ++ ...921-bindings-correction-review-ff0e52c6.md | 28 + ...y-padding-implementor-conflict-27da762b.md | 181 ++ ...adding-width-planner-amendment-27da762b.md | 104 + ...gure-exit-implementor-handback-c2536dd0.md | 143 ++ ...configure-exit-planner-handoff-6ca23952.md | 124 + ...-configure-exit-planner-review-c2536dd0.md | 72 + ...21-control-only-planner-review-2ac3cb28.md | 99 + ...ol-only-recheck-planner-return-fd62f65f.md | 77 + ...control-only-replies-architect-decision.md | 151 ++ ...y-replies-implementor-handback-2ac3cb28.md | 152 ++ ...ontrol-only-replies-implementor-handoff.md | 108 + .../pr921-conversation-labels-assessment.md | 68 + .../pr921-delivery-continuation-7e7ffd27.md | 89 + ...ity-evidence-correction-prompt-f83e3554.md | 32 + ...orical-identity-planner-review-d4b0e326.md | 79 + ...orical-identity-planner-review-f83e3554.md | 118 + ...-submission-identity-implementor-prompt.md | 22 + ...cal-submission-identity-planner-handoff.md | 189 ++ ...r921-history-self-stack-review-d906c636.md | 63 + ...pane-tabs-top-spacing-planner-amendment.md | 111 + .../pr921-implementor-handback-940249af.md | 122 + .../pr921-implementor-handback-d4b0e326.md | 96 + .../pr921-implementor-handback-f83e3554.md | 166 ++ .../pr921-implementor-handback-ff0e52c6.md | 150 ++ .../pr921-isolated-implementor-handoff.md | 208 ++ ...ding-colors-implementor-return-27da762b.md | 134 + ...ing-colors-planner-disposition-27da762b.md | 41 + ...header-colors-planner-addendum-27da762b.md | 126 + .../pr921-padding-planner-review-6ca23952.md | 110 + ...ng-width-approved-continuation-27da762b.md | 92 + ...ing-width-implementor-handback-6ca23952.md | 136 + ...ailure-status-architect-return-940249af.md | 132 + .../pr921-pending-work-implementor-handoff.md | 536 ++++ ...g-measurement-crash-assessment-ff0e52c6.md | 94 + ...-replacement-correction-prompt-5a3d32bd.md | 79 + ...-replacement-correction-prompt-ed202610.md | 57 + ...replacement-independent-review-ed202610.md | 46 + ...pr921-replacement-planner-pass-7613cddf.md | 90 + ...921-replacement-planner-review-5a3d32bd.md | 175 ++ ...921-replacement-planner-review-7613cddf.md | 103 + ...921-replacement-planner-review-ed202610.md | 124 + ...ement-pr2-implementor-handback-5a3d32bd.md | 216 ++ ...ement-pr2-implementor-handback-ed202610.md | 124 + ...ment-pr2-verification-handback-7613cddf.md | 75 + .reviewer/issue-883/pr921-review-d906c636.md | 125 + ...d-body-padding-planner-handoff-27da762b.md | 189 ++ .../pr921-sidekick-diagnostics-followups.md | 22 + .../pr921-task-a-planner-review-940249af.md | 77 + ...1-ui-feedback-sessions-history-sidekick.md | 190 ++ ...ui-headers-continuation-prompt-7613cddf.md | 53 + ...ers-guidance-planner-amendment-7613cddf.md | 158 ++ ...i-headers-implementor-conflict-7613cddf.md | 194 ++ ...i-headers-implementor-handback-27da762b.md | 147 ++ ...921-ui-headers-planner-handoff-7613cddf.md | 181 ++ ...r921-ui-headers-planner-review-27da762b.md | 91 + .reviewer/issue-883/remaining-architecture.md | 948 +++++++ .../root-documentation-boundary-interview.md | 192 ++ .../root-evaluation-architect-handoff.md | 224 ++ .../root-evaluation-planner-handoff.md | 296 +++ .../sidekick-instructions-proposal.md | 206 ++ .../sidekick-language-primer-proposal.md | 215 ++ .reviewer/issue-883/storage-contract.md | 210 ++ .../issue-883/syntax-discovery-amendment.md | 172 ++ .reviewer/issue-932/api-interview.md | 76 + .reviewer/pr920-description/after.md | 107 + .reviewer/pr920-description/before.md | 120 + .../MANIFEST.md | 53 + ...repository-pr-stack-architecture-review.md | 355 +++ .../upstream-repository-pr-stack-plan.md | 92 + ...sitory-pr1-architecture-review-1f43f26f.md | 203 ++ ...sitory-pr1-architecture-review-2b475121.md | 127 + ...pr1-contextual-installer-plan-amendment.md | 40 + ...sitory-pr1-file-dir-implementor-handoff.md | 267 ++ ...-repository-pr1-planner-review-1f43f26f.md | 68 + ...-repository-pr1-planner-review-2b475121.md | 69 + ...-repository-pr1-planner-review-e5f095bf.md | 75 + ...-prerequisite-consumer-integration-note.md | 100 + ...ream-repository-prerequisite-stack-plan.md | 236 ++ ...tory-prerequisite-stack-planner-handoff.md | 184 ++ ...ory-prerequisite-u1-implementor-handoff.md | 146 ++ ...erequisite-u3-architect-review-ac466780.md | 55 + ...ory-prerequisite-u3-implementor-handoff.md | 180 ++ ...uisite-u3-implementor-revision-ac466780.md | 213 ++ ...tream-repository-prerequisite-u3-landed.md | 18 + ...-plan-named-lookup-architecture-request.md | 75 + ...an-named-lookup-architecture-resolution.md | 47 + ...requisite-u3-plan-named-lookup-proposal.md | 76 + ...prerequisite-u3-planner-review-ac466780.md | 59 + ...pository-prerequisite-u3-planner-status.md | 60 + ...tory-prerequisite-u3-syntax-a2-proposal.md | 85 + ...equisite-u3-syntax-architecture-request.md | 80 + ...isite-u3-syntax-architecture-resolution.md | 50 + ...ory-prerequisite-u4-implementor-handoff.md | 221 ++ ...tory-prerequisite-u4-implementor-prompt.md | 27 + ...pository-prerequisite-u4-planner-status.md | 33 + ...ository-reusable-interface-prerequisite.md | 824 +++++++ .../implementor-revision-prompt.md | 25 + .../planner-review.md | 67 + .../implementor-revision-prompt.md | 22 + .../planner-review.md | 73 + .../planner-review.md | 102 + .reviewer/upstream-u4-status.md | 9 + ...pository-prerequisite-u4-landed-receipt.md | 29 + ...ory-prerequisite-u5-implementor-handoff.md | 460 ++++ ...tory-prerequisite-u5-implementor-prompt.md | 50 + ...pository-prerequisite-u5-planner-status.md | 75 + .../implementor-revision-prompt.md | 25 + .../planner-review.md | 79 + .../architect-review.md | 76 + .../planner-review.md | 85 + .../implementor-revision-prompt.md | 27 + .../planner-review.md | 102 + AGENTS.md | 8 + architecture.md | 48 +- 404 files changed, 60800 insertions(+), 6 deletions(-) create mode 100644 .agents/agent-writing.md create mode 100644 .reviewer/README.md create mode 100644 .reviewer/api-selection-pattern-proposal.md create mode 100644 .reviewer/issue-881/README.md create mode 100644 .reviewer/issue-881/architecture-review.md create mode 100644 .reviewer/issue-881/assessment.md create mode 100644 .reviewer/issue-881/capture-runbook.md create mode 100644 .reviewer/issue-881/comparison-matrix.md create mode 100644 .reviewer/issue-881/fail-entry.md create mode 100644 .reviewer/issue-881/final-gallery-matrix.md create mode 100644 .reviewer/issue-881/generated-readme.md create mode 100644 .reviewer/issue-881/image-review-log.md create mode 100644 .reviewer/issue-881/implementation-plan.md create mode 100644 .reviewer/issue-881/json-entry.md create mode 100644 .reviewer/issue-881/permission-entry.md create mode 100644 .reviewer/issue-881/plan-entry.md create mode 100644 .reviewer/issue-881/planning-measurement.md create mode 100644 .reviewer/issue-881/pr1-architecture-review.md create mode 100644 .reviewer/issue-881/pr1-handoff.md create mode 100644 .reviewer/issue-881/pr1-implementation-handoff.md create mode 100644 .reviewer/issue-881/pr1-planner-acceptance.md create mode 100644 .reviewer/issue-881/pr1-planner-review.md create mode 100644 .reviewer/issue-881/pr2-architecture-draft.md create mode 100644 .reviewer/issue-881/pr2-architecture-review.md create mode 100644 .reviewer/issue-881/pr2-fatal-precedence-architecture-review.md create mode 100644 .reviewer/issue-881/pr2-fatal-precedence-implementation-handback.md create mode 100644 .reviewer/issue-881/pr2-fatal-precedence-implementation-handoff.md create mode 100644 .reviewer/issue-881/pr2-fatal-precedence-planner-acceptance.md create mode 100644 .reviewer/issue-881/pr2-implementation-handback.md create mode 100644 .reviewer/issue-881/pr2-implementation-handoff.md create mode 100644 .reviewer/issue-881/pr2-independent-architecture-review.md create mode 100644 .reviewer/issue-881/pr2-invocation-contract.md create mode 100644 .reviewer/issue-881/pr2-planner-acceptance.md create mode 100644 .reviewer/issue-881/pr2-planner-handoff.md create mode 100644 .reviewer/issue-881/pr2-planner-rereview.md create mode 100644 .reviewer/issue-881/pr2-planner-review.md create mode 100644 .reviewer/issue-881/pr2-product-verification.md create mode 100644 .reviewer/issue-881/pr2-published-architecture-rereview.md create mode 100644 .reviewer/issue-881/pr2-published-architecture-review.md create mode 100644 .reviewer/issue-881/pr2-source-inspection.md create mode 100644 .reviewer/issue-881/pr2-source-presentation.md create mode 100644 .reviewer/issue-881/pr3-history-contract.md create mode 100644 .reviewer/issue-881/pr3-implementation-handback-r2.md create mode 100644 .reviewer/issue-881/pr3-implementation-handback.md create mode 100644 .reviewer/issue-881/pr3-implementation-handoff.md create mode 100644 .reviewer/issue-881/pr3-planner-acceptance.md create mode 100644 .reviewer/issue-881/pr3-planner-handoff.md create mode 100644 .reviewer/issue-881/pr3-planner-review-r2.md create mode 100644 .reviewer/issue-881/pr3-planner-review.md create mode 100644 .reviewer/issue-881/pr3-product-verification.md create mode 100644 .reviewer/issue-881/pr3-published-architecture-review.md create mode 100644 .reviewer/issue-881/pr3-r2-evidence-correction.md create mode 100644 .reviewer/issue-881/pr4-implementation-handback.md create mode 100644 .reviewer/issue-881/pr4-planner-acceptance.md create mode 100644 .reviewer/issue-881/pr4-planner-review.md create mode 100644 .reviewer/issue-881/pr4-published-architecture-review.md create mode 100644 .reviewer/issue-881/pr886-planner-review.md create mode 100644 .reviewer/issue-881/pr887-planner-review.md create mode 100644 .reviewer/issue-881/pr889-planner-review.md create mode 100644 .reviewer/issue-881/stack-and-evidence.md create mode 100644 .reviewer/issue-881/story-draft.md create mode 100644 .reviewer/issue-883/README.md create mode 100644 .reviewer/issue-883/acceptance-proposal.md create mode 100644 .reviewer/issue-883/architect-handoff.md create mode 100644 .reviewer/issue-883/architecture-review.md create mode 100644 .reviewer/issue-883/base-refresh.md create mode 100644 .reviewer/issue-883/core-interfaces-proposal.md create mode 100644 .reviewer/issue-883/generated-root-syntax-architect-decision.md create mode 100644 .reviewer/issue-883/implementation-plan.md create mode 100644 .reviewer/issue-883/implementor-handback.md create mode 100644 .reviewer/issue-883/parse-failure-follow-up-issue.md create mode 100644 .reviewer/issue-883/planner-handoff.md create mode 100644 .reviewer/issue-883/pr1-planner-review-05d03afb.md create mode 100644 .reviewer/issue-883/pr1-planner-review-2765a76b.md create mode 100644 .reviewer/issue-883/pr1-planner-review.md create mode 100644 .reviewer/issue-883/pr2-admission-gate-increment-1-working-review.md create mode 100644 .reviewer/issue-883/pr2-admission-gate-planner-review-14ebf82d.md create mode 100644 .reviewer/issue-883/pr2-admission-gate-planner-review-9bb1d465.md create mode 100644 .reviewer/issue-883/pr2-admission-pause-a1-architect-decision.md create mode 100644 .reviewer/issue-883/pr2-admission-pause-a1-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-admission-pause-architect-assessment.md create mode 100644 .reviewer/issue-883/pr2-admission-pause-architect-handoff.md create mode 100644 .reviewer/issue-883/pr2-admission-pause-implementation-handoff.md create mode 100644 .reviewer/issue-883/pr2-admission-pause-planner-handoff.md create mode 100644 .reviewer/issue-883/pr2-admission-pause-planner-review-29fb689f.md create mode 100644 .reviewer/issue-883/pr2-admission-pause-planner-review-cf3c6526.md create mode 100644 .reviewer/issue-883/pr2-admission-pause-planner-review-f156f2c3.md create mode 100644 .reviewer/issue-883/pr2-admission-pause-startup-architect-return.md create mode 100644 .reviewer/issue-883/pr2-admission-prefix-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-admission-prefix-planner-review-32bbd7cc.md create mode 100644 .reviewer/issue-883/pr2-admission-prefix-settlement-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-admission-settlement-planner-review-55e5d4a7.md create mode 100644 .reviewer/issue-883/pr2-chat-flow-planner-addendum-d634b28b.md create mode 100644 .reviewer/issue-883/pr2-configuration-agent-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-configuration-implementor-correction-57773de0.md create mode 100644 .reviewer/issue-883/pr2-configuration-implementor-correction-d4f38f6e.md create mode 100644 .reviewer/issue-883/pr2-configuration-implementor-correction-ef68c71c.md create mode 100644 .reviewer/issue-883/pr2-configuration-p2-planner-review-08c95ca2.md create mode 100644 .reviewer/issue-883/pr2-configuration-planner-review-00a19527.md create mode 100644 .reviewer/issue-883/pr2-configuration-planner-review-2cd17192.md create mode 100644 .reviewer/issue-883/pr2-configuration-planner-review-57773de0.md create mode 100644 .reviewer/issue-883/pr2-configuration-planner-review-81523318.md create mode 100644 .reviewer/issue-883/pr2-configuration-planner-review-d4f38f6e.md create mode 100644 .reviewer/issue-883/pr2-configuration-planner-review-ef68c71c.md create mode 100644 .reviewer/issue-883/pr2-configuration-precommit-result-correction.md create mode 100644 .reviewer/issue-883/pr2-configuration-request-routing-architect-decision.md create mode 100644 .reviewer/issue-883/pr2-configuration-request-routing-architect-return.md create mode 100644 .reviewer/issue-883/pr2-configuration-result-architect-review-08c95ca2.md create mode 100644 .reviewer/issue-883/pr2-configuration-result-implementor-handback.md create mode 100644 .reviewer/issue-883/pr2-configuration-staged-inspection.md create mode 100644 .reviewer/issue-883/pr2-configuration-writer-progress-correction-bb60ca35.md create mode 100644 .reviewer/issue-883/pr2-controls-profile-planner-review-80a2c4b6.md create mode 100644 .reviewer/issue-883/pr2-controls-profile-planner-review-dc87c5fd.md create mode 100644 .reviewer/issue-883/pr2-core-syntax-planner-review-66d330dd.md create mode 100644 .reviewer/issue-883/pr2-correction-planner-review-8b4efe91.md create mode 100644 .reviewer/issue-883/pr2-creation-policy-architect-handoff-b01bbe6c.md create mode 100644 .reviewer/issue-883/pr2-direct-provider-architect-handoff.md create mode 100644 .reviewer/issue-883/pr2-direct-provider-architect-review-004de839.md create mode 100644 .reviewer/issue-883/pr2-direct-provider-implementor-handback.md create mode 100644 .reviewer/issue-883/pr2-direct-provider-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-direct-provider-planner-handoff.md create mode 100644 .reviewer/issue-883/pr2-direct-provider-planner-prompt.md create mode 100644 .reviewer/issue-883/pr2-direct-provider-planner-review-004de839.md create mode 100644 .reviewer/issue-883/pr2-documentation-planner-review-8be2d2bc.md create mode 100644 .reviewer/issue-883/pr2-documentation-planner-review-91eb10bd.md create mode 100644 .reviewer/issue-883/pr2-elicit-owner-planner-review-3d363e38.md create mode 100644 .reviewer/issue-883/pr2-elicit-pinning-planner-handoff.md create mode 100644 .reviewer/issue-883/pr2-elicit-pinning-planner-review-32fc3c2a.md create mode 100644 .reviewer/issue-883/pr2-environment-plugins-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-feedback-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-feedback-planner-review-2fddcf6b.md create mode 100644 .reviewer/issue-883/pr2-feedback-planner-review-97f8cb79.md create mode 100644 .reviewer/issue-883/pr2-feedback-planner-review-f5b60c99.md create mode 100644 .reviewer/issue-883/pr2-feedback-receipts-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-guidance-padding-planner-amendment.md create mode 100644 .reviewer/issue-883/pr2-guide-examples-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-guide-planner-review-9a9d2a04.md create mode 100644 .reviewer/issue-883/pr2-guide-planner-review-c8c689e7.md create mode 100644 .reviewer/issue-883/pr2-latency-39c24f37-report.md create mode 100644 .reviewer/issue-883/pr2-metadata-delivery-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-metadata-planner-review-8b45ee24.md create mode 100644 .reviewer/issue-883/pr2-metadata-planner-review-c5bec458.md create mode 100644 .reviewer/issue-883/pr2-mounted-implementor-correction-86debcb9.md create mode 100644 .reviewer/issue-883/pr2-mounted-initial-focus-m1-flake-39c24f37.md create mode 100644 .reviewer/issue-883/pr2-mounted-permission-u2-flake-a438905f.md create mode 100644 .reviewer/issue-883/pr2-mounted-planner-review-86debcb9.md create mode 100644 .reviewer/issue-883/pr2-mounted-planner-review-a438905f.md create mode 100644 .reviewer/issue-883/pr2-name-planner-review-6e3a7b37.md create mode 100644 .reviewer/issue-883/pr2-owner-failures-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-owner-planner-review-94acc66c.md create mode 100644 .reviewer/issue-883/pr2-owner-planner-review-e3aaa61e.md create mode 100644 .reviewer/issue-883/pr2-pane-width-guidance-planner-assessment.md create mode 100644 .reviewer/issue-883/pr2-pane-width-implementor-conflict.md create mode 100644 .reviewer/issue-883/pr2-pending-submission-product-decision.md create mode 100644 .reviewer/issue-883/pr2-preview-implementor-correction-b44098ff.md create mode 100644 .reviewer/issue-883/pr2-preview-implementor-correction-f8b4e035.md create mode 100644 .reviewer/issue-883/pr2-preview-planner-review-10b17a40.md create mode 100644 .reviewer/issue-883/pr2-preview-planner-review-b44098ff.md create mode 100644 .reviewer/issue-883/pr2-preview-planner-review-f8b4e035.md create mode 100644 .reviewer/issue-883/pr2-projection-root-planner-review-fdf67b04.md create mode 100644 .reviewer/issue-883/pr2-projector-output-planner-review-1ba2c48a.md create mode 100644 .reviewer/issue-883/pr2-question-implementor-correction-2f3af332.md create mode 100644 .reviewer/issue-883/pr2-question-planner-review-2f3af332.md create mode 100644 .reviewer/issue-883/pr2-question-planner-review-bb60ca35.md create mode 100644 .reviewer/issue-883/pr2-r2-completion-reconciliation-004de839.md create mode 100644 .reviewer/issue-883/pr2-reads-planner-review-356f1b51.md create mode 100644 .reviewer/issue-883/pr2-reads-planner-review-68d10d7d.md create mode 100644 .reviewer/issue-883/pr2-recording-implementor-correction-8fec6316.md create mode 100644 .reviewer/issue-883/pr2-recording-planner-review-8fec6316.md create mode 100644 .reviewer/issue-883/pr2-recording-planner-review-a66c5d8a.md create mode 100644 .reviewer/issue-883/pr2-recovery-creation-policy-architect-decision.md create mode 100644 .reviewer/issue-883/pr2-recovery-creation-policy-architect-return.md create mode 100644 .reviewer/issue-883/pr2-recovery-implementor-correction.md create mode 100644 .reviewer/issue-883/pr2-recovery-message-correlation-architect-assessment.md create mode 100644 .reviewer/issue-883/pr2-recovery-message-correlation-architect-decision.md create mode 100644 .reviewer/issue-883/pr2-recovery-message-correlation-architect-return.md create mode 100644 .reviewer/issue-883/pr2-recovery-message-correlation-planner-handoff.md create mode 100644 .reviewer/issue-883/pr2-recovery-message-vocabulary-decisions.md create mode 100644 .reviewer/issue-883/pr2-recovery-message-vocabulary-interview.md create mode 100644 .reviewer/issue-883/pr2-recovery-message-vocabulary-planner-disposition.md create mode 100644 .reviewer/issue-883/pr2-recovery-planner-review-14ee0d8e.md create mode 100644 .reviewer/issue-883/pr2-recovery-planner-review-68547603.md create mode 100644 .reviewer/issue-883/pr2-recovery-planner-review-87b25a40.md create mode 100644 .reviewer/issue-883/pr2-recovery-turn-vocabulary-decisions.md create mode 100644 .reviewer/issue-883/pr2-recovery-turn-vocabulary-interview.md create mode 100644 .reviewer/issue-883/pr2-recovery-unknown-implementor-correction.md create mode 100644 .reviewer/issue-883/pr2-repl-lifecycle-l2-flake-10b17a40.md create mode 100644 .reviewer/issue-883/pr2-repl-validation-architect-review-a49229e9.md create mode 100644 .reviewer/issue-883/pr2-repl-validation-implementor-handback.md create mode 100644 .reviewer/issue-883/pr2-repl-validation-planner-handoff.md create mode 100644 .reviewer/issue-883/pr2-responsiveness-evidence-implementor-handback-25227d38.md create mode 100644 .reviewer/issue-883/pr2-retained-requests-name-interview.md create mode 100644 .reviewer/issue-883/pr2-root-documentation-wiring-planner-review.md create mode 100644 .reviewer/issue-883/pr2-root-documentation-wiring-proposal.md create mode 100644 .reviewer/issue-883/pr2-root-evaluation-planner-review-01abab27.md create mode 100644 .reviewer/issue-883/pr2-root-evaluation-planner-review-3e6329f7.md create mode 100644 .reviewer/issue-883/pr2-root-evaluation-planner-review-ddf3f6f9.md create mode 100644 .reviewer/issue-883/pr2-section2-planner-review-43d53df7.md create mode 100644 .reviewer/issue-883/pr2-section2-planner-review.md create mode 100644 .reviewer/issue-883/pr2-section5-configuration-architect-handoff.md create mode 100644 .reviewer/issue-883/pr2-section5-configuration-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-section5-configuration-planner-handoff.md create mode 100644 .reviewer/issue-883/pr2-section5-configuration-planner-prompt.md create mode 100644 .reviewer/issue-883/pr2-section5-configuration-product-decisions.md create mode 100644 .reviewer/issue-883/pr2-section5-configuration-timing-architect-decision.md create mode 100644 .reviewer/issue-883/pr2-section5-mounted-message-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-section5-mounted-message-planner-handoff.md create mode 100644 .reviewer/issue-883/pr2-section5-preview-architect-decision.md create mode 100644 .reviewer/issue-883/pr2-section5-preview-architect-handoff.md create mode 100644 .reviewer/issue-883/pr2-section5-preview-architect-prompt.md create mode 100644 .reviewer/issue-883/pr2-section5-preview-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-section5-preview-planner-handoff.md create mode 100644 .reviewer/issue-883/pr2-section5-preview-planner-prompt.md create mode 100644 .reviewer/issue-883/pr2-section5-question-drawer-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-section5-question-drawer-planner-handoff.md create mode 100644 .reviewer/issue-883/pr2-section5-selection-routing-implementor-handoff.md create mode 100644 .reviewer/issue-883/pr2-section5-sessions-architect-decision.md create mode 100644 .reviewer/issue-883/pr2-section5-sessions-architect-handoff.md create mode 100644 .reviewer/issue-883/pr2-section5-sessions-architect-prompt.md create mode 100644 .reviewer/issue-883/pr2-section5-sessions-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-section5-sessions-planner-handoff.md create mode 100644 .reviewer/issue-883/pr2-section5-sessions-planner-prompt.md create mode 100644 .reviewer/issue-883/pr2-selection-example-implementor-correction.md create mode 100644 .reviewer/issue-883/pr2-selection-planner-review-1d373a61.md create mode 100644 .reviewer/issue-883/pr2-selection-planner-review-b01bbe6c.md create mode 100644 .reviewer/issue-883/pr2-session-configuration-architect-review-ef68c71c.md create mode 100644 .reviewer/issue-883/pr2-session-configuration-implementor-handback.md create mode 100644 .reviewer/issue-883/pr2-session-configuration-placement-vocabulary-return.md create mode 100644 .reviewer/issue-883/pr2-session-configuration-planner-handoff.md create mode 100644 .reviewer/issue-883/pr2-session-recording-architect-review-8fec6316.md create mode 100644 .reviewer/issue-883/pr2-session-recording-implementor-handback.md create mode 100644 .reviewer/issue-883/pr2-session-recording-planner-handoff.md create mode 100644 .reviewer/issue-883/pr2-session-rename-architect-review-9f15dc51.md create mode 100644 .reviewer/issue-883/pr2-session-rename-implementor-handback.md create mode 100644 .reviewer/issue-883/pr2-session-rename-implementor-handoff.md create mode 100644 .reviewer/issue-883/pr2-session-rename-planner-disposition.md create mode 100644 .reviewer/issue-883/pr2-session-rename-planner-review-9f15dc51.md create mode 100644 .reviewer/issue-883/pr2-session-vocabulary-architect-decision.md create mode 100644 .reviewer/issue-883/pr2-session-vocabulary-architect-handoff.md create mode 100644 .reviewer/issue-883/pr2-sessions-implementor-correction-4ee4f448.md create mode 100644 .reviewer/issue-883/pr2-sessions-implementor-correction-5ce2e2d2.md create mode 100644 .reviewer/issue-883/pr2-sessions-planner-review-4ee4f448.md create mode 100644 .reviewer/issue-883/pr2-sessions-planner-review-5ce2e2d2.md create mode 100644 .reviewer/issue-883/pr2-sessions-planner-review-ab681d4a.md create mode 100644 .reviewer/issue-883/pr2-sidekick-message-composer-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-sidekick-message-composer-planner-addendum.md create mode 100644 .reviewer/issue-883/pr2-sidekick-pane-width-planner-addendum.md create mode 100644 .reviewer/issue-883/pr2-sidekick-responsiveness-implementor-correction-13c4900d.md create mode 100644 .reviewer/issue-883/pr2-sidekick-responsiveness-implementor-handback.md create mode 100644 .reviewer/issue-883/pr2-sidekick-responsiveness-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-sidekick-responsiveness-planner-review-13c4900d.md create mode 100644 .reviewer/issue-883/pr2-sidekick-responsiveness-planner-review-25227d38.md create mode 100644 .reviewer/issue-883/pr2-stop-planner-review-01990ca4.md create mode 100644 .reviewer/issue-883/pr2-stop-planner-review-88c482b7.md create mode 100644 .reviewer/issue-883/pr2-stop-startup-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-terminal-completion-implementor-correction-39c24f37.md create mode 100644 .reviewer/issue-883/pr2-terminal-completion-implementor-correction-d634b28b.md create mode 100644 .reviewer/issue-883/pr2-terminal-completion-implementor-handback-correction.md create mode 100644 .reviewer/issue-883/pr2-terminal-completion-implementor-handback.md create mode 100644 .reviewer/issue-883/pr2-terminal-completion-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr2-terminal-completion-planner-handoff.md create mode 100644 .reviewer/issue-883/pr2-terminal-completion-planner-review-39c24f37.md create mode 100644 .reviewer/issue-883/pr2-terminal-completion-planner-review-d634b28b.md create mode 100644 .reviewer/issue-883/pr2-validation-planner-review-a49229e9.md create mode 100644 .reviewer/issue-883/pr890-architect-review.md create mode 100644 .reviewer/issue-883/pr890-planner-correction.md create mode 100644 .reviewer/issue-883/pr890-planner-review-79d404d0.md create mode 100644 .reviewer/issue-883/pr890-planner-review.md create mode 100644 .reviewer/issue-883/pr890-pr921-delivery-implementor-handback.md create mode 100644 .reviewer/issue-883/pr890-pr921-delivery-planner-return-c10a2062.md create mode 100644 .reviewer/issue-883/pr890-pr921-final-delivery-continuation-c2536dd0.md create mode 100644 .reviewer/issue-883/pr890-pr921-final-delivery-implementor-handoff-27da762b.md create mode 100644 .reviewer/issue-883/pr890-pr921-main-integration-architect-decision.md create mode 100644 .reviewer/issue-883/pr890-pr921-main-integration-architect-handoff.md create mode 100644 .reviewer/issue-883/pr890-pr921-main-integration-architect-interview.md create mode 100644 .reviewer/issue-883/pr890-pr921-main-integration-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr890-pr921-main-integration-planner-handoff.md create mode 100644 .reviewer/issue-883/pr890-pr921-main-integration-planner-release-d4b0e326.md create mode 100644 .reviewer/issue-883/pr890-rebase-attempt-finding.md create mode 100644 .reviewer/issue-883/pr890-replacement-correction-prompt-fdcef428.md create mode 100644 .reviewer/issue-883/pr890-replacement-planner-review-85da74b9.md create mode 100644 .reviewer/issue-883/pr890-replacement-planner-review-fdcef428.md create mode 100644 .reviewer/issue-883/pr890-replacement-pr1-implementor-handback-85da74b9.md create mode 100644 .reviewer/issue-883/pr890-replacement-pr1-implementor-handback-fdcef428.md create mode 100644 .reviewer/issue-883/pr921-agent-feedback-scope-architect-return-940249af.md create mode 100644 .reviewer/issue-883/pr921-architect-review-d906c636.md create mode 100644 .reviewer/issue-883/pr921-bindings-correction-review-ff0e52c6.md create mode 100644 .reviewer/issue-883/pr921-body-padding-implementor-conflict-27da762b.md create mode 100644 .reviewer/issue-883/pr921-body-padding-width-planner-amendment-27da762b.md create mode 100644 .reviewer/issue-883/pr921-configure-exit-implementor-handback-c2536dd0.md create mode 100644 .reviewer/issue-883/pr921-configure-exit-planner-handoff-6ca23952.md create mode 100644 .reviewer/issue-883/pr921-configure-exit-planner-review-c2536dd0.md create mode 100644 .reviewer/issue-883/pr921-control-only-planner-review-2ac3cb28.md create mode 100644 .reviewer/issue-883/pr921-control-only-recheck-planner-return-fd62f65f.md create mode 100644 .reviewer/issue-883/pr921-control-only-replies-architect-decision.md create mode 100644 .reviewer/issue-883/pr921-control-only-replies-implementor-handback-2ac3cb28.md create mode 100644 .reviewer/issue-883/pr921-control-only-replies-implementor-handoff.md create mode 100644 .reviewer/issue-883/pr921-conversation-labels-assessment.md create mode 100644 .reviewer/issue-883/pr921-delivery-continuation-7e7ffd27.md create mode 100644 .reviewer/issue-883/pr921-historical-identity-evidence-correction-prompt-f83e3554.md create mode 100644 .reviewer/issue-883/pr921-historical-identity-planner-review-d4b0e326.md create mode 100644 .reviewer/issue-883/pr921-historical-identity-planner-review-f83e3554.md create mode 100644 .reviewer/issue-883/pr921-historical-submission-identity-implementor-prompt.md create mode 100644 .reviewer/issue-883/pr921-historical-submission-identity-planner-handoff.md create mode 100644 .reviewer/issue-883/pr921-history-self-stack-review-d906c636.md create mode 100644 .reviewer/issue-883/pr921-horizontal-pane-tabs-top-spacing-planner-amendment.md create mode 100644 .reviewer/issue-883/pr921-implementor-handback-940249af.md create mode 100644 .reviewer/issue-883/pr921-implementor-handback-d4b0e326.md create mode 100644 .reviewer/issue-883/pr921-implementor-handback-f83e3554.md create mode 100644 .reviewer/issue-883/pr921-implementor-handback-ff0e52c6.md create mode 100644 .reviewer/issue-883/pr921-isolated-implementor-handoff.md create mode 100644 .reviewer/issue-883/pr921-padding-colors-implementor-return-27da762b.md create mode 100644 .reviewer/issue-883/pr921-padding-colors-planner-disposition-27da762b.md create mode 100644 .reviewer/issue-883/pr921-padding-header-colors-planner-addendum-27da762b.md create mode 100644 .reviewer/issue-883/pr921-padding-planner-review-6ca23952.md create mode 100644 .reviewer/issue-883/pr921-padding-width-approved-continuation-27da762b.md create mode 100644 .reviewer/issue-883/pr921-padding-width-implementor-handback-6ca23952.md create mode 100644 .reviewer/issue-883/pr921-parse-failure-status-architect-return-940249af.md create mode 100644 .reviewer/issue-883/pr921-pending-work-implementor-handoff.md create mode 100644 .reviewer/issue-883/pr921-reading-measurement-crash-assessment-ff0e52c6.md create mode 100644 .reviewer/issue-883/pr921-replacement-correction-prompt-5a3d32bd.md create mode 100644 .reviewer/issue-883/pr921-replacement-correction-prompt-ed202610.md create mode 100644 .reviewer/issue-883/pr921-replacement-independent-review-ed202610.md create mode 100644 .reviewer/issue-883/pr921-replacement-planner-pass-7613cddf.md create mode 100644 .reviewer/issue-883/pr921-replacement-planner-review-5a3d32bd.md create mode 100644 .reviewer/issue-883/pr921-replacement-planner-review-7613cddf.md create mode 100644 .reviewer/issue-883/pr921-replacement-planner-review-ed202610.md create mode 100644 .reviewer/issue-883/pr921-replacement-pr2-implementor-handback-5a3d32bd.md create mode 100644 .reviewer/issue-883/pr921-replacement-pr2-implementor-handback-ed202610.md create mode 100644 .reviewer/issue-883/pr921-replacement-pr2-verification-handback-7613cddf.md create mode 100644 .reviewer/issue-883/pr921-review-d906c636.md create mode 100644 .reviewer/issue-883/pr921-shared-body-padding-planner-handoff-27da762b.md create mode 100644 .reviewer/issue-883/pr921-sidekick-diagnostics-followups.md create mode 100644 .reviewer/issue-883/pr921-task-a-planner-review-940249af.md create mode 100644 .reviewer/issue-883/pr921-ui-feedback-sessions-history-sidekick.md create mode 100644 .reviewer/issue-883/pr921-ui-headers-continuation-prompt-7613cddf.md create mode 100644 .reviewer/issue-883/pr921-ui-headers-guidance-planner-amendment-7613cddf.md create mode 100644 .reviewer/issue-883/pr921-ui-headers-implementor-conflict-7613cddf.md create mode 100644 .reviewer/issue-883/pr921-ui-headers-implementor-handback-27da762b.md create mode 100644 .reviewer/issue-883/pr921-ui-headers-planner-handoff-7613cddf.md create mode 100644 .reviewer/issue-883/pr921-ui-headers-planner-review-27da762b.md create mode 100644 .reviewer/issue-883/remaining-architecture.md create mode 100644 .reviewer/issue-883/root-documentation-boundary-interview.md create mode 100644 .reviewer/issue-883/root-evaluation-architect-handoff.md create mode 100644 .reviewer/issue-883/root-evaluation-planner-handoff.md create mode 100644 .reviewer/issue-883/sidekick-instructions-proposal.md create mode 100644 .reviewer/issue-883/sidekick-language-primer-proposal.md create mode 100644 .reviewer/issue-883/storage-contract.md create mode 100644 .reviewer/issue-883/syntax-discovery-amendment.md create mode 100644 .reviewer/issue-932/api-interview.md create mode 100644 .reviewer/pr920-description/after.md create mode 100644 .reviewer/pr920-description/before.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/MANIFEST.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-pr-stack-architecture-review.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-pr-stack-plan.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-pr1-architecture-review-1f43f26f.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-pr1-architecture-review-2b475121.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-pr1-contextual-installer-plan-amendment.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-pr1-file-dir-implementor-handoff.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-pr1-planner-review-1f43f26f.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-pr1-planner-review-2b475121.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-pr1-planner-review-e5f095bf.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-consumer-integration-note.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-stack-plan.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-stack-planner-handoff.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-u1-implementor-handoff.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-u3-architect-review-ac466780.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-u3-implementor-handoff.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-u3-implementor-revision-ac466780.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-u3-landed.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-u3-plan-named-lookup-architecture-request.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-u3-plan-named-lookup-architecture-resolution.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-u3-plan-named-lookup-proposal.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-u3-planner-review-ac466780.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-u3-planner-status.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-u3-syntax-a2-proposal.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-u3-syntax-architecture-request.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-u3-syntax-architecture-resolution.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-u4-implementor-handoff.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-u4-implementor-prompt.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-prerequisite-u4-planner-status.md create mode 100644 .reviewer/upstream-prerequisites-6314e187/upstream-repository-reusable-interface-prerequisite.md create mode 100644 .reviewer/upstream-u4-review-2824855c/implementor-revision-prompt.md create mode 100644 .reviewer/upstream-u4-review-2824855c/planner-review.md create mode 100644 .reviewer/upstream-u4-review-695bc5b2/implementor-revision-prompt.md create mode 100644 .reviewer/upstream-u4-review-695bc5b2/planner-review.md create mode 100644 .reviewer/upstream-u4-review-eef612ed/planner-review.md create mode 100644 .reviewer/upstream-u4-status.md create mode 100644 .reviewer/upstream-u5-handoff-3a1fade9/upstream-repository-prerequisite-u4-landed-receipt.md create mode 100644 .reviewer/upstream-u5-handoff-3a1fade9/upstream-repository-prerequisite-u5-implementor-handoff.md create mode 100644 .reviewer/upstream-u5-handoff-3a1fade9/upstream-repository-prerequisite-u5-implementor-prompt.md create mode 100644 .reviewer/upstream-u5-handoff-3a1fade9/upstream-repository-prerequisite-u5-planner-status.md create mode 100644 .reviewer/upstream-u5-review-2f105ed7/implementor-revision-prompt.md create mode 100644 .reviewer/upstream-u5-review-2f105ed7/planner-review.md create mode 100644 .reviewer/upstream-u5-review-326afc60/architect-review.md create mode 100644 .reviewer/upstream-u5-review-86c10507/planner-review.md create mode 100644 .reviewer/upstream-u5-review-d2e684e2/implementor-revision-prompt.md create mode 100644 .reviewer/upstream-u5-review-d2e684e2/planner-review.md diff --git a/.agents/agent-writing.md b/.agents/agent-writing.md new file mode 100644 index 000000000..066b8be2a --- /dev/null +++ b/.agents/agent-writing.md @@ -0,0 +1,76 @@ +# Writing for agents + +These approved rules govern guides and instructions written for agents, +including initial prompts and on-demand reference chapters. They supplement +the general Writing Guide in `AGENTS.md` and the +[product-interface rules](product-interface.md). + +Optimize each guide for helping the agent take the next correct action. Keep +the writing human-readable so people can review what the agent is taught. + +## Approved rules + +1. Lead with when to read the guide and what action it enables. +2. State whether instructions apply to Sidekick responses, REPL entries or both. +3. Give direct instructions explaining what to write, under which conditions and what happens. +4. Show complete, safe-to-copy examples with required bindings and expected results. +5. Pair consequential, likely mistakes with the correct alternative and its practical consequence. +6. Keep one coherent topic per guide and name prerequisite and deeper guides using their exact component invocation. +7. Separate stable rules from current facts and obtain actual paths, capabilities and settings through inspection. +8. Use consistent terminology and ground component syntax in its authoritative reference. + +## Common guide format + +Use predictable Markdown sections in this order: + +- **Title and opening:** when to read the guide and what it enables. +- **Applies to:** the execution contexts covered. +- **Instructions:** the actions and conditions needed to use the topic. +- **Example:** complete source followed by its expected result. +- **Common mistake:** a consequential trap and the correct alternative. +- **Read next:** exact invocations for related guides. + +Omit optional sections when they add no useful information. A guide is useful +when an unfamiliar agent can discover it and perform the intended task +correctly with the documented initial context. + +## Example guide excerpt + +This excerpt illustrates the writing format for the Sidekick bindings chapter; +component availability is determined by the active syntax reference. + +````markdown +# Bindings + +Read this before using values created by earlier REPL entries. + +## Applies to + +Sidekick responses and the root bindings inherited by REPL entries. + +## Instructions + +- Read current published values with REPL.Bindings. +- Use returned binding names in entry source when appropriate. +- Each Sidekick response starts with an empty binding environment. +- Feedback does not automatically create response bindings. + +## Example + +```xmd + +``` + +The host returns a JSON map of published binding names and values +as feedback, then requests your next response. + +## Common mistake + +Receiving a binding named names does not make {names} available +in your next Sidekick response. It can be referenced inside an +entry that inherits that binding. + +## Read next + +Read when continuing interrupted work. +```` diff --git a/.agents/architect.md b/.agents/architect.md index f54ca77f0..3e1d77798 100644 --- a/.agents/architect.md +++ b/.agents/architect.md @@ -146,6 +146,8 @@ concept to explain itself. ## Communication rules 1. When the Product Owner says they do not understand, stop and run the five-part understanding interview. +2. Before proposing a new abstraction, show the concrete problem, why existing APIs cannot solve it, and what decision requires the Product Owner. +3. Explain behavior with familiar words and a concrete example before introducing technical terms; use only terms needed for the current decision. When the Product Owner says they do not understand, stop the current design discussion and run this interview before continuing: diff --git a/.agents/architecture-rules.md b/.agents/architecture-rules.md index 6894d3272..96cc4519b 100644 --- a/.agents/architecture-rules.md +++ b/.agents/architecture-rules.md @@ -28,6 +28,7 @@ the system itself; this file governs how new architecture is designed. 19. Renderer output is copied out of the engine before returning, and a refused frame is redrawn on a renderer rebuilt for that frame's dimensions without changing selection, focus, actions or the frame itself. 20. A contextual adapter owns terminal modes, listeners and readers, registers their release before taking them, and restores them exactly once on every exit. 21. A narrow surface displays the one route selected; every other surface is absent from the frame, its map and its targets rather than hidden within them. +22. Never mutate `next` or attach metadata to it; keep the continuation callable unchanged. 23. Use methods on an owned handle for operations tied to that instance. 24. Use a Context to select a scoped service; capture it for any lifetime that requires a fixed provider. 25. Use middleware when per-call interception or transformation is an intended extension point. @@ -38,6 +39,10 @@ configuration still follows that service's own update contract. A Context selects a trusted service, while authorization, durable identity, reconciliation and canonical outcomes stay with their owners. +The [API selection record](../.reviewer/api-selection-pattern-proposal.md) +contains examples and deferred review candidates. It assigns no refactor of +existing APIs. + The Architect applies these rules without another approval when they settle a design. A new concept, ambiguous fit, conflict or proposed exception returns to the Product Owner through the interview in diff --git a/.agents/planner.md b/.agents/planner.md index c964b7abe..fa56cf73c 100644 --- a/.agents/planner.md +++ b/.agents/planner.md @@ -166,3 +166,26 @@ End every planning handoff with the exact base, produced artifact paths, settled decisions, unresolved blockers and the next Implementor action. An implementation review records the exact reviewed SHA and the focused commands it rests on. + +When passing a sequence of changes to a new Planner, carry the context of the +whole sequence, including prerequisites and parallel work. The handoff includes +a self-contained snapshot of: + +- the overall outcome and why the work is split; +- every delivery's purpose, status, dependencies and remaining scope; +- landed PRs and exact merge commits, the verified current base, and any + difference between reviewed revisions and published or merged revisions; +- accepted product and architecture decisions that constrain later deliveries, + including superseded approaches that must not return; +- parallel tracks, their overlap, owners or known assignment status, and their + governing plans; +- unresolved decisions, preserved worktrees and evidence, and the exact next + action and authorization boundary. + +Maintain a shared sequence record and link its governing plans and reviews. +Include the concise sequence snapshot in the new handoff itself; do not rely +on conversation history or a chain of earlier handoffs to supply it. Separate +verified facts from reported or unknown status and mark historical snapshots. +The receiving Planner refreshes the record against current evidence and carries +it forward again at the next Planner transition. Planning one delivery does +not silently discard the dependencies or accepted decisions of the others. diff --git a/.agents/product-interface.md b/.agents/product-interface.md index f154e5309..1d9f027c8 100644 --- a/.agents/product-interface.md +++ b/.agents/product-interface.md @@ -9,6 +9,9 @@ shape the product's output. Component descriptions also follow the specialized additions in [component-descriptions.md](component-descriptions.md). +Guides and instructions written for agents also follow +[agent-writing.md](agent-writing.md). + ## Approved rules 1. Design public XMD interfaces so people understand what to write, what will happen, what it affects and what they receive. diff --git a/.reviewer/README.md b/.reviewer/README.md new file mode 100644 index 000000000..7161f630a --- /dev/null +++ b/.reviewer/README.md @@ -0,0 +1,23 @@ +# Review and planning records + +These records preserve architecture decisions, planning handoffs, implementation +handbacks and review evidence accumulated while delivering the REPL and Sidekick. +Each record describes its own revision and date. Historical verdicts and delivery +status are snapshots; consult the current issue, source and latest handoff before +using an older record as an assignment. + +- [API selection decisions](api-selection-pattern-proposal.md) +- [REPL history and lifecycle work (#881)](issue-881/README.md) +- [Sidekick delivery and reviews (#883)](issue-883/README.md) +- [Saved-entry inspection API interview (#932)](issue-932/api-interview.md) +- [Repository prerequisite status](upstream-u4-status.md) +- [Repository prerequisite record inventory](upstream-prerequisites-6314e187/MANIFEST.md) + +This archive includes written Markdown records. Copied source trees, generated +captures, logs, executable probes and binary archives remain local evidence and +are not included. References to those artifacts describe the original review +environment; they are not a claim that the artifacts ship in this repository. + +The shared query discussion is tracked separately in +[#934](https://github.com/taras/executable.md/issues/934); its public syntax remains +under design. diff --git a/.reviewer/api-selection-pattern-proposal.md b/.reviewer/api-selection-pattern-proposal.md new file mode 100644 index 000000000..077328f2f --- /dev/null +++ b/.reviewer/api-selection-pattern-proposal.md @@ -0,0 +1,101 @@ +# Choose APIs by ownership and intended composition + +Read this when choosing between an owned handle, a Context-selected service +and contextual Api middleware. It records an approved architecture pattern and +records existing APIs to revisit later. It does not assign their refactoring. + +**Approved, 2026-10-13.** The Product Owner explicitly approves the three rules +and the Code Rule 15 amendment below. They are recorded in the main checkout's +[architecture rules, 23–25](../.agents/architecture-rules.md) and +[AGENTS.md, Code Rule 15](../AGENTS.md). Other API choices remain deferred review +candidates. No production implementation or implementation-worktree edit is +made by this record. + +## Applies to + +TypeScript architecture and provider integration, including Core/host and +cross-package interfaces. This is not new syntax for Sidekick responses or REPL +entries. + +## Approved rules + +1. Use methods on an owned handle for operations tied to that instance. +2. Use a Context to select a scoped service; capture it for any lifetime that requires a fixed provider. +3. Use middleware when per-call interception or transformation is an intended extension point. + +Each rule is one sentence below 160 characters. The choice follows what callers should be able +to vary, rather than a blanket requirement that callable operations use +middleware. + +Core keeps authorization, durable identity, reconciliation and canonical +outcomes with their existing owners. A Context can select a trusted service; +replacing its value does not rewrite the owner's history or constitute proof +that an operation was authorized or completed. + +| Need | API shape | Consequence | +| --- | --- | --- | +| Work on one particular execution, conversation or tree | Methods on that owned handle | The caller states which instance the operation belongs to | +| Let the host choose a service for a scope | Context containing the selected service | The consumer captures it for the lifetime that needs a fixed choice | +| Let extensions intercept, transform, refuse or delegate individual calls | Contextual Api middleware | Per-call composition is an intentional product/extension contract | + +Capturing a service controls selection for the consumer's lifetime. It does not +make mutable service state immutable or add a live-update protocol. A future +verified configuration update remains an operation on the same owned +conversation, rather than silent retargeting by replacing Context. + +## Examples from the current work + +The accepted root-evaluation decision put evaluation on HostExecution and +AgentConversation. Evaluation belongs to that particular execution or +conversation, so an owned method fits. It replaced the generatedRoot callback +proposal. See [the accepted handoff](issue-883/root-evaluation-architect-handoff.md). + +REPL tree validation similarly belongs on the returned tree, alongside apply; +the caller uses the object that owns reconciliation. See +[the validation review](issue-883/pr2-repl-validation-architect-review-a49229e9.md). + +For Sidekick, a provider object selected through Context replaces the proposed +session/prompt inspection direction under these approved rules. The host +chooses the provider and Core holds it for the live conversation. Its existing +configuration admission and canonical recording remain private Core +responsibilities. The concrete four-method interface and integration are in +[the Architect handoff](issue-883/pr2-direct-provider-architect-handoff.md); +the Planner prepares the replacement implementation assignment. + +## Align the existing operations rule + +Before the approved amendment, AGENTS.md Code Rule 15 said: + +> State shared across loaded copies uses stable, namespaced names: plain structural values for composition data and a contextual Api for operations. + +That blanket choice conflicted with a Context-selected callable service. The +Product Owner approves its replacement, now recorded in AGENTS.md: + +> State shared across loaded copies uses stable, namespaced names. Use owned handles for instance operations, Context for scoped service selection, and contextual Api middleware for intended per-call composition. + +Its existing authority constraint remains: + +> Security enforcement, durable identity, and reconciliation never trust replaceable context state. + +This is an approved general rule change. An implementation worktree receives +the accepted instructions through its normal delivery plan. This record does +not edit that checkout. + +## Deferred API review candidates + +| API | Evidence of the same design pressure | Question for its later review | +| --- | --- | --- | +| AgentProviders.install | Provider selection uses private inspect/acknowledge exchanges through the registered provider's captured continuation | Does installation need per-call composition, or would scoped provider selection and direct Core-owned installation better express its purpose? | +| Git-host reconciliation routing | One request-only middleware operation reaches an invocation-private terminal through inspect/answer exchanges | Which parts require composition, which select a provider, and which must remain private reconciliation authority? | + +These are candidates, not findings or approved rewrites. Their authority, +credential handling, replay and lifetime constraints need their own reviews. +The pattern does not imply that a Context can replace a canonical terminal or +that all existing middleware is wrong. Ordinary Agent operation composition +also needs its own assessment if later work proposes changing it globally. + +## Next action + +Prepare #883's bounded Planner correction assignment from the Architect handoff. +Keep other API work deferred; no GitHub issue, production +edit, commit, push or CI inspection is assigned here. diff --git a/.reviewer/issue-881/README.md b/.reviewer/issue-881/README.md new file mode 100644 index 000000000..fa21f198a --- /dev/null +++ b/.reviewer/issue-881/README.md @@ -0,0 +1,97 @@ +# Prepare #881: original Terminal Interface parity + +The remaining original parity work is frozen for implementation: + +- [PR 2: lifecycle, Source and Output](pr2-implementation-handoff.md), with exact + Core interfaces, ownership, engine-measured wrapping, focused tests and + **44 comparison pairs**. +- [PR 3: History rail and exact selection](pr3-implementation-handoff.md), with + one retained snapshot, truthful head states, measured grouping/caption rules, + focused tests and **77 fresh assembled pairs**. +- [Final gallery matrix](final-gallery-matrix.md) and + [machine-readable scene plan](final-gallery-plan.json). +- [Exact stack and evidence rules](stack-and-evidence.md) and + [private engine measurement](planning-measurement.md). + +**PR 1 implementation feedback: PASS** at +`080b6ec80ca74e614789e8d2252857ac281df7e5`. Preserve its +[acceptance](pr1-planner-acceptance.md), [handoff](pr1-handoff.md) and 35-pair +record. The branch is unpublished. PR 2 starts there and integrates recorded +main `4c0414be1010f69f11bff0d1d634623a5b08f886`; PR 3 starts from the future +accepted PR 2 feedback SHA. + +The Architect/Product Owner decisions are complete in the +[PR 2](pr2-planner-handoff.md) and [PR 3](pr3-planner-handoff.md) architecture +handoffs. No persistence change or renewed Journal decision is needed. +**PR 2 has no planning blocker. PR 3 implementation depends on PR 2 acceptance.** +No PR 2/3 production change, implementation verdict, commit, push or PR is issued +by this planning packet. + +The [baseline comparison](comparison.html), [gap assessment](assessment.md) and +[earlier proposed matrix](comparison-matrix.md) remain historical evidence. They +are not the frozen final acceptance matrix. + +## Authority and base + +- Governing [Story #881](https://github.com/taras/executable.md/issues/881), child + of [Quest #827](https://github.com/taras/executable.md/issues/827). +- Original archive: [XMD REPL Terminal Interface corrected.zip](https://github.com/user-attachments/files/32939115/XMD.REPL.Terminal.Interface.corrected.zip). + SHA-256 `86be64318121546f3208342edaf17f0a3aed35f3fde2766b523423e6c708c77b`. + The downloaded, verified bytes are in [evidence/reference.zip](evidence/reference.zip). +- Captured production: `2d719f78025059158a35023701fdff52b855a65b`, local main. +- PR 1 recorded main base: `e68f128121cd802623ab7797a016b0c66ce91176`. + Current remote main read for the later slices on 2026-10-08: + `4c0414be1010f69f11bff0d1d634623a5b08f886`. The shared stack record accounts + for #880/#884 and the actual unpublished predecessor. +- #876 measured layout, #877 reveal retention and #878 semantic row styling are + merged foundations. Reuse them. No required unmerged stack was identified. + Refresh main and overlapping PRs immediately before implementation starts. + +Relevant installed versions: Effection 4.1.0, @effectionx/context-api 0.6.0, +@bomb.sh/tty 0.9.0 and core 0.13.1. Freedom is the repository's patched vendor +snapshot of commit `8be97e7201cd6effddb2f8b240b4b5166641e7f0`, rather than an npm +dependency. The proposal reuses these versions and their existing adapters. + +The archive owns visual intent. The current REPL specification and architecture +own execution and interaction. A visual conflict remains a decision, rather +than an implicit change to those contracts. The existing Story is preserved in +[story-draft.md](story-draft.md); no GitHub rewrite is proposed. + +## Evidence and limits + +The pre-change baseline contains 71 production/reference pairs: 23 scenes at all three supported +profiles, one wide resize recovery and one undersized refusal. ANSI screens, +plain text, PNGs, action records, a local provider fixture and the retained +Journal are preserved. [capture-runbook.md](capture-runbook.md) records provenance +and reproduction; [image-review-log.md](image-review-log.md) records inspection. + +Production images are fresh. Reference PNGs are unchanged derivatives inherited +from the earlier review gallery, with that provenance stated in the runbook. +The archive itself was freshly downloaded and verified. Scene times identify +reference analogues; they do not establish an identical workflow or a terminal +pixel target. No newer archive supplies a requirement. + +The existing presentation-style test passes: 7 tests, 25 steps. The installed +TTY engine also accepts independently coloured text runs in one element. Both +are useful implementation evidence; neither is a visual-parity verdict. +Cold inspection leaves the Journal and provider log byte-identical. + +## Continuity + +The Product Owner settled lifecycle authority: middleware observes complete +invocations and feeds a session-owned live view; the Journal supplies retained +history. A missing observation boundary is addressed without persistence. +Historical panes receive no live lifecycle overlay; returning live receives the +session's current snapshot. Original UI parity remains the scope. + +No production files, dependencies, commits, GitHub state or CI were changed. +The untracked greeting.md predates this work and is untouched. The isolated tmux +server is stopped. Review-created histories remain in the normal host storage; +no other history was changed. + +Next Implementor action: prepare the isolated PR 2 stack from its frozen +handoff, run the focused evidence and return a stable feedback SHA. PR 3 follows +that accepted revision. Feedback acceptance and separately authorized delivery +retain their own gates. This turn changes only planning artifacts; no production +or GitHub state changed. The earlier 71-pair baseline and accepted 35-pair PR 1 +record remain intact. diff --git a/.reviewer/issue-881/architecture-review.md b/.reviewer/issue-881/architecture-review.md new file mode 100644 index 000000000..e5d3832db --- /dev/null +++ b/.reviewer/issue-881/architecture-review.md @@ -0,0 +1,309 @@ +# Architect review prompt + +**Architecture decisions complete.** The accepted interfaces, presentation and +verification journeys are consolidated in the ready +[PR 2](pr2-planner-handoff.md) and [PR 3](pr3-planner-handoff.md) Planner handoffs. +This record does not report an implementation verdict for either slice. + +The Planner has now frozen [PR 2 implementation](pr2-implementation-handoff.md), +[PR 3 implementation](pr3-implementation-handoff.md) and the +[final gallery](final-gallery-matrix.md). Those replace the older implementation +proposal and provisional scene mapping as acceptance evidence. The accepted +architecture contracts and structural checklists remain unchanged. + +Finalize the later slices of #881's original Terminal Interface parity. PR 1 +is approved and start-ready under [pr1-handoff.md](pr1-handoff.md); its private +token types/helpers need no further architecture ruling. The +Planner has produced a fresh [gap inventory](assessment.md), +[71-pair baseline gallery](comparison.html) and +[finite product comparison proposal](comparison-matrix.md). The intended base is +`e68f128121cd802623ab7797a016b0c66ce91176`; the captured production at +`2d719f78025059158a35023701fdff52b855a65b` is byte-identical. + +Apply `.agents/architect.md`, architecture-rules.md, product-interface.md and +product-verification.md. Read the complete architecture and governing REPL/XMD +contracts. Draft product verification, interview the Product Owner about the +unresolved behavior one item at a time, and return explicit rulings. Do not ask +the Implementor to discover these choices while coding. + +## 1. Middleware observes the complete live invocation + +The Product Owner has settled the authority: execution middleware feeds a +session-owned live lifecycle view. The Journal supplies retained history. It +does not decide whether a component is currently ACTIVE or WAITING. Missing +observation boundaries are addressed without adding persistence; original UI +parity remains the scope. + +The exact API is now accepted in +[pr2-invocation-contract.md](pr2-invocation-contract.md), which governs this +boundary. Static source inspection and generated-source presentation are also +accepted. [pr2-planner-handoff.md](pr2-planner-handoff.md) consolidates PR 2's +contracts. History is accepted in +[pr3-history-contract.md](pr3-history-contract.md) and consolidated in the ready +[pr3-planner-handoff.md](pr3-planner-handoff.md). + +The original reference shows ▶ ENTER, ● ACTIVE, ● WAITING, ◀ EXIT, +✓ SETTLED and × FAILED on nested executable occurrences. Keep this live reading +separate from the projector's admitted entry/component/generated source regions. +Those retained regions help locate source; they are not invocation lifetimes. + +### Current observation boundaries + +`Component.importComponent` observes resolution. Returning a definition says +that resolution finished, not that its body, projected content, generated work, +result validation, binding or teardown finished. Wrapping a returned definition +also misses failures before the body and is not a complete invocation boundary. + +`Execution.document` brackets the document walk. `Component.content` and +`tryContent` bracket requested content, and `Elicitation.elicit` observes an +actual unanswered question. The REPL's Agent bridge observes active Prompts and +pending `Agent.requestPermission` calls. The expansion controller owns real +pause holds. These are useful boundaries, but none alone brackets every +component invocation. + +Core's `expandComponent` resolves and validates a named occurrence before +dispatching its Markdown or function body. Both use `withInvocation`, which +joins projected content, then body resources, then persistent resources. +Function failure handling runs after that teardown; Markdown/function result +acceptance and bindings also occur outside the body itself. The new observation +boundary must cover this complete path, including early resolution/validation +failure and cancellation. Observing only the generator body's return is too +short. + +Keep `Execution.document` as the outer live execution anchor, not a substitute +for child invocation spans. Engine-handled structural occurrences used by the +original journey, such as `Switch`, bypass `importComponent`/`expandComponent`; +name their equivalent complete expansion boundary and observe it through the +same focused contract. Do not silently omit their children or invent import +events for them. + +### Proposed state-to-boundary map + +| State | Middleware observation boundary | Completion and recovery | +| --- | --- | --- | +| ▶ ENTER | Core begins a named invocation occurrence, before its resolution and validation. Middleware receives the frozen Expansion description; the REPL owns private call keys and nesting. | Resolution completion advances preparation; it does not close the occurrence. An early refusal is an invocation failure with its actual stage. | +| ● ACTIVE | Core reaches the accepted body and delegates its execution inside the complete invocation boundary. | Remains open through nested content and generated expansion. Resuming a resolved wait returns to ACTIVE only while the invocation still owns ongoing work. | +| ● WAITING | Middleware brackets an actual pending `Elicitation.elicit`, Agent permission request or owned expansion hold, attributed to its invocation. | Closing a drawer is not answering the wait. Release removes that wait reason; the invocation becomes ACTIVE only when no other relevant wait remains. Ordinary generator suspension or an in-flight import/Prompt alone does not mean a human is being asked. | +| ◀ EXIT | Core reports that body work has returned, failed or been cancelled and invocation teardown begins. | Keep EXIT through ordered content/body/persistent teardown and subsequent result acceptance. Carry the exit reason. Do not report SETTLED while a destructor is still running. | +| ✓ SETTLED | The complete invocation boundary reports accepted success after teardown, return validation and any result binding. | Ends this live occurrence once. A later Journal append is not its completion signal. | +| × FAILED | The complete boundary reports canonical invocation failure, including resolution/prop refusal, body failure, failed result validation, unrecovered content failure or teardown failure. | Preserve the failure's stage and canonical cause; report the final badge after unwind completes. Printed failure can return normally, so middleware must observe the canonical semantic outcome, not merely whether `next()` threw. | +| Cancellation | The complete boundary reports cancellation and its unwind: EXIT with reason `cancelled`, then the existing textual cancelled outcome after teardown. | Clear every wait and active occurrence once. Cancellation is not successful SETTLED or FAILED merely because no value returned. A cleanup failure follows Core's actual failure precedence and is reported as such. | + +ENTER/EXIT are event-backed phases, not promises of a minimum animation time. +Do not delay execution so a frame can catch them. Subscriptions begin with the +latest phase; the session may retain completed live badges. That snapshot is +process-local and never becomes reconstructed history. + +### Session ownership and separation + +Install lifecycle middleware before the session starts entry execution, in the +same owned execution lineage as its existing Elicitation, Agent and expansion +adapters. Core supplies the Expansion id/name/position; the REPL allocates +session-local call keys and binds the enclosing presentation key around +delegation. These distinguish repeated or concurrent calls and entries. The observer stores +only presentation observations and publishes detached immutable snapshots to +the root. It owns no invocation, authority, provider, resource or terminal reader. +Core continues to own execution, failure disposition and teardown. + +Track wait reasons per occurrence, not one session-wide boolean. Concurrent +waits cannot erase one another. An ancestor can display that it waits on a +particular descendant, while the child keeps its own state; it does not acquire +the child's failure or outcome automatically. Observe child work actually owned +by the invocation, rather than assuming caller-retained resources end when its +body returns. + +Live middleware observations are neither Journal records nor `ReplModel` fields. +They may support the current session's completed badges, but a cold reader +cannot reconstruct those observations. It displays only retained source, +admissions, answers and entry outcomes actually available in the Journal. +Absence of a component close record is neither ACTIVE nor WAITING. + +During history inspection, source/bindings/output and lifecycle content in the +inspected panes come only from the selected retained prefix. Suppress the live +lifecycle overlay there, including live questions, permissions and active +badges. The running session continues observing offscreen. Returning live uses +its latest snapshot, not the snapshot from when inspection began. Any head +navigation summary remains explicitly separate, as described in section 3. + +### Address the missing boundary without persistence + +Specify a focused contextual middleware seam around Core's complete invocation +and its ordered phases/outcome. Cover Markdown and function components, +including value/captured invocations and generated descendants. Reuse the +existing invocation machinery and existing wait operations; do not expand this +into a general tracing system. Export any necessary consumer-facing contextual +API/types through Core's `/api`, under the repository's existing API rules. + +The seam delegates the canonical continuation without substituting a definition, +overriding a result, swallowing a failure or changing error disposition. Identity, +authorization and final settlement remain Core's closure-owned facts, not +replaceable observer context. Observation adds no durable records, timestamps, +sidecar, replay protocol or provider activity. It must leave Journal bytes and +execution outcomes unchanged with observation installed or absent. + +Register observer cleanup before entering the observed operation. Let canonical +teardown finish before publishing the final outcome. Session shutdown joins its +owned execution/observers and leaves no active/waiting entry or late publication. +Never yield in `finally`, infer completion from an import return or use an +unregistered post-acquisition destructor. + +Use the accepted seam, phase/outcome types, installation path and parent/wait +attribution in [pr2-invocation-contract.md](pr2-invocation-contract.md). +Freeze the remaining product verification and visual evidence with the source +presentation contract; do not reopen the persistence question. + +### Required lifecycle evidence + +Use one real nested fixture with two siblings and a generated child. Hold a +component after import resolution to show it remains open; hold an Elicit and +a permission request to show WAITING until their actual resolution. Include +overlapping waits, a recovered child failure and an unrecovered failure so the +observer cannot propagate every child outcome to its parent indiscriminately. + +Exercise early resolution/validation refusal, returned printed failure, body +failure, slow teardown, teardown failure and cancellation while waiting. Assert +one terminal outcome after owned cleanup, no active/waiting leak and unchanged +canonical failure precedence. Cancel a session while an observer is installed +to verify its own lifetime. + +Inspect a retained prefix while the live execution changes, then return live: +historical panes stay unchanged while the live snapshot advances. Cold inspection +installs no execution observation and makes no provider call. A Journal containing +the same admissions without a live observer cannot manufacture active/waiting +badges. Keep Journal-byte equivalence between observed and unobserved runs. + +Output ownership is accepted in pr2-source-presentation.md: the entry-rendered +result stays with the entry; retained block output stays with its recorded source +owner. The lifecycle Result carries no rendered value. Retained output is limited +to the selected prefix. No persistence is required to decide what is active now. + +## 2. Generated replacement and readable transcript + +`generated_xmd` retains admitted source and the producing source position. +`ReplPosition` distinguishes a path from a generated-source owner. Yet +`application.ts` currently describes generated admission as a transcript row +and selects an entry-wide flat transcript regardless of the nested source +selection. Many effect summaries precede the generated source and final README. + +The paired source reading is accepted in +[pr2-source-presentation.md](pr2-source-presentation.md): successful admission +replaces Evaluate's inner producer content while preserving its opening/closing +tags and enclosure. Original source and Journal bytes remain unchanged; an +earlier prefix still shows the producer. The self-closing adaptation is also +accepted: keep its authored row and place admitted source directly beneath it. +Soft wrapping and vertical windows are accepted, with `[↑ earlier]` / `[↓ later]` +labels throughout. Lifecycle glyphs and words use an accepted shared right-aligned +status column, with source rails on the left and source wrapping in the remaining +width. Entry Output precedes Source; nested source readings display only output +with an established narrower owner. These presentation choices are accepted. +A private display +projection may weave retained source together; it may not execute it. + +Preserve readable access to every source/output character through soft wrapping +and measured vertical windows. Source previews follow the same policy within +their existing drawer window; metadata keeps its existing fitting rules. +No hand-calculated screen positions or multiline editor are proposed. Refuse +ambiguous ownership instead of attaching source/output to a guessed sibling. + +The exact read-only source inspection boundary is accepted in +[pr2-source-inspection.md](pr2-source-inspection.md). Keep it separate from live +middleware; do not introduce a second CLI parser, load component source during +cold inspection or expand the accepted observation request with unrelated +source parsing. The main verification journey is accepted in +[pr2-product-verification.md](pr2-product-verification.md). +The ready [PR 2 Planner handoff](pr2-planner-handoff.md) consolidates these +contracts and freezes the structural checklist. Concrete implementation and +evidence remain the Planner's responsibility. + +## 3. History: current head versus inspected prefix + +The original reference's rail shows the recorded head and the earlier selected +checkpoint separately. Current `ReplCheckpoint` contains marker/kind/label, +with no timestamp. Inspecting a checkpoint projects a prefix, so its model +cannot describe the later known head. The captured tokens inspection illustrates +this loss of relationship. + +Accepted recorded-order adaptation: space marks by retained checkpoint +order, label the band `History · recorded order`, use tall entry boundaries and +short semantic marks, and draw the head and inspected-selection indicators +separately. Do not display invented elapsed time or animation percentages as +retained facts. The existing History drawer remains the exact-selection control; +the rail has no pointer/input targets and adds no scrubbing or fork capability. + +Accepted navigation boundary: the root supplies a private immutable summary +with all retained checkpoint identities/kinds and the overall head state. +The marker list reaches only History's band and exact-selection drawer; head +state reaches only the band. Source, bindings, result and Agent content in +inspected panes still come only from the selected prefix. The frozen action +row retains its History reading. Both readings come from one validated retained +snapshot, with actual session-owned task/controller facts for head state. + +Five-row placement is accepted: title/head label, entry/selection captions, +entry uprisers and selected diamond, horizontal rail, then minor stems and +the head marker. Keep selection above and head below the rail, including when +they share a column. Collision grouping is accepted: crowded marks use heavier +notches, entry captions merge into ranges, and the selected ordinal stays exact. +Every grouped checkpoint stays separately selectable in the existing drawer. +Resize preserves selected marker identity. The five History rows and seven-row footer +are fixed. Head state distinguishes empty, live, pausing, paused, settling, +settled and unfinished. Settled includes failure and cancellation; a cold +historical reading does not invent a paused execution. The Product Owner accepts +HEAD · EMPTY, HEAD · LIVE, HEAD · PAUSING EXPANSION, HEAD · EXPANSION PAUSED, +HEAD · SETTLING, HEAD · SETTLED and HEAD · UNFINISHED at all three profiles. + +The Product Owner accepts recorded-order spacing and the major/minor hierarchy. +The two-member navigation boundary interview is in +[pr3-history-contract.md](pr3-history-contract.md). Both members are accepted; +head wording, five-row placement and generic drawer wording are accepted. +Collision grouping and the reference +colour treatment are accepted, including neutral non-live head states and +dimmed later recorded marks. The colour study is an interview aid, not a +production capture or visual implementation verdict. All PR 3 interface, +presentation and [verification journey](pr3-product-verification.md) decisions +are accepted. The [Planner handoff](pr3-planner-handoff.md) is ready. + +## 4. Approved private token-run approach + +The installed `@bomb.sh/tty@0.9.0` accepts multiple `text()` operations with +different colours in one element. The [probe](evidence/tty-probe.jsonl) writes +`` contiguously with the original literal colours and no engine +errors. Token colouring does not require extra Freedom nodes, a new renderer or +a dependency upgrade. + +Approved ownership: the application supplies immutable structural runs containing +text and semantic role. The private presentation module maps roles to engine +styles. The admitted layout emits the runs in the existing keyed element. Both +measurement and commit use the same builder. The renderer remains model-blind. +Selection stays a surface; focus adds its existing textual marker/weight and +does not overwrite token/lifecycle foregrounds. No ANSI strings or runtime +detection enter shared view data. + +A conservative private lexical highlighter preserves every +source character and uses ordinary source style where a partial draft cannot +be classified. It validates nothing, evaluates nothing and does not introduce +another XMD language contract. JSON presentation starts from the model's parsed +JSON value. The Product Owner approves this approach under the existing +architecture rules; exact local types and helpers remain implementation +decisions. PR 1's frozen colours, examples and evidence are in its handoff. + +## Product review and return contract + +Settle the later-slice scene mapping and adaptations in comparison-matrix.md. +PR 1's surface-only comparisons are frozen separately. Existing +rules already settle narrow routing, footer size, integer drawer placement, +explicit activation, location absence, single-row draft, keyboard/pointer +equivalence and Freedom focus ownership. Do not ask to approve them again. + +Accepted adaptations include ordinal History geometry and cell-based rails, +source/output wrapping and windows, right-aligned lifecycle words and the exact +head/drawer captions. The ready handoffs carry these examples and decisions. +Record adjacent `granted: … — Decline` wording separately; no permission-semantics +expansion is implicit. + +The ready handoffs return for PRs 2 and 3: approved product verification; each decision and its authority; exact +architecture/spec amendments; the complete-invocation observation seam and +session-owned live view; accepted private run/head-summary boundaries; and the +resulting plan changes. Keep the settled middleware authority and absence of new +persistence explicit. The Planner then freezes their lower-level evidence and +writes their separate Implementor handoffs. No production edit, commit, GitHub mutation, CI dispatch or +weights measurement is requested by this prompt. diff --git a/.reviewer/issue-881/assessment.md b/.reviewer/issue-881/assessment.md new file mode 100644 index 000000000..603a9331c --- /dev/null +++ b/.reviewer/issue-881/assessment.md @@ -0,0 +1,78 @@ +# Fresh gap assessment + +The current REPL has the accepted measured composition and useful semantic row +styles. It does not yet resemble the original reference's execution reading. +The largest difference is information hierarchy: the reference lets a person +follow source, nested work and result; production often shows many muted effect +summaries before the useful content. + +This assessment uses the freshly captured revision in README.md. All 71 pairs +were inspected through the indexed contact sheets; the full History, question +and settled reference images were also opened. The inherited V1–V6 assessment +and its definitions were not found in this checkout or the referenced former +checkout. Those historical IDs remain **unassessed**. G1–G6 below are fresh +findings, not invented replacements for their definitions. + +| Gap | Baseline observation | Required correction | Evidence | +| --- | --- | --- | --- | +| G1: colours within content | JSON keys, strings, numbers, booleans, null and punctuation share one foreground. The Plan review's XMD is a plain source block. Focus recolours the entire draft or control cyan. | Preserve token roles within XMD and JSON, including generated source and read-only previews. Focus adds a visible cue without erasing those roles. | [JSON wide](pairs/json-bindings-160x36.png), [binding drawer medium](pairs/binding-drawer-120x30.png), [Plan review wide](pairs/plan-review-160x36.png) | +| G2: source and execution structure | The nested Plan becomes `Plan-1 Plan`, interspersed with `import_component ok` and other effect summaries. Generated admission is recorded, but its source is beyond the initial visible transcript. The settled README is also below the initial effect list. | Present the known source with nested indentation and rails; place generated source at its recorded producing expression; distinguish source, progress, rendered output and subordinate metadata. Preserve readable access to long content. | [running wide](pairs/nested-running-160x36.png), [generated medium](pairs/generated-inline-120x30.png), [settled wide](pairs/settled-160x36.png) | +| G3: lifecycle | Entry outcomes and waiting guidance exist, but nested occurrences do not show the reference's ENTER, ACTIVE, WAITING, EXIT, SETTLED and FAILED glyphs/labels. Imports are not proof that a component body entered or exited. | Middleware observes the complete invocation and its actual waits, failure and cancellation. A session-owned live view carries those observations; the Journal supplies the separate retained reading. | [running medium](pairs/nested-running-120x30.png), [failed wide](pairs/failed-160x36.png), [paused wide](pairs/paused-head-160x36.png) | +| G4: coordinated panes and drawers | Pane colours and edges are present. Drawers begin directly over cut background headings; titles such as `SessiBinding` visually run together. Field/action stripes and the blank preview area make the drawer's boundary hard to read. Original drawers have a clear boundary, subordinate state line and grouped preview/actions. | Make each admitted drawer rectangle read as a distinct surface with a clear edge/title hierarchy and grouped labels, hints, values, validation and actions. Retain the measured placement and modal ownership. | [binding narrow](pairs/binding-drawer-72x20.png), [details wide](pairs/completed-details-160x36.png), [permission narrow](pairs/permission-drawer-72x20.png) | +| G5: History | Five rows wrap gold checkpoint labels. There is no horizontal rail, major/minor tick hierarchy or distinct head and selection marks. Inspecting `tokens` projects the prefix and removes later checkpoints from this reading; the footer does not show its relationship to the known head. | Draw the reference's rail relationships in the existing five rows using recorded order, subject to approval. Keep exact checkpoint selection in History's existing drawer. Decide how its head reading coexists with prefix-only inspected panes. | [History wide](pairs/history-drawer-160x36.png), [selected medium](pairs/historical-selection-120x30.png), [historical closed narrow](pairs/historical-closed-72x20.png) | +| G6: terminal adaptation and focus | Selection has a background and `*`; keyboard focus has `>`/weight. Narrow actually omits transcript and bindings. Resized drawers retain their route and draft, but long read-only lines are hard to read within a short window. | Preserve selection/focus separation, absent-pane targeting and window controls while adding token colours. Approve cell-based emphasis/rails and readable source/preview layout explicitly. | [draft narrow](pairs/draft-72x20.png), [README narrow](pairs/readme-preview-72x20.png), [recovered drawer](pairs/resize-recovered-160x36.png) | + +## Findings that do not justify another layout rewrite + +The fixed footer survives the drawer journey at all three supported sizes. +The 60×15 screen refuses with the actual dimensions and a recovery instruction; +enlarging restores the permission drawer and the exact unsubmitted draft. +Those captures reproduce no claim that modal ownership or resize destroyed the +route. G4 is a visual separation problem, not evidence that #876/#877 failed. + +Narrow absence is an intentional existing product adaptation. There is no +transcript or bindings pane at 72×20, and this plan adds neither. The draft is +one row with a line-count summary for multiline input. The live location stays +absent from the screen, as already settled in #878. + +The baseline fixture reached real Plan review, generated project details, +validation failure, README confirmation and a real completed write in the +review's temporary working directory. Its source differs from the mockup only +to use the accepted declarative generated-XMD grammar. Inspection and cold +reopen contact no provider and add no Journal records. + +## Architectural finding + +The captured Journal has 45 Yield and five Close records, all with coroutine ID +`root`. The closes belong to the five entries. Component imports retain useful +source positions, but they do not supply separate component closing events. +ReplScope models admitted source regions, not every executable element's +lifetime. ReplCheckpoint has marker/kind/label, with no timestamp or owner depth. + +The Product Owner has settled that live lifecycle comes from execution +middleware, not these records. The missing piece is a complete-invocation +observation seam: resolution, accepted body, pending waits, ordered teardown and +final semantic outcome, including failure and cancellation. Add that boundary +without persistence. The [revised proposal](architecture-review.md) maps the +states and separates the session-owned live view from inspected retained panes. +Applying the root's status to every imported component or adding a presentation +Journal would not satisfy #881. + +## Capture qualifications + +Some main-scenes deliberately keep an earlier selected entry while a later +entry runs. That is supported behavior, and the captions identify the state; +their contents are not presented as exact reference scene matches. Source and +rendered output currently hidden below the initial transcript window are +assessed from both the capture and the application/model code, not imagined as +visible in those frames. + +An early provider fixture failed to match a prompt with leading whitespace; +another permission capture outlived the fixture's 180-second timeout. Diagnostic +files and traffic are retained separately. Corrected captures replace those +scenes. These are capture-fixture errors, not intermittent product test failures. + +The selected Decline choice is retained correctly in provider traffic, but the +Sessions audit row says `granted: … — Decline`. This adjacent wording discrepancy +is recorded for the Architect's scope decision; it is not permission to broaden +permission semantics in this visual Story. diff --git a/.reviewer/issue-881/capture-runbook.md b/.reviewer/issue-881/capture-runbook.md new file mode 100644 index 000000000..4391549b2 --- /dev/null +++ b/.reviewer/issue-881/capture-runbook.md @@ -0,0 +1,138 @@ +# Baseline capture provenance and reproduction + +Production revision: `2d719f78025059158a35023701fdff52b855a65b`. +Capture date: 2026-10-08, America/Toronto. Action timestamps are Unix seconds in +actions.jsonl. This is a baseline review, not accepted implementation evidence. + +## Production path + +The unchanged CLI ran through its real Deno entrypoint, real terminal adapter, +input decoder, mounted tree and TTY renderer. No synthetic HTML recreation or +test-only renderer supplied production screens. + +```sh +deno run --allow-all --node-modules-dir=manual --cached-only --frozen \ + --config /Users/tarasmankovski/Repositories/taras/executable.md/deno.json \ + /Users/tarasmankovski/Repositories/taras/executable.md/packages/cli/src/deno.ts \ + repl --default-agent /Users/tarasmankovski/Repositories/taras/executable.md/.reviewer/issue-881/fixture-agent.py +``` + +Working directory: `/private/tmp/xmd-881-reference`. No HOME or data-root override +was used. The command created its own normal host histories. The corrected +journey's history is +`~/Library/Application Support/xmd/repl/4e2daca80ac407f6e4e5af24eee7cd83.jsonl`. +Only that review-created file was copied/read for cold evidence. No other +history was modified or deleted. + +The PTY used private tmux socket `/private/tmp/xmd-881-review.sock`, session +`issue881`, pane `issue881:0.0`, with a 256-colour terminal. It was isolated from +all user tmux sessions and is stopped. Normal entry/exit and read-only cold +invocations are recorded; a corrected second cold session verifies returning +live after closing the History modal. Focus containment correctly prevents +activating the background `[live]` action while that modal remains open. + +## Scenes and input + +The initial invocation supplies empty/draft frames. A fresh corrected invocation +runs Plan/README, JSON, failure and local permission entries. The provider gates +Plan completion and permission arrival on files owned by this review directory. +Its complete protocol traffic is provider.jsonl; it makes no external agent +request. Generated XMD is the declarative program in generated-readme.md. +The README write occurs only in the temporary working directory. + +The JSON fixture uses a trusted-root TypeScript evaluation to publish a JSON +value, following the existing real-execution test pattern. The Planner reviewed +that fixture choice. Generated source contains no evaluation block. + +capture.py drives bracketed paste/text, Tab/Enter/Escape and actual pointer +input. Pointer coordinates are derived from visible labels. `click-body` +excludes the fixed footer when a checkpoint label also appears in that footer. +Each supported profile is an actual PTY resize: 160×36, 120×30, 72×20. +Resize recovery additionally visits 60×15 and returns to 160×36. + +Screen originals are `tmux capture-pane -p -e -N`; captures/*.ansi preserves +screen SGR, and corresponding .txt files remove SGR for inspection. Three +*.stream.ansi files preserve raw output from the point pipe-pane was enabled; +they do not claim to include CLI startup bytes. actions.jsonl records every +capture's actual columns/rows. The authoritative gallery is gallery-manifest.json. +Intermediate screens are in diagnostics/ and are not acceptance scenes. + +The leading-whitespace prompt mismatch is in diagnostic-fixture-miss/. The +permission fixture originally used a 180-second capture timeout; the final +fixture removes that timeout for repeatable manual review. Its first request +expired while planning continued; the gallery's permission drawer uses a later +actual request, resolved through Decline. These harness corrections do not +change the captured production revision. + +## Cold truth + +The production exit location retained the selected failed entry and nonempty +draft. evidence/cold-command.txt records the exact reopen command. Cold viewing +also selected the tokens checkpoint, closed History and returned live. + +Before/after signatures are evidence/cold-before.json and cold-after.json: + +- Journal: 52,930 bytes, 50 records, + SHA-256 `1780fb0eb042436fe4e6ac3c8a819ec2f9abfa4a93c1e26cb38efc7538e3782a`. +- Provider log: 13,718 bytes, 37 lines, + SHA-256 `b8a25932cdaa3c47a45561d83540e0f3060390d838d9cd5eeedc8a6a8e92079c`. + +Both files are byte-identical after both cold inspection sessions. No provider +protocol call or retained append occurred. The retained Journal copy is +evidence/retained-journal.jsonl. + +## Reference provenance + +The original corrected archive was downloaded from #827's attachment and freshly +verified against SHA-256 +`86be64318121546f3208342edaf17f0a3aed35f3fde2766b523423e6c708c77b`. +Its exact bytes are evidence/reference.zip. The relevant original sources were +inspected, including their literal palettes, lifecycle definitions and rail. +evidence/reference-style-extract.txt preserves those source constants. + +Six PNGs are copied unchanged from +`.claude/worktrees/repl-parity-slice1/.reviewer/repl-parity-final-c2a173ab/references/`. +That gallery's runbook identifies them as unretouched derivatives of the earlier +#870 reference captures. Its copy is evidence/inherited-reference-runbook.md. +They are inherited reference renders, not fresh browser screenshots, and their +historical scene times are reported provenance. Current production captures +were never reused from that gallery. + +The empty, question, settled and Time Travel images are visual analogues for +the expanded production state matrix. Wide reference studies supply medium +comparisons; narrow question/empty studies supply those counterparts. Time +Travel is a wide study even when paired with a narrow production route. The +proposed mapping still needs approval. Reference PNG colours and styles are +not treated as an independent executable oracle; source-derived literal +expectations own the proposed regressions. + +## Rendering and inspection + +- Deno 2.9.7 stable, aarch64-apple-darwin; V8 15.0.245.2-rusty; TypeScript 6.0.3. +- tmux 3.6a; librsvg/rsvg-convert 2.60.0. +- Raster settings: Menlo 15px, 9×18 cell placement, foreground #c8d2d9, + background #0b0d0f. Production RGB foreground/background/weight SGR is retained. +- render.py rejects unsupported SGR and rows wider than their reported terminal. + It creates fixed-cell SVG/PNG screens and reference-above-production pairs. +- Paired reference images are fitted without changing aspect ratio. Browser + pixel sizes, variable fonts and animation times are not terminal dimensions. + +review-sheet-index.json maps all 71 pairs to 18 full-resolution contact sheets. +image-review-log.md records inspection of every sheet and the full key reference +images. Original pair PNGs, ANSI and text remain available from comparison.html. +sha256sums.txt hashes the packet artifacts other than itself. + +## Baseline verification + +`deno task test packages/cli/tests/repl-presentation-style.test.ts` passes +7 tests / 25 steps; evidence/baseline-style-test.log preserves the output. +This does not establish original-reference parity. + +The installed TTY probe is evidence/tty-probe.ts with output in +evidence/tty-probe.jsonl. Both same-element runs and flow children draw contiguous +independently coloured tokens without engine errors. Use the same-element +finding to avoid unnecessary focus/node changes; no dependency was installed. + +No baseline break controls were run: #881's discriminating token/rail/lifecycle +tests do not yet exist. Four controls are proposed for the later implementation +revision, with the unmodified positive result and restored negatives recorded. diff --git a/.reviewer/issue-881/comparison-matrix.md b/.reviewer/issue-881/comparison-matrix.md new file mode 100644 index 000000000..81b09a84e --- /dev/null +++ b/.reviewer/issue-881/comparison-matrix.md @@ -0,0 +1,128 @@ +# Proposed finite comparison matrix + +**Superseded for implementation acceptance** by +[final-gallery-matrix.md](final-gallery-matrix.md), frozen with the PR 2 and PR 3 +implementation handoffs. This earlier proposal remains a planning history record. + +**Complete-story proposal; not frozen.** PR 1 instead uses the approved, +self-contained [handoff](pr1-handoff.md) and its +[35-pair subset](pr1-gallery-manifest.json). This matrix gives the Architect and Product Owner a +concrete review target. It preserves #881's outcome and the current product. +The Architect refines product verification before the Planner freezes these +scenarios and their lower-level evidence. + +All numbered scenes use 160×36, 120×30 and 72×20. At narrow, the scene shows its +existing routed outlet and admitted drawer; absent transcript/bindings panes are +absent from descriptions, focus traversal, frame targets and pointer maps. +Reference frames are visual analogues; no identical pixel geometry is claimed. + +| ID | Production scene and action | Original reference comparison | Recognition required | Incomplete implementation caught | +| --- | --- | --- | --- | --- | +| M1 | Empty REPL, then multiline Evaluate/Plan draft | Agent Sessions empty; TUI input | Headings, pane surfaces/edges, ready guidance, single-row persistent draft and reachable History | Styling only the submitted transcript | +| M2 | Submit Evaluate/Plan; hold the scripted Agent turn before completion; show Sessions | Time Travel nested Plan; Agent Sessions progress | Known source token colours, nested source rails, full lifecycle glyph/word in the shared right-aligned status column and streaming turn hierarchy | One coloured summary, or every imported component labelled active | +| M3 | Plan review waits; explicitly activate Answer, inspect source, reach decision controls | Question/preview hierarchy; Time Travel XMD | Tokenized source, grouped read-only preview and choices, explicit activation | A working but undifferentiated form; automatic opening | +| M4 | Approve Plan; generated fragment admitted; inspect the generating source position | Time Travel generated replacement in original JSX | Admitted XMD replaces paired Evaluate's inner producer content; Evaluate's enclosure remains visible; source and rendered output remain distinct | Source appended as unrelated output or muted event metadata | +| M5 | Open project details; submit empty values; enter Northstar and its description; review README | Agent Sessions question and confirmation | Label/hint/value/validation hierarchy, input focus and choices; preview remains readable through window controls | Decorative fields that hide validation or cannot reach decisions | +| M6 | Approve README; inspect settled entry; submit a separate failing entry | Agent Sessions settled; original lifecycle glyph definitions | Entry Output precedes Source; actual rendered result and identifying success/failure words/glyphs, with subordinate metadata | Green/red alone, wrong output ownership, or settled output buried under effect chatter | +| M7 | Submit JSON fixture; select tokens; activate the binding inspector; move keyboard focus away from selection | Time Travel bindings and selected reading | JSON token roles; selection persists independently; focus does not flatten syntax colours | Importing the production palette into expected assertions; focus overwriting all roles | +| M8 | Agent permission waits in Sessions; activate the pending request; inspect choices and duration; Decline | Original Agent Sessions surface and drawer hierarchy | Waiting turn, provider option labels, duration and explicit activation; recorded request later has no live authority | Automatically opened drawer; historically actionable request | +| M9 | Pause the real expansion; inspect an earlier checkpoint; close History; return live | Time Travel and Journal Scrubber rail studies | Accepted five-row ordinal rail, entry/minor hierarchy, grouped marks with exact drawer selection, distinct head/selection, truthful expansion-paused/settling/settled wording, prefix-only inspected panes | A label list; one marker used for both head and selection; future binding/output leakage | +| M10 | Cold-open the settled exit location and navigate retained content | Settled and historical reference analogues | Same retained styling/content and persistent URL draft; provider log and Journal bytes unchanged | Reconstructing the view by executing the document or materializing a provider | + +M4's paired replacement behavior is accepted in +[pr2-source-presentation.md](pr2-source-presentation.md); its full visual evidence +is not frozen. The [PR 2 main verification journey](pr2-product-verification.md) +and all five presentation decisions are accepted. Canonical static source +inspection is accepted, and pr2-planner-handoff.md is ready for the Planner. +M9's interface and presentation contracts are accepted in +[pr3-history-contract.md](pr3-history-contract.md). Its proposed +[verification journey](pr3-product-verification.md) is accepted. The ready +[PR 3 handoff](pr3-planner-handoff.md) carries the contracts before the Planner +freezes complete-story evidence. Terminal adaptations cannot +silently reduce the lifecycle or generated-source acceptance. + +## One resize journey + +Use a pending permission drawer with the unsubmitted draft +``. Move through 160×36 → 120×30 → 72×20 → 60×15 → 160×36. +Record normalized input, actual sizes and original ANSI. Observe the fixed +action row, five History rows and draft row; drawer placement remains above +them. The undersized screen shows the refusal and returns to the same route, +selection, focus target and exact draft when enlarged. A separate form journey +already exercises the same supported-size sequence with edited field values. + +This is one representative geometry boundary, not a new exhaustive size grid. + +## Reference-derived style evidence + +Use literal expected values derived from the verified archive, with file/hash +provenance. A test must not import REPL_PALETTE or the implementation's role map +to decide which colour should appear. Sample committed cells in the actual +frame's rectangles, and assert characters and attributes together. + +| Content role | Reference colour | +| --- | --- | +| XMD delimiters | #4e8b9c | +| Tags | #7fd3e8 | +| Attributes / JSON keys | #8fa7b8 | +| XMD strings | #d6b477 | +| Reference braces / booleans | #9b8ed0 | +| References | #b7aee0 | +| Numbers | #d69a6a | +| Prose | #c8d2d9 | +| Punctuation | #7c868d | +| JSON strings | #9ec49a | +| JSON null | #8b959c | + +Lifecycle expectations come from the original L map: ▶ ENTER #5aa87c, +● ACTIVE #7fd3e8, ● WAITING #c99a3f, ◀ EXIT #c2766e, +✓ SETTLED #4f8468, × FAILED #d24b3f. Middleware observes the complete live +invocation and actual pending waits; the session owns the live snapshot. The +Journal supplies retained history separately. The complete-invocation seam and +outcome details are accepted in pr2-invocation-contract.md; import resolution alone +cannot end the live occurrence. + +The source-role fixture covers one representative tag with attribute/string, +reference, ordinary prose, escaped text and an incomplete draft. Concatenating +runs reproduces the original source exactly. The JSON fixture covers keys, +escaped strings, number, boolean, null and punctuation. A nested execution +fixture includes a generated fragment and two siblings so guessed attribution +cannot pass unnoticed. Lifecycle evidence covers a body held after import +resolution, overlapping waits, failure/cancellation and slow or failed teardown. +Observe the same run with and without middleware to verify unchanged execution +outcomes and Journal bytes. During inspection, live observations advance only +offscreen; the historical panes stay prefix-only, and returning live uses the +latest snapshot. Cold history cannot manufacture ACTIVE/WAITING from admissions. + +## Four independent visual break controls + +After an unmodified feedback revision passes, apply each control alone in an +isolated checkout, capture its first failure, restore the exact revision and +verify restoration before the next control. Never mutate the shared prepared +worktree's dependencies or generated files. + +1. Collapse token roles to ordinary source colour: the XMD/JSON committed-cell + assertions fail at their named token positions. +2. Remove nesting rails/indentation: the nested-source geometry assertions fail, + even though the document still runs. +3. Remove lifecycle glyphs/words: the state-specific frame assertions fail, + independently of any colour. +4. Replace History's rail/head/selection with a label list: entry/minor tick and + distinct marker assertions fail, while exact drawer navigation may still work. + +Keep the restored positive result and all four failing outputs. Product +acceptance also requires a reviewer to open every final production/reference +pair and classify each difference as approved adaptation or unmet criterion. +Passing tests cannot substitute for this review. + +## Delivery artifacts + +The implementation PR links an externally accessible gallery and original +artifacts, with exact feedback SHA, reference checksum, scene IDs, actual terminal +dimensions, runtime, font/theme and capture method. Local-only links do not meet +#881's delivery condition. Publication is part of the later authorized +implementation PR work, not this local preparation. + +Freeze the final scene mapping, adaptations, ownership rulings and evidence +commands together. Add a scenario afterward only for an unmet existing criterion +or a distinct structural consequence requiring an explicit amendment. diff --git a/.reviewer/issue-881/fail-entry.md b/.reviewer/issue-881/fail-entry.md new file mode 100644 index 000000000..252df8a77 --- /dev/null +++ b/.reviewer/issue-881/fail-entry.md @@ -0,0 +1 @@ + diff --git a/.reviewer/issue-881/final-gallery-matrix.md b/.reviewer/issue-881/final-gallery-matrix.md new file mode 100644 index 000000000..68eb139c1 --- /dev/null +++ b/.reviewer/issue-881/final-gallery-matrix.md @@ -0,0 +1,175 @@ +# Frozen PR 2 and assembled #881 galleries + +PR 2 supplies **44 pairs**: fourteen states at three profiles and two resize +endpoints. PR 3 supplies **77 fresh assembled pairs**: twenty-five states at +three profiles and two endpoints. These are separate slice and complete-story +comparisons, not the provisional 71-pair baseline or PR 1's accepted 35 pairs. +The machine-readable list is final-gallery-plan.json. No capture is claimed +to exist yet and no implementation SHA is invented. + +## Reference authority and final mapping + +Use only evidence/reference.zip, SHA-256 +86be64318121546f3208342edaf17f0a3aed35f3fde2766b523423e6c708c77b. +The exact original sources own the named visual relationships below. Images +under references/ are unchanged inherited illustrations; their provenance is +recorded in capture-runbook.md and evidence/inherited-reference-runbook.md. +They are not new browser captures, terminal pixel targets or a substitute for +literal source expectations. The scene mapping below is final for this plan: +state intent replaces provisional animation timestamps. + +| Reference key | Archive source and recognizable scene | Supporting PNG | +| --- | --- | --- | +| R1 | xmd-repl-agent-sessions.jsx Shell, S/C/Y and Code: empty panes/input, coordinated surfaces and draft | reference-empty-wide.png; narrow uses reference-empty-narrow.png | +| R2 | xmd-repl-timetravel.jsx LifeLines and L, root document at lines 745–793: nested Plan, inline transition preserving Evaluate, lifecycle glyph/word and distinct output | reference-history-wide.png | +| R3 | xmd-repl-agent-sessions.jsx j1View/Shell and Code: Plan review, project question, confirmation preview, field/hint/value/validation hierarchy | reference-question-wide.png; narrow uses reference-question-narrow.png | +| R4 | xmd-repl-timetravel.jsx root settled reading/L/Code: completed rendered document before execution source, bindings jsonSpans and failure vocabulary | reference-settled-wide.png; binding reading uses reference-history-wide.png | +| R5 | xmd-repl-agent-sessions.jsx PermissionDrawer, MessageRow and j2View: waiting turn and explicitly activated permission choices/duration | reference-question-wide.png; narrow uses reference-question-narrow.png | +| R6 | xmd-journal-scrubber.jsx Scrubber/S/C and xmd-repl-timetravel.jsx Band/JournalPanel: horizontal rail, major/minor hierarchy, later dimming, distinct head/selection and exact navigation | reference-history-wide.png | + +Medium uses the wide study. R2/R4/R6 are wide studies at all profiles; the whole +narrow terminal route is compared against their relationship, not a manufactured +narrow mockup. Empty and drawer scenes have their existing narrow counterparts. +Settled/failed/cleanup references supply state/structure intent; actual diagnostic +and output text comes from the real run, not an animation's fictional receipt. + +All six supporting PNGs have freshly verified SHA-256: + +| PNG basename | SHA-256 | +| --- | --- | +| reference-empty-wide | 3db0c270a6371e214aadac711caeafbfa1be7031f88ada4da32bed78f69456af | +| reference-empty-narrow | 7ccd22d5b4f8def9f5f9aa7a7eae9be8b2f5194792b9633c792add15838d1532 | +| reference-question-wide | 28af525ab68ba2ade907282d65c4cb5ba44aafc01efba1f075a8a9ba20a4bfe2 | +| reference-question-narrow | 807c284826dc162deed125823cdc9acc6fe5f909447347757b91ef3c4f781ca2 | +| reference-settled-wide | edb3929cb7abb7151047a419986e158c85ee79b1de37ea0574c5703643d51978 | +| reference-history-wide | 47e97966b5f8118a2acf96b8952733434375b68348ad8d4bbc89f7d3728f7706 | + +## Exact scenes + +Every numbered scene is captured at 160×36, 120×30 and 72×20. Narrow uses the +listed current route. Wide/medium retain all admitted panes. Pause/cleanup +scenes use the controlled host with production assembly; other scenes use the +ordinary CLI and local provider. Each capture records its actual command. +Ordinary execution states are reached by normalized input and real operations, +not presentation injection. PR 2 assesses its frozen slice; PR 3 assesses the +assembled screen, including retained PR 1 roles and the new History band. + +| ID | Narrow route; capture trigger and finite claim | Reference | PR 2 | PR 3 | +| --- | --- | --- | --- | --- | +| empty | entries; fresh view: surfaces/input, empty History without invented mark | R1/R6 | — | yes | +| draft | entries; paste original Plan entry without submit: token roles, single-row persistent draft | R1 | — | yes | +| nested-running | entries; hold the Plan provider after work starts: Evaluate/Plan rails and ACTIVE, no settlement at resolution | R2 | yes | yes | +| plan-review | entries; explicitly open actual Plan Answer: WAITING survives closing/reopening; original producer and preview roles | R3/R2 | yes | yes | +| plan-review-controls | entries; reach its final decision controls using ↓ later: last preview row and complete actionable controls | R3 | yes | yes | +| generated-inline | entries; approve Plan and open Source's admission window: exact generated heading/Elicit inside unchanged Evaluate enclosure | R2 | yes | yes | +| invalid-details | entries; submit empty project fields: real validation and continuing WAITING | R3 | yes | yes | +| completed-details | entries; Northstar/description populated, drawer open: labels/value/focus preserve roles | R3 | yes | yes | +| readme-preview-tail | entries; actual confirmation drawer, scroll through last preview/decision rows: wrapping and tail access | R3 | yes | yes | +| settled-output-first | entries; approve write, wait for full unwind, select entry's first reading window: actual Output starts before Source | R4 | yes | yes | +| settled-output-last | entries; reach rendered `README.md was created.`: actual report, complete tail, no invented or duplicated result | R4 | yes | yes | +| settled-source | entries; reach admitted source after Output: enclosure/rails, colours, separate known source owner | R2/R4 | yes | yes | +| binding-drawer | entries; submit json-entry, select/activate its binding, move focus away: JSON roles and independent selection | R4 | — | yes | +| permission-wait | sessions; actual provider request arrives with drawer closed: truthful waiting announcement, explicit activation | R5 | — | yes | +| permission-drawer | sessions; activate request, retain nonempty draft: opaque bounded drawer, options/duration and real authority | R5 | — | yes | +| failed | entries; separately submit fail-entry: actual failed diagnostic and glyph/word, retained output ownership | R4 | yes | yes | +| pausing-head | entries; crowd/background fixture started, Pause requested before all holds establish: actual PAUSING EXPANSION | R6 | — | yes | +| historical-before-admission | entries; inspect Entry 1 before admission while session advances: producer only, no future output/bindings/live badges | R2/R6 | yes | — | +| paused-historical | entries; real expansion held, select Entry 1 before admission: prefix-only panes, full dimmed later rail, History action row | R6 | — | yes | +| offscreen-advance | entries; request Pause against active provider work, inspect during PAUSING, then release it: retained/navigation growth, same exact selection/prefix, actual PAUSED head | R6 | — | yes | +| grouped-history | entries; open full History after crowd fixture: heavier collision/entry marks, measured caption range, separate exact drawer rows selected in turn | R6 | — | yes | +| shared-head-selection | entries; inspect last offered checkpoint: ◆ above and ▼ below same column, independent captions/colours | R6 | — | yes | +| settling-head | entries; root outcome retained while installation teardown held: SETTLING, neutral head, unavailable next submission; release changes head without input | R6/R4 | — | yes | +| returned-live | entries; close History, return live/Continue actual hold: latest retained source/output and current live view; selected draft unchanged | R2/R6 | yes | yes | +| cold-settled | entries; settled read-only reopen head: retained source/output/style, no live badges or provider/source load | R4/R6 | yes | yes | +| cold-historical | entries; same cold session selects pre-admission marker: original producer, retained draft, full thin navigation, no later payload or live badges | R2/R6 | — | yes | + +Companion focused tests cover self-closing Evaluate, decline/unselected branches, +independent waits/readers, ENTER/EXIT/clean cancellation, empty output, static +scanner refusal, empty/singleton/unfinished and retained failure/cancellation +heads. They are not another gallery or an invitation to expand the state grid. + +PR 2's two extra pairs are `question-resize-refused-60x15` and +`question-resize-recovered-160x36`: take both with the Northstar/description +question still open, visiting 160×36→120×30→72×20→60×15→160×36. The restored +frame must still show that Answer and its values, not a later permission drawer. +Compare R3, with the existing explicit undersized refusal adaptation. + +PR 3's two extra pairs are `history-resize-refused-60x15` and +`history-resize-recovered-160x36`: an exact crowded historical marker selected, +History open and draft `` retained. Visit the same sizes; +restore the same marker, route and admitted focus under existing window rules. +Compare R6. Supported intermediate geometry and target agreement are also +asserted in H5, rather than adding more pairs. + +## Approved terminal adaptations + +These are the complete consequential adaptations for comparison: + +1. Fixed cells, terminal font/weight and actual 160/120/72-column profiles replace + browser pixels/variable font sizes. The footer remains action + five History + + single-row draft, with drawer above. Narrow mounts only its routed surface. +2. PR 1's gold drawer top rule and one-cell inset consume one row/two columns; + existing decisions/validation stay reachable through windows. Focus adds + weight plus its cyan cue; selected surface remains independent. +3. Source/output wrap and vertical windows replace pixel-sized browser text + regions. Source character/role tails remain reachable. Full state words use + one stable measured right column; rails remain at left. Glyphs/labels are + actual phases, not frame-duration animations. +4. Generated fixture uses supported declarative Switch/File XMD; paired Evaluate + retains its enclosure and replaces inner content, self-closing attaches a + child. Real rendered output stays separate and comes first at entry level. +5. Arrow labels are ↑/↓ with existing activation semantics. Drawers still require + explicit opening. No mock scrubbing or arrow shortcut is introduced. +6. History uses recorded ordinals instead of elapsed/compressed-wait clocks; + tall/short glyphs replace pixel notches. Consecutive collisions group visually, + captions merge actual entry ranges, exact drawer actions remain separate. + Accepted truthful head words and neutral settled colour replace mock success/ + completed claims. Amber selection above and head below preserve both at one + column. Category-only drawer wording protects the navigation exception. +7. Cold/prefix views show retained facts with no ephemeral lifecycle reconstruction + or future content. This intentionally differs from an animation that simply + freezes all its live state. Returning live reads actual current work. + +Other visible differences must be classified against a named frozen claim; +do not approve new adaptations silently. Browser timings, a fictional receipt, +elapsed times and extra features are not requirements. + +## Capture, audit and review + +Use separate pr2-evidence/ and pr3-evidence/ directories. Preserve original +`tmux capture-pane -p -e -N` ANSI, plain text, terminal PNG and paired PNG, actual +dimensions, normalized input/actions, local provider log, relevant retained +Journal copy and before/after SHA-256. Keep fixture commands/version, feedback +SHA and clean-tree proof, archive/source/image hashes, route/marker, runtime, +tmux/font/theme/cell-renderer settings and reference key per pair in the manifest. +Use private temporary sockets/history working directories; stop only the +harness's own server and never touch another invocation's temporary state. + +The merged terminal bench can collect ordinary CLI originals; when automating, +keep its single-run pointer isolated to the implementation worktree. The existing +capture/render harness can drive the multi-scene journey and controlled host. +Record adaptations to its input matching after `entries` and Unicode labels. +No screenshot or baseline terminal frame substitutes for a fresh final capture. + +For each scene assert its named claim in committed cells plus the common +relationships: full footer/drawer bounds, no pane overflow, correct admitted +route, focus/selection cues preserving token semantics, and complete controls. +PR 2 additionally samples independent L/source roles and reserved status bounds; +PR 3 additionally samples independent rail/entry/minor/selection/head colours and +exact ordinal labels. The scene table and C/L/S/H test tables freeze claims; +cell coordinates come from the actual engine bounds, not hand-positioned guesses. +Keep expected characters/colours independent of production role maps. An audit +reports each named claim, not only a total, and demonstrates failures against the +unchanged pre-change baseline. Break controls are frozen in each slice's handoff. + +Open every pair at readable resolution, using indexed contact sheets only when +the full cells/text remain legible. Record each pair as matching, approved +adaptation (name it) or unmet criterion (name it), plus the reviewer's actual +inspection. Do not infer review from filenames or a green audit count. +Cold-open both settled head and earlier prefix: identical Journal/provider bytes +and zero component-source loads, not merely a visually similar screen. + +The feedback handback includes these local artifacts. #881's eventual delivery +links a publicly accessible gallery and originals from its authorized PR; local +links alone do not satisfy that separate publication requirement. This planning +turn creates no PR or public upload and claims no final parity verdict. diff --git a/.reviewer/issue-881/generated-readme.md b/.reviewer/issue-881/generated-readme.md new file mode 100644 index 000000000..e7af99aaf --- /dev/null +++ b/.reviewer/issue-881/generated-readme.md @@ -0,0 +1,32 @@ +# Create a project README + +Enter the project details. + +Proposed README.md: + +# The project + + + +Review this README. + +# The project + + + + + + + + + +# The project + + + +README.md was created. + + +No file was created. + + diff --git a/.reviewer/issue-881/image-review-log.md b/.reviewer/issue-881/image-review-log.md new file mode 100644 index 000000000..4426ae900 --- /dev/null +++ b/.reviewer/issue-881/image-review-log.md @@ -0,0 +1,35 @@ +# Baseline image review + +All 71 production/reference pairs in gallery-manifest.json were opened through +the 18 full-resolution contact sheets listed in review-sheet-index.json. Every +pair is embedded unchanged in one sheet. The full original History-wide, +question-wide and settled-wide reference PNGs were additionally opened to read +their hierarchy and rail. This is the Planner's fresh gap review, not a final +product approval. + +| Sheets | Scenes inspected | Findings | +| --- | --- | --- | +| 01–03 | Binding inspector, cold outcomes, completed details, draft | JSON foreground is undifferentiated; drawer title runs into cut pane heading; one-row draft preserves line count; narrow omits transcript. | +| 04–06 | Empty, failed, generated admission, historical reading | Useful pane surfaces already exist; source/lifecycle structure is absent; effect summaries consume the initial generated/settled transcript view; History has no rail. | +| 07–09 | Historical selection, History drawer, validation, JSON | Prefix changes the visible checkpoint corpus; head/selection relationship is missing; exact History drawer selection remains available; JSON values share one foreground. | +| 10–12 | Active Plan, paused head, Sessions permission wait and drawer | Sessions state is visible; nested component progress is represented mainly by summaries; drawer edge/title separation is weak; pause/continue remain real controls. | +| 13–15 | Plan source review and decisions, project details | Source preview is whole-row styled; window controls keep decisions reachable; labels/hints/values have useful baseline emphasis; narrow preview needs readable long-content adaptation. | +| 16–18 | README preview, resize/refusal/recovery, return live, settled outcome | Edited values and draft persist; refusal shows actual dimensions; recovery restores the drawer; completed output is below the initial effect list; rail/lifecycle gaps remain. | + +The original Time Travel frame independently shows a tall entry boundary, +shorter semantic marks, a gold selected checkpoint and a separate paused head. +Its source uses differently coloured tags, attributes, strings and delimiters, +and an ENTER label beside the executable occurrence. The question reference +separates state, title, a subordinate preview and choices within a clearly +bounded surface. The settled reference gives the README and completed write +statement visual priority. + +Assessment verdict: **original parity remains unmet**. The baseline is useful +and the merged layout/focus corrections are retained. The gap assessment's +G1–G6 and proposed matrix define the next review. Historical V1–V6 definitions +are unavailable and are not assigned fabricated verdicts. + +Limits: reference renders are inherited derivatives, scene mapping is +provisional, and a screen cannot prove invisible node/input ownership. The +existing regressions cover that ownership separately. Cold hashes demonstrate +the read-only boundary; they do not establish visual resemblance. diff --git a/.reviewer/issue-881/implementation-plan.md b/.reviewer/issue-881/implementation-plan.md new file mode 100644 index 000000000..cf16a244b --- /dev/null +++ b/.reviewer/issue-881/implementation-plan.md @@ -0,0 +1,39 @@ +# Frozen original parity implementation plan + +PR 1 is accepted at 080b6ec80ca74e614789e8d2252857ac281df7e5. The remaining +architecture and product decisions are complete. Use the self-contained +[PR 2 implementation handoff](pr2-implementation-handoff.md), then +[PR 3 implementation handoff](pr3-implementation-handoff.md). They replace the +previous later-slice proposal. + +PR 2 delivers complete invocation observations, pure canonical source inspection, +session-owned phases/waits, generated-source replacement, Output before Source, +engine-measured wrapping and Unicode window labels. Its 44-pair gallery proves +that slice. It implements no new History geometry or navigation exception. + +PR 3 delivers the thin full-navigation exception, one validated retained snapshot, +entry-wide head truth, five-row measured ordinal rail, collision/caption grouping +and category-only exact checkpoint drawer. Its 77 fresh assembled pairs prove the +complete original visual contract, preserving PR 1 and PR 2 relationships. + +The [gallery matrix](final-gallery-matrix.md) freezes scenes, reference mapping, +profiles and accepted adaptations; final-gallery-plan.json freezes the counts. +The [shared stack record](stack-and-evidence.md) names the exact PR 1/main inputs, +merged changes, open overlaps, fixtures, feedback and delivery rules. +[planning-measurement.md](planning-measurement.md) records the private engine-fit +method and its read-only probe evidence. + +Core owns canonical execution. The session owns live observations and complete +entry unwind. The Journal supplies retained facts. The root owns immutable +readings, routes and actions; Freedom owns focus; measured admission owns mounted +rows and targets; renderer input remains operations. No persistence, timing, +dependency/vendor, newer-reference feature or extra reader is added. + +Continuity: PR 2 starts from 080b6ec80ca74e614789e8d2252857ac281df7e5 and +integrates 4c0414be1010f69f11bff0d1d634623a5b08f886 in an isolated worktree. +PR 3's exact base is the future accepted PR 2 feedback SHA. Produced artifacts +are the two implementation handoffs and shared gallery/stack/measurement records. +All design decisions are settled. No planning blocker remains; PR 3 execution +waits for PR 2 feedback acceptance. Next action: implement PR 2 under its frozen +handoff. This packet reports no later-slice implementation verdict or delivery +approval and changes no production code or GitHub state. diff --git a/.reviewer/issue-881/json-entry.md b/.reviewer/issue-881/json-entry.md new file mode 100644 index 000000000..b07350ae0 --- /dev/null +++ b/.reviewer/issue-881/json-entry.md @@ -0,0 +1,5 @@ +```ts eval +const tokens = { name: "Northstar", count: 3, approved: true, empty: null }; +``` + + diff --git a/.reviewer/issue-881/permission-entry.md b/.reviewer/issue-881/permission-entry.md new file mode 100644 index 000000000..a432cddf6 --- /dev/null +++ b/.reviewer/issue-881/permission-entry.md @@ -0,0 +1 @@ + diff --git a/.reviewer/issue-881/plan-entry.md b/.reviewer/issue-881/plan-entry.md new file mode 100644 index 000000000..9f242e9ed --- /dev/null +++ b/.reviewer/issue-881/plan-entry.md @@ -0,0 +1,8 @@ + + + Create an XMD program that asks me for a project name and a one-sentence + description. Preview the README it will create and ask for confirmation. + If I approve, write README.md and report that it was created. If I + decline, stop without writing anything. + + diff --git a/.reviewer/issue-881/planning-measurement.md b/.reviewer/issue-881/planning-measurement.md new file mode 100644 index 000000000..f50662821 --- /dev/null +++ b/.reviewer/issue-881/planning-measurement.md @@ -0,0 +1,74 @@ +# Engine measurement for wrapped readings and History + +The installed @bomb.sh/tty 0.9.0 engine answers natural text width through a +fit-sized element. No public line-break API or renderer change is needed. +These are planning probes, not a product test or implementation verdict. + +Two read-only Node probes imported the installed engine in the accepted PR 1 +worktree. Each rendered an element with width/height fit inside a 160×36 root, +then immediately copied its bounds before the next render. No engine error +occurred. The probes installed nothing and changed no production file. + +| Exact text | UTF-16 units | Engine width | Engine height | +| --- | ---: | ---: | ---: | +| abc | 3 | 3 | 1 | +| 界é🙂 | 4 | 5 | 1 | +| e followed by U+0301 combining accent | 2 | 1 | 1 | +| a b c | 5 | 5 | 1 | +| x repeated 240 times | 240 | 240 | 1 | + +The longer probe also showed that a nominal fixed width does not itself prevent +an unbroken text operation from expanding its measured minimum. Merely bounding +a box or reading its wrapped height is insufficient. Construct complete fitting +row fragments before admission, and measure the operations actually drawn. + +## Private preparation method + +After prepareFrame's empty width pass, use renderer.measure with independent +probe ops and structural ids. A probe is a fit-sized text element with the same +run/style operations the final row uses, without a viewport's fixed-height clip. +Read natural widths only; discard its output bytes. Batch modest probe groups +and copy every answer before another measurement invalidates engine info. +Keep the existing measuring and committing engine pair and frame acknowledgment. + +For each explicit logical line, consider cuts at Unicode grapheme boundaries; +UTF-16 offsets index source, never terminal width. Find the longest prefix whose +engine-measured width fits the available measured content region. Prefer its +last fitting word/whitespace boundary; if no such boundary exists, take the +longest fitting grapheme prefix. Preserve whitespace in the fragments, never +trim it. Keep blank logical lines as one row. Keep explicit newlines in the +logical reading and omit only those separator bytes from visual row text. +Measure the finished candidate again using its actual run ops. Every nonempty +iteration consumes source; no ellipsis or single-colour fallback is allowed. + +Split token runs by the chosen source offsets, maintaining their roles. Carry +source owner, logical line and continuation identity on private prepared rows. +Only the first visual row of an opening/closing observation carries its badge; +rails continue. Measurements reserve rails, a separator and the stable status +column first. These reservations are engine-measured, not text.length. Include +`◀ EXIT · ● WAITING` and the existing cancelled wording in the maximum status +width along with all six phase readings. The two accents in cleanup wait remain +distinct. Status-only changes reuse the same reservation and source cuts. + +The private result becomes immutable frame preparation data. The same prepared +row list supplies row counts, window admission, descriptions, boxes and targets. +The application consumes those rows; renderer input remains only engine ops. +Do not call measurement from a pure description or create a child reader. +Reprepare after size, selected reading, output or source changes. A phase-only +update can reuse cuts. Unmeasured passes emit no windowed content. + +Use the same fit probe for full Unicode arrow controls and History captions. +Widths of labels are engine results; ordinal spacing is arithmetic within the +engine's measured rail region. Static caption probes share preparation, not a +new frame subscription. Cache only private immutable input/size/style results; +no offset, width, phase or probe is retained in the Journal. + +The supported fixtures leave room for at least one grapheme after reservations. +An engine refusal remains the existing frame refusal. Do not repair an +unprovable fit by clipping source or spilling into another region. + +Probe entrypoints used in this session were +/private/tmp/issue-881-measure-probe.mjs and +/private/tmp/issue-881-fit-probe.mjs; these are local exploratory tooling. +The required implementation regressions reproduce the Unicode, unbroken-token +and exact-row-fit boundaries through Effection and the production renderer. diff --git a/.reviewer/issue-881/pr1-architecture-review.md b/.reviewer/issue-881/pr1-architecture-review.md new file mode 100644 index 000000000..44e139527 --- /dev/null +++ b/.reviewer/issue-881/pr1-architecture-review.md @@ -0,0 +1,86 @@ +# PR 1 architecture review — #885 + +**PASS** on `c7d54769d56661bef38cee8549b148f3bf87a904`. +The original colour, pane and drawer slice preserves the settled REPL ownership +and presentation boundaries. No architecture blockers remain. + +## Reviewed boundary + +Reviewed [PR #885](https://github.com/taras/executable.md/pull/885) against base +`4c0414be1010f69f11bff0d1d634623a5b08f886`, resolved on 2026-10-09. +It is the bottom of the #881 stack: #885 → #886 → #887. The latter two PRs +depend on this head; they are not dependencies of this slice or covered by this +verdict. The open-PR overlap check finds no other private REPL implementation +overlap. + +The accepted contract is [pr1-handoff.md](pr1-handoff.md), including the approved +UI16/UI17 window adjustment. The reference remains the older corrected archive, +SHA-256 `86be64318121546f3208342edaf17f0a3aed35f3fde2766b523423e6c708c77b`. +Lifecycle observation, generated-source restructuring and History presentation +remain outside PR 1. + +This head merges accepted PR 1 commit +`080b6ec80ca74e614789e8d2252857ac281df7e5` with the stated main base. +`git show --remerge-diff --format= c7d54769d56661bef38cee8549b148f3bf87a904` +is empty: the published integration introduces no manual merge changes. +The PR 1 layout, palette, classifier, reference fixture and three frozen focused +test files are byte-identical to the accepted revision. The private REPL changes +from main carry its `entries` route spelling and command-owned `Interrupt` key. + +## Structural findings + +The review traces the full patch and its consumers against the frozen ownership +rules: + +- Token runs are detached, frozen strings and role names. They add no executable + capability or identity. Classification is pure and stays in private REPL + composition; JSON comes from serialized parsed values. +- Multiple text operations remain inside one existing keyed row element. They + create no token nodes, bounds or pointer targets. Runs apply only when their + concatenation matches the mounted row's text; measured width constrains the + committed operations. +- The shared layout builder measures the drawer's rule and side inset before + admission. The admitted rows alone reach reconciliation, drawing and targets. + UI16/UI17 advance the existing measured window at 72×20 and retain their + behavioral assertions. +- Freedom retains focus ownership. Semantic colours survive focus, selection + keeps its independent surface, and typed activation still travels through the + existing mounted ancestry. Styling creates no alternate input path. +- The renderer remains model-blind. This slice adds no listener, reader, task, + clock, execution state, Journal record, persistence format or provider work. + Success, failure, cancellation, replay and teardown retain their existing + owners. + +The architecture and REPL specification changes describe these delivered +boundaries. No new architecture decision or exception is needed. + +## Focused evidence + +Prepared an isolated detached worktree at the exact reviewed head with +`deno task setup`, then ran: + +```sh +deno task test packages/cli/tests/repl-presentation-style.test.ts packages/cli/tests/repl-layout-admission.test.ts packages/cli/tests/repl-forms.test.ts +# exit 0 — 28 tests / 105 steps +deno task test packages/cli/tests/repl-composition.test.ts +# exit 0 — 9 tests / 45 steps +git diff 4c0414be1010f69f11bff0d1d634623a5b08f886 c7d54769d56661bef38cee8549b148f3bf87a904 --check +# exit 0 +``` + +Saved outputs: [frozen focused checks](evidence/pr885-architecture-focused.log) +and [composition checks](evidence/pr885-architecture-composition.log). +The isolated checkout remains clean after verification. + +[Planner acceptance](pr1-planner-acceptance.md) supplies the accepted revision's +35-pair visual review, independent colour expectations, five restored mutation +controls and unchanged cold-read signatures. Those artifacts remain pinned to +`080b6ec8`; this review does not relabel them as new captures from the integrated +head. The code comparison and fresh focused checks establish integration +continuity. No CI was inspected and no GitHub review was posted. + +## Continuity + +PR 1 architecture review is complete at the exact SHA above. #881's remaining +lifecycle/source and History work belongs to the separate #886 and #887 +contracts and reviews. This verdict does not close the full parity Story. diff --git a/.reviewer/issue-881/pr1-handoff.md b/.reviewer/issue-881/pr1-handoff.md new file mode 100644 index 000000000..3e96d368c --- /dev/null +++ b/.reviewer/issue-881/pr1-handoff.md @@ -0,0 +1,336 @@ +# PR 1 handoff: original colours, panes and drawers + +**Ready for implementation.** This is the approved first slice of +[Story #881](https://github.com/taras/executable.md/issues/881). XMD and JSON +keep their original token colours when focused. Panes have distinct surfaces; +an open drawer has an opaque, bounded surface with a readable title, content, +fields and actions. This document freezes PR 1's examples and evidence. The +full-story proposal and comparison matrix do not add acceptance criteria here. + +The Product Owner approves this slice and the private token-run approach in the +current planning session. Local types, helper names and lexical implementation +remain Implementor decisions under the existing architecture rules. PR 1 has +no pending architecture decision. + +## Base and authority + +Start from main **`e68f128121cd802623ab7797a016b0c66ce91176`**, resolved again on +2026-10-08. Captured production is +`2d719f78025059158a35023701fdff52b855a65b`; the only intervening change is +#879's history terminology in architecture.md. Production bytes are unchanged. +Reuse merged #876 measured layout, #877 reveal retention and #878 row styling. +There is no required unmerged stack. The read-only base and overlap checks are +recorded in [evidence/pr1-base-state.json](evidence/pr1-base-state.json). At this check, #805 at +`7cc1752d6ae3a90c234b768842cfb714d874e093` and the older #779 POC at +`11720a1301acc846f7d6c3767f117f407ec1f81e` change no private REPL files owned by +this slice; neither is a dependency. Refresh main and overlapping file changes +before editing. A changed base is recorded, not silently substituted. + +The visual authority is the original +[corrected Terminal Interface archive](https://github.com/user-attachments/files/32939115/XMD.REPL.Terminal.Interface.corrected.zip), +SHA-256 `86be64318121546f3208342edaf17f0a3aed35f3fde2766b523423e6c708c77b`. +The verified bytes are [evidence/reference.zip](evidence/reference.zip). +`xmd-repl-timetravel.jsx` supplies `S`, `C`, `Y`, `xmdSpans` and `jsonSpans`; +`xmd-repl-agent-sessions.jsx` supplies `Shell`, the question drawers and +`PermissionDrawer`. The [source extract](evidence/reference-style-extract.txt) +preserves the literal palette. The archive supplies appearance; existing +architecture and REPL/XMD specifications supply execution and interaction. + +Read repository AGENTS.md, Effection's required AGENTS.md, +[Implementor instructions](../../.agents/implementor.md), architecture.md and +the affected REPL and executable-MDX contracts before implementation. Relevant +installed versions are Effection 4.1.0, context-api 0.6.0, tty 0.9.0 and core +0.13.1. Freedom is the patched vendor snapshot of +`8be97e7201cd6effddb2f8b240b4b5166641e7f0`. No dependency or vendor change is +needed. Run `deno task setup` only to prepare a new worktree; builds install +nothing and verification does not mutate dependency state. + +## Slice boundary + +Style the existing source rows, visible draft text, question source previews, +JSON bindings and their inspectors. Coordinate the existing Sessions, +Transcript, Bindings, draft and contextual drawer surfaces. Group existing +question and permission content by its present roles. Preserve every existing +word, choice, value, validation message and action. + +Lifecycle observation, invocation APIs, component rails/badges, generated-source +replacement or ownership, transcript restructuring, new long-source presentation +policy and History are later slices. Do not edit their models, controls, +captions or geometry in PR 1. Existing successful, failed and waiting entry or +Agent cues retain their current meaning; a styling change adds no state. +Source already shown in a drawer may receive token colours without settling +how generated source appears in the later transcript. + +Keep the existing profiles, column constraints, integer drawer rectangle and +seven-row footer. At 72×20 only the current routed outlet and contextual drawer +are mounted. Keep explicit activation, Tab/Backtab/Enter/Escape, pointer +equivalence, modal containment, window controls, process-local offsets, the +single-row draft and absent location when no execution exists. No automatic +drawer, new shortcut, editor, route, public syntax or permission behavior is +introduced. Permission dismissal still denies; closing an Answer drawer still +does not answer it. + +## Frozen colours and emphasis + +These literal values are the independent expectations. Tests must not obtain +expected colours from production palette or style functions. + +| Visible role | RGB hex | Concrete example | +| --- | --- | --- | +| XMD delimiter | `#4e8b9c` | `<`, ``, `/>` | +| Tag name | `#7fd3e8` | `Elicit`, `Plan` | +| Attribute name / JSON key | `#8fa7b8` | `as`, `schema`, `"name"` | +| Quoted XMD value, including quotes | `#d6b477` | `"answers"` | +| Reference braces / JSON boolean | `#9b8ed0` | `{`, `}`, `true`, `false` | +| Reference content | `#b7aee0` | `schema`, `answers` inside braces | +| JSON number | `#d69a6a` | `3`, `-12.5` | +| Ordinary source / whitespace | `#c8d2d9` | `Enter the project details.` | +| Source heading | `#c7c4e6` | `# Create a project README`, bold | +| Punctuation | `#7c868d` | attribute `=`, JSON `{ } [ ] , :` | +| JSON string, including quotes | `#9ec49a` | `"Northstar"` | +| JSON null | `#8b959c` | `null` | +| Rendered output / entered value | `#e6ecf1` | README result, populated text field | +| Pane heading / ordinary drawer title / action | `#cfe0ea` | `Bindings`, `Binding · tokens`, `[close]` | +| Question or permission drawer title | `#c99a3f` | existing `Answer` or form title, `Permission · …` | +| Field label | `#8b959c` | `*Project name:` | +| Hint / metadata | `#7b858d` | `Name your project.` | +| Existing success / failure or validation / waiting accent | `#5aa87c` / `#c2766e` / `#c99a3f` | existing outcome and validation words | +| Focus marker | `#7fd3e8` | existing `>` | + +Headings and drawer titles use terminal bold. Focus adds the existing marker +and bold emphasis while each token and semantic foreground keeps its colour. +Selection remains the existing `*` cue and full measured row background +`#122026`, independently of keyboard focus. These selection and focus mechanics +are retained terminal adaptations. Do not import the reference's new focus +badge, variable font sizes or animation timing. + +| Surface | RGB hex | Boundary | +| --- | --- | --- | +| Application | `#0b0d0f` | uncovered application area | +| Sessions/catalog | `#090b0c` | its admitted pane | +| Transcript/routed centre | `#0c0e11` | its admitted pane | +| Bindings | `#0a0c0e` | its admitted pane | +| Draft | `#0a0d0f` | existing single-row draft | +| Drawer | `#0e1316` | entire admitted rectangle, including unused cells | +| Editable value | `#090c0e` | its measured value row | +| Pane/input separators | `#161c21` | existing pane/input boundaries | +| Contextual drawer top edge | `#c99a3f` | one terminal-cell rule inside its admitted rectangle | + +Do not restyle the History band. The reference's pixel padding becomes a +one-cell horizontal inset for drawer title/content, with the top rule separating +the drawer from the background reading. Titles do not join cut-off background +labels. All decoration belongs to the measured rectangle, and consumes measured +capacity before admission. Field value surfaces and the drawer remain opaque +after focus changes, shorter values, scrolling, closing and resize. + +## Frozen surface examples + +**Source.** In an existing draft or read-only source row, preserve exactly: + +```md +# Create a project README +Enter the project details. +{answers} +``` + +The table assigns separate colours to delimiters, names, attributes, `=`, +quoted values, braces and reference content. Ordinary prose remains source +coloured. These are presentation examples using existing grammar, not a new +executable program or an adoption of the reference's JavaScript conditions. +An unfinished draft such as `` and bold focus, `*` and `#122026` across the selected row's measured width. | Focus flattening all foregrounds; selection following focus or covering only the label. | +| P1-T3 | Commit empty panes, populated/invalid question, JSON inspector and permission drawer. Assert literal surfaces/edge, title inside its rectangle, label/hint/value/validation roles, and opaque unused drawer cells. Commit shorter content and close the drawer; inspect vacated cells. | A title spliced into background text; background leaking through an overlay; fields visually undifferentiated; stale pixels. | +| P1-T4 | Run the existing layout-admission and forms regressions, preserving their behavioral assertions. Add assertions only where drawer decoration changes capacity. Check supported profiles, measured window reachability, fixed footer, whole controls, and absent narrow outlets/targets. UI16/UI17 may advance the existing content window as specified below. | Padding painted after admission; hidden or unreachable submit/choices; duplicate narrow panes or altered validation/input. | + +The measured top rule consumes one content row; the side insets consume two +columns. At 72×20, UI16's submit control and UI17's validation row therefore +require one `[v later]` action. Keep both tests at 72×20 and reach those rows +through the existing window action and measured admission, rather than assigning +an offset directly. Recompute UI16's placed controls, modal ring and guidance +from that advanced window, retaining every forward/reverse traversal, +containment and action assertion. UI17 still verifies the field explanation and +unchanged lifecycle guidance in the same frame. Rows outside the first window +remain absent from its drawing, pointer targets and Tab ring. This adjustment +changes fixture positioning; it drops no behavioral claim and adds no product +interaction. + +Run exactly this focused positive command, plus the control reruns and whitespace +check below. Additional checks are required only by an actual failure or changed +boundary, not a newly imagined permutation. + +```sh +deno task test packages/cli/tests/repl-presentation-style.test.ts packages/cli/tests/repl-layout-admission.test.ts packages/cli/tests/repl-forms.test.ts +git diff --check +``` + +Run three isolated break controls in the implementation's own worktree: +collapse token roles to ordinary source (P1-T1 fails); restore whole-row cyan +focus (P1-T2 fails); remove the opaque drawer surface (P1-T3 fails at a named +unused/background cell). Save each patch and the first failing output. Restore +production bytes exactly between controls, then rerun the positive command. +Do not mutate dependencies or add a permanent switch for these controls. + +Once these focused checks pass, create the stable feedback commit promptly and +report its exact SHA, parent, commands and results. Capture the gallery from that +commit, with no production edits. Do not delay the feedback commit for the full +suite, lint/typecheck battery or CI. A passing baseline test is not evidence +that the new slice passes. Preserve the first failure before rerunning; follow +the repository flake procedure if an unchanged revision passes on retry. + +## Frozen PR 1 visual evidence + +Use an isolated PTY and the real CLI/input/TTY path. The +[capture runbook](capture-runbook.md), [local provider](fixture-agent.py), +[Plan entry](plan-entry.md), [generated fixture](generated-readme.md) and +[JSON entry](json-entry.md) provide the reproducible production journey. Copy +the harness into a fresh evidence directory; update its private socket, working +directory and entrypoint paths for the implementation worktree. Preserve the +baseline packet. No external provider request is needed. + +Capture **these 11 states at 160×36, 120×30 and 72×20: 33 pairs**. The existing +same-named files in `captures/` and `pairs/` are the pre-change examples. + +| States | Surface comparison frozen for PR 1 | +| --- | --- | +| `empty`, `draft` | Original Agent Sessions `Shell` and source `Code`: pane/input surfaces, headings, persistent draft and token roles. | +| `plan-review`, `plan-review-controls` | Original Plan-review drawer: opaque bound, separate title, source colours, reachable existing choices and submit. | +| `binding-drawer` | Original Time Travel `jsonSpans`/`Code` and bindings palette: JSON roles and inspector surface only. No History or source-rail comparison. | +| `invalid-details`, `completed-details` | Original project-form drawer: label/hint/value/validation hierarchy and focused populated field. | +| `readme-preview` | Original confirmation drawer: readable existing preview, decisions and surface separation only. | +| `permission-wait`, `permission-drawer` | Original Sessions/Permission drawer: existing pending-request hierarchy, explicit opening, grouped provider details and controls. | +| `cold-settled` | Original settled pane colours; retained content keeps the same styling after a read-only reopen. No new historical presentation. | + +Also capture **two resize endpoints**: with the populated question drawer open, +resize to 60×15 and capture the existing refusal; restore 160×36 and capture the +same admitted drawer and values. Total: **35 pairs**. Preserve originals, ANSI, +dimensions, input actions, fixture traffic and a SHA-pinned manifest. Check cold +reopen leaves its Journal and provider log byte-identical. + +The archive source elements named above freeze the PR 1 comparisons; the inherited +reference PNGs are supporting illustrations with their recorded provenance, not +an executable oracle. Their full-story timestamps and History/generated-source +mapping remain provisional. Keep the whole production screen for geometry +evidence, but assess only the PR 1 surfaces/roles. Browser pixel sizes and +animation times are not terminal targets. + +The Implementor opens all 35 pairs and records whether the frozen relationships +hold. Planner feedback reviews the exact commit, focused tests/controls and +these pairs. Lifecycle, generated-source structure and History gaps in those +screens do not fail this slice. A real unmet criterion returns for correction; +an unrelated observation does not silently enlarge the matrix. + +## Feedback, delivery and continuity + +Hand back the exact commit SHA/parent, changed files, all focused commands and +results, independent colour fixture provenance, restored control evidence and +the 35-pair gallery/runbook/manifest. Explain any criterion the evidence cannot +prove. Stop before push or PR creation unless separately authorized. PR 1 does +not close #881. + +Feedback acceptance is distinct from merge readiness. Required CI and `green` +own the exhaustive runtime shards, lint, typechecks, JSR and site checks before +merge. A private presentation change does not require repeating whole runtime +suites locally. Dependency/build mutation and test-discovery rules apply if +scope actually changes; neither is part of this slice. Do not inspect CI for a +Planner feedback verdict. + +Exact base: `e68f128121cd802623ab7797a016b0c66ce91176`. Artifact: +`.reviewer/issue-881/pr1-handoff.md`, with its frozen 35-pair evidence subset in +`pr1-gallery-manifest.json`. Settled: original colours and surfaces, retained +interaction/layout ownership, private same-element token runs, local types and +helpers delegated. **PR 1 blockers: none.** Next Implementor action: prepare an +isolated branch/worktree on the resolved base and implement this slice. + +Before PR 2, the Architect supplies the exact complete-invocation observation +API, phases/outcomes and installation/attribution contract. Before PRs 2 and 3, +the Architect and Product Owner finalize generated-source/History presentation +and the final reference scene mapping; the Planner then freezes their separate +handoffs. Session-owned middleware observations, completion after teardown and +separation from retained inspection are settled. No persistence change or +renewed Journal decision is needed. diff --git a/.reviewer/issue-881/pr1-implementation-handoff.md b/.reviewer/issue-881/pr1-implementation-handoff.md new file mode 100644 index 000000000..e2808bf55 --- /dev/null +++ b/.reviewer/issue-881/pr1-implementation-handoff.md @@ -0,0 +1,137 @@ +# PR 1 implementation handoff: original colours, panes and drawers + +**R1–R3 addressed; ready for Planner feedback.** Revised from the reviewed +`f0b8eb1f323c1ad5826eafba978ef9c2e9f5fffa` against +[pr1-planner-review.md](pr1-planner-review.md). Not pushed, no PR. + +## The commits + +| | | +| --- | --- | +| Feedback commit | `080b6ec80ca74e614789e8d2252857ac281df7e5` | +| Parent | `f0b8eb1f323c1ad5826eafba978ef9c2e9f5fffa` (the reviewed commit) | +| Earlier | `56afe3af7a960d00494cd495b00274b5986e812a` | +| Base | `e68f128121cd802623ab7797a016b0c66ce91176` | +| Branch | `agent/issue-881-pr1`; worktree `.claude/worktrees/issue-881-pr1` | + +Review `080b6ec8`; the whole slice is the three commits against the base. + +## R1 — the roles of visible characters survive an overflowing row + +The single-colour fallback is gone. The stretches of a row are now **cut at the +room the element has** (`layout.ts`, `written()` → `roomOf`/`bounded`), so the +engine never has to wrap one: every character the row can show keeps the role +it has and the order it was in, and the row shows one more character than the +word-wrapped reading it replaced rather than fewer. A row whose width the flow +decides — only the pass that is *asking* what the widths are draws one — still +takes the single operation it always did, so no measurement moved. + +The two cells the review named, read out of the new captures: + +| Capture | Cell | Was | Now | +| --- | --- | --- | --- | +| `plan-review-160x36` | `<` | `#c8d2d9` | `#4e8b9c` delimiter | +| `plan-review-160x36` | `Elicit` | `#c8d2d9` | `#7fd3e8` tag | +| `plan-review-160x36` | `schema` | `#c8d2d9` | `#8fa7b8` attribute | +| `completed-details-72x20` | `A lightweight` | `#8b959c` label | `#e6ecf1` value | + +The overflow regression now asserts the delimiter, tag, attribute, quoted +value, reference and prose roles **on the overflowing row itself**, that no row +is one colour throughout, that a focused overflowing row keeps its cyan cue, +and that the narrow populated form keeps its field's name and its value apart — +alongside the character-prefix checks it already had. `audit.py` no longer +accepts a tag drawn as one stretch: "a tag row is not painted one colour +throughout" and "a visible value reads as a value, not as its field's name" are +now claims of its own. + +No multiline editing, no new wrapping or access behavior, no generated-source +replacement, no second renderer. The measured geometry, window behavior and one +node and target per row are unchanged. + +## R2 — the frozen expectations are independent of the product + +New fixture `packages/cli/tests/fixtures/repl/reference-style.ts`: `SURFACE`, +`SEMANTIC` and `SYNTAX`, transcribed from the corrected archive's own `S`, `C` +and `Y` constants, carrying the archive SHA-256 +`86be64318121546f3208342edaf17f0a3aed35f3fde2766b523423e6c708c77b`, the two +source files and the extract they were read from. `RETAINED` holds the one +value the archive states differently — the selected row's `#122026` — named as +the retained terminal adaptation it is. + +All 65 expected-colour references in this slice's assertions now read that +fixture. **No `REPL_PALETTE` reference remains in them**; the pre-PR1 tests are +untouched, as the review allows. Control 5 below changes one palette entry by a +single bit and three rows go red — under the reviewed commit they would all +have stayed green. My previous handback said these were literals and none came +from production; that was wrong, and this replaces it. + +## R3 — the frozen resize journey + +`journey.py` takes both endpoints inside `stage_details`, with the populated +project question open: refusal at 60×15, then 160×36 again. The recovered frame +shows the same `Answer` drawer with `Northstar` and +`A lightweight workspace for coordinating coding agents.` retained, its rule, +its inset and its controls. The audit now expects a question title there, not a +permission one. Still 35 pairs; no extra journey. + +## Evidence + +```sh +deno task test packages/cli/tests/repl-presentation-style.test.ts \ + packages/cli/tests/repl-layout-admission.test.ts \ + packages/cli/tests/repl-forms.test.ts +# ok | 28 passed (105 steps) | 0 failed — exit 0 +git diff --check # clean, exit 0 +``` + +Also run on this revision: the journey set +(`repl-journey`, `repl-composition`, `repl-terminal`, `repl-boundaries`, +`repl-agent-journey`) — ok, 64 passed (208 steps), exit 0; +`deno check --frozen packages/cli/src packages/cli/tests` — exit 0; +`oxfmt --check` and `oxlint` over the changed files — clean, warnings unchanged. + +**Five break controls**, each applied alone to `080b6ec8`, patch and first +failing output in [pr1-controls/](pr1-controls/), production bytes SHA-256 +verified restored between each, positive command re-run green afterwards: + +| Control | Fails | +| --- | --- | +| Collapse token roles to ordinary source | P1-T1 ×3, D1 ×2 | +| Restore whole-row cyan focus | P1-T1, P1-T2 | +| Remove the opaque drawer surface | G5, P1-T3 — `the cell at 20,3 … carries 592652` | +| Send an overflowing row through a single-colour fallback | P1-T1 overflow, P1-T2 overflow, P1-T3 narrow form | +| Drift one palette entry by a single bit | P1-T1 ×2, P1-T2 | + +## The gallery + +[pr1-evidence/](pr1-evidence/) was recaptured end to end from `080b6ec8`: all +35 frozen states at 160×36, 120×30 and 72×20 plus the two question-drawer +resize endpoints, in one journey, with `actions.jsonl` recording every action +and every capture's actual columns and rows. `pr1-gallery-manifest.json` is +SHA-pinned through `sha256sums.txt` (262 files). + +- `audit.py` reads the frozen table out of the cells: **421 checks, all held**. + Against the pre-change baseline captures it reports **129 unmet claims**, + including the two R1 claims, so it discriminates. +- All 35 pairs opened again through the 13 contact sheets; + [image-review-log.md](pr1-evidence/image-review-log.md) records what each + shows and where the three findings are now visible. +- Cold reopen leaves its Journal and provider log **byte-identical** + (`cold-before.json` = `cold-after.json`). + +## Standing notes + +The drawer's decoration still costs its content window one row and two columns +at every profile, which is why UI16 and UI17 reach `[submit]` and the validation +row through one `[v later]` — unchanged from the reviewed commit and consistent +with the handoff. The two pre-existing drawer observations (first-field focus +ring; typing reaching the last-selected field) remain non-blocking and unfiled, +as the review directs. + +No criterion in the frozen matrix is now unproven, and there is no +ordinary-source exception left to report. + +## Next + +Planner feedback against `080b6ec8`. Nothing pushed, no PR; say the word and I +will open the draft PR from the repository template. PR 1 does not close #881. diff --git a/.reviewer/issue-881/pr1-planner-acceptance.md b/.reviewer/issue-881/pr1-planner-acceptance.md new file mode 100644 index 000000000..a7e2e47a2 --- /dev/null +++ b/.reviewer/issue-881/pr1-planner-acceptance.md @@ -0,0 +1,76 @@ +# PR 1 Planner acceptance + +**PASS** on `080b6ec80ca74e614789e8d2252857ac281df7e5`. +The frozen colour, pane and drawer slice satisfies P1-T1–P1-T4 and its visual +evidence. R1–R3 from the [previous review](pr1-planner-review.md) are resolved. + +Parent: `f0b8eb1f323c1ad5826eafba978ef9c2e9f5fffa`. +Base: `e68f128121cd802623ab7797a016b0c66ce91176`. +Branch: `agent/issue-881-pr1`; worktree: `.claude/worktrees/issue-881-pr1`. +Review covers the full three-commit slice against the base and the revision +against its reviewed parent. The accepted contract remains +[pr1-handoff.md](pr1-handoff.md), including the UI16/UI17 window clarification. + +## Resolved findings + +| Finding | Verified correction | +| --- | --- | +| R1: overflowing rows lose their roles | Runs are bounded by the element's stated room before engine text operations are emitted. Visible characters keep their order, semantic colours and focus cue. The overflow regression checks those roles on the overflowing row itself, and the narrow populated form checks label/value separation. All four previously cited captured cells now carry the frozen colours. | +| R2: expected colours come from production | The new P1 assertions use independent literals in `tests/fixtures/repl/reference-style.ts`. Its archive hash, source names and values match the original reference; the selected-row surface is explicitly recorded as the retained terminal adaptation. The palette-drift control fails the independent assertions. | +| R3: resize uses the wrong drawer | Both endpoints are captured during the populated project question. The recovered Answer drawer retains `Northstar` and the complete description, with its rule, inset and existing controls. The manifest still contains exactly 35 pairs. | + +The revision retains the one keyed element/node/target per row and the shared +measuring/committing builder. The width-discovery pass keeps its existing +measurement behavior. No lifecycle, History, generated-source restructuring, +Core, Journal, persistence, dependency or runtime-entrypoint work enters PR 1. + +## Focused evidence + +The Planner ran these commands in the implementation worktree at the exact SHA: + +```sh +deno task test packages/cli/tests/repl-presentation-style.test.ts packages/cli/tests/repl-layout-admission.test.ts packages/cli/tests/repl-forms.test.ts +# 28 tests / 105 steps passed; exit 0 +git diff --check e68f128121cd802623ab7797a016b0c66ce91176 080b6ec80ca74e614789e8d2252857ac281df7e5 +# exit 0 +``` + +The Planner opened all 35 refreshed pairs through their 13 contact sheets. +The [gallery](pr1-evidence/) retains the supported profiles, refusal and recovered +question endpoints. Its 262 checksum entries match, and its manifest names +`080b6ec80ca74e614789e8d2252857ac281df7e5`. + +The saved audit reproduces **421 held checks**. Direct captured-cell inspection +confirms `<` as `#4e8b9c`, `Elicit` as `#7fd3e8`, `schema` as `#8fa7b8`, and +the narrow field's visible value as `#e6ecf1`. The reference fixture's literal +colours were checked against the verified original JSX. Cold Journal/provider +signatures are identical before and after reopening. + +The five isolated control patches and first-failure logs discriminate collapsed +token roles, cyan focus overriding roles, a transparent drawer, overflowing rows +losing roles and one-bit palette drift. Controlled production files match the +saved restored checksum baseline. The final positive log also records +28 tests / 105 steps passing. The Planner inspected these control artifacts; +it did not reapply mutations during this review. + +Additional Implementor-reported journey, typecheck, format and lint evidence is +recorded in [the handback](pr1-implementation-handoff.md). The feedback verdict +rests on the frozen focused evidence and visual review. No CI was inspected. +Machine-readable review checks are in +[evidence/pr1-080b6ec8-planner-validation.json](evidence/pr1-080b6ec8-planner-validation.json). + +## Continuity + +Exact accepted SHA: `080b6ec80ca74e614789e8d2252857ac281df7e5`. +Artifact: `.reviewer/issue-881/pr1-planner-acceptance.md`. +PR 1 blockers: none. The one-row drawer capacity cost is the accepted measured +decoration; UI16/UI17 retain their behavioral assertions. The two disclosed +pre-existing drawer observations remain non-blocking and outside this slice. + +PR 1 feedback is complete. Delivery can proceed through the repository's normal +PR and merge verification when authorized; this review publishes nothing. +#881 remains open in scope: before PRs 2 and 3, the Architect and Product Owner +settle the invocation observation API and later generated-source/History +presentation and scene mapping. Session-owned middleware observations, +completion after teardown and separation from retained history remain settled. +No persistence change or renewed Journal decision is required. diff --git a/.reviewer/issue-881/pr1-planner-review.md b/.reviewer/issue-881/pr1-planner-review.md new file mode 100644 index 000000000..fe2145808 --- /dev/null +++ b/.reviewer/issue-881/pr1-planner-review.md @@ -0,0 +1,153 @@ +# PR 1 Planner feedback + +**REQUEST CHANGES** on `f0b8eb1f323c1ad5826eafba978ef9c2e9f5fffa`. +The colour, pane and drawer slice has three unmet frozen requirements. Its +structure, measured drawer decoration and scope separation can remain. + +Reviewed parent: `56afe3af7a960d00494cd495b00274b5986e812a`. +Base: `e68f128121cd802623ab7797a016b0c66ce91176`. +Branch: `agent/issue-881-pr1`; worktree: `.claude/worktrees/issue-881-pr1`. +The worktree is clean at the exact feedback commit. Review covers the full +two-commit change against that base and the current frozen +[PR 1 handoff](pr1-handoff.md), including its UI16/UI17 window clarification. +No CI was inspected. Nothing was pushed or published. + +## What passes + +The Planner ran: + +```sh +deno task test packages/cli/tests/repl-presentation-style.test.ts packages/cli/tests/repl-layout-admission.test.ts packages/cli/tests/repl-forms.test.ts +# 28 tests / 102 steps passed; exit 0 +git diff --check e68f128121cd802623ab7797a016b0c66ce91176 f0b8eb1f323c1ad5826eafba978ef9c2e9f5fffa +# exit 0 +``` + +The implementation retains one keyed element per row, immutable structural +runs, the shared measuring/committing operation builder and a model-blind +renderer. There is no Core, lifecycle, Journal, persistence, dependency or +runtime-entrypoint change. Local token helpers/types stay delegated. + +The pane/drawer surfaces, bounded title, waiting title accent, measured inset +and short-row role separation are visible. UI16/UI17 remain at 72×20, advance +through the real window action and retain their behavioral assertions. The +description export inventory and journey reader changes fit those mechanics. + +The Planner opened all 35 pairs through the 13 original contact sheets, +covering every supported profile and both supplied resize endpoints. All 262 +files in the implementation evidence checksum manifest match. The saved cold +Journal/provider signatures are identical before and after inspection. The +reported audit reproduces 376 held checks; its result does not establish the +three missing requirements below. The four control patches and their first +failure outputs were inspected; their failures discriminate the tested behavior. + +## R1: retain the roles of visible characters when a row overflows + +`packages/cli/src/repl/layout.ts:800` sends every overflowing row through the +single-colour fallback. This prevents the engine's per-operation wrapping +defect, but removes the frozen role separation from already classifiable, +visible characters. This is not the allowed fallback for unclassified text or +an unfinished draft. + +The failure exists in the frozen gallery, without inventing another scenario: + +| Capture | Actual captured cell, one-based | Frozen expectation | Actual | +| --- | --- | --- | --- | +| `plan-review-160x36` | `<` at row 21, column 22 | `#4e8b9c` delimiter | `#c8d2d9` | +| `plan-review-160x36` | `Elicit` at row 21, column 23 | `#7fd3e8` tag | `#c8d2d9` | +| `plan-review-160x36` | `schema` at row 21, column 30 | `#8fa7b8` attribute | `#c8d2d9` | +| `completed-details-72x20` | `A lightweight` in the field-name/value row, row 9, column 40 | `#e6ecf1` value | `#8b959c` label | + +The last row demonstrates that the fallback affects the approved form example +as well as source syntax. The visible value stops reading differently from its +field name at narrow size. + +The overflow regression at `repl-presentation-style.test.ts:1908` checks that +displayed characters remain a source prefix, then checks colours on a separate +short row. It never asserts the overflowing row's visible token colours. +Likewise, `pr1-evidence/audit.py` accepts a tag either in its roles **or** as a +single-colour row. Those are weaker expectations than the frozen handoff. + +Preserve character order and the existing admitted row/rectangle while keeping +the semantic colours of characters that are visible. This does not request +multiline editing, new source wrapping/access behavior, generated-source +replacement or another renderer. The local rendering mechanics remain the +Implementor's decision. If the engine makes the frozen behavior impossible +within that boundary, return the concrete constraint for architecture resolution; +do not silently adopt an ordinary-source exception. + +Extend the existing overflow regression to assert the visible delimiter, tag, +attribute/quoted value/reference roles, alongside its character-prefix checks. +Assert narrow field label/value separation on the existing populated form. +An overflowing focused row also retains its existing cyan focus cue. These +assertions enforce P1-T1–P1-T3, rather than expanding acceptance. + +## R2: use independent literals for the frozen committed-cell expectations + +The new P1 tests import production `REPL_PALETTE` and use it for expected RGB, +for example at `repl-presentation-style.test.ts:1443` and throughout P1-T1–P1-T4. +The handoff explicitly requires independent literal expectations derived from +the original archive. The implementation handback's statement that these +expectations are literals and none is imported from production is incorrect. + +A production palette drift changes both drawing and the expected value, so +these tests can stay green while the original colour contract breaks. The +separate gallery audit contains literals but does not replace the required +named-rectangle regressions; it also permits R1's weaker source presentation. + +Give the new frozen colour/surface assertions an independent reference fixture +or literal constants, with the archive hash and source provenance. Do not read +expected RGB from production helpers. Existing pre-PR1 tests do not need an +unrelated rewrite. Keep the character, rectangle and weight assertions and +correct the implementation handback's evidence description. + +## R3: reproduce the frozen populated-question resize journey + +The handoff freezes a populated project question drawer, its refusal at 60×15, +then its recovery at 160×36 with the same drawer and values. The submitted +`resize-recovered-160x36` shows **Permission · Write visual-review.txt**. +`pr1-evidence/journey.py:137` performs the resize inside `stage_permission`, +and the audit explicitly expects a Permission title for that capture. + +That is a valid permission capture, but it does not prove recovery of the +editable question and its populated values. Replace the two resize endpoints +with the frozen project-question sequence. Preserve the same values and current +question across refusal/recovery, then inspect the actual restored frame and +existing controls. Keep the total at 35 pairs; no extra journey is required. + +## Non-blocking observations + +The reported first-field focus-ring and typing-to-last-selected-field defects +are pre-existing observations. Their interaction mechanisms are not introduced +by this presentation diff. They do not enlarge PR 1's scope, and this review +does not create a follow-up issue or require their repair. The later lifecycle, +generated-source and History contracts remain separate architecture work. + +## Revision prompt + +Revise PR 1 from `f0b8eb1f323c1ad5826eafba978ef9c2e9f5fffa` to satisfy R1–R3: + +1. Correct overflowing-row presentation so visible classifiable characters keep + the frozen roles and focus cue, without losing or reordering text. Preserve + the current measured geometry, window behavior and one node/target per row. + Extend the existing overflow and populated-form checks to reject single-colour + fallback. Remove that exception from the audit and handback. +2. Replace production-derived expected RGB in the new P1 assertions with an + independent archive-derived literal fixture. Preserve their existing behavioral + assertions and correct the evidence description. +3. Capture the two frozen resize endpoints with the populated project question, + retaining its values, rather than substituting a permission drawer. + +Run the frozen three-file command, the applicable existing controls and the +overflow control, restore production bytes between controls, and rerun the +positive command plus `git diff --check`. Preserve first failures. Once the +focused evidence passes, create the feedback commit promptly and return its +exact SHA/parent and all commands/results. Capture the 35-pair gallery from that +revision, inspect every pair, and return corrected provenance, manifests and +checksums. Do not change the frozen criteria, add lifecycle/History work, wait +for CI, push or open a PR as part of this feedback revision. + +Continuity: exact reviewed SHA `f0b8eb1f323c1ad5826eafba978ef9c2e9f5fffa`; +review artifact `.reviewer/issue-881/pr1-planner-review.md`; blockers R1–R3; +next Implementor action is the bounded revision above. This verdict does not +accept PR 1 or complete #881. diff --git a/.reviewer/issue-881/pr2-architecture-draft.md b/.reviewer/issue-881/pr2-architecture-draft.md new file mode 100644 index 000000000..7f44faa9d --- /dev/null +++ b/.reviewer/issue-881/pr2-architecture-draft.md @@ -0,0 +1,503 @@ +# PR 2 architecture: observe the complete expansion + +**Draft for Product Owner review, not an Implementor handoff.** PR 1 feedback +is complete at `080b6ec80ca74e614789e8d2252857ac281df7e5`, based on +`e68f128121cd802623ab7797a016b0c66ce91176`. This proposal concerns the Core +observation boundary PR 2 needs. It changes no production files or GitHub state. + +## Purpose and example + +While a Plan is running, the REPL shows the Plan's executable occurrence as +active. When that occurrence asks an Elicit question, the question's occurrence +waits until an accepted answer arrives. After the body returns, its badge remains +EXIT while owned cleanup runs. SETTLED appears only after cleanup and result +acceptance succeed. A failure which Core prints still has a failed occurrence; +printing it does not turn it into a successful invocation. + +These are process-local observations. Historical panes use only the selected +retained prefix. Returning live reads the latest session snapshot. Cold inspection +starts no execution, installs no observer and invents no active or waiting state. +No Journal record, timestamp, sidecar or persistence protocol is added. + +## Traced boundaries + +The production paths inspected are unchanged by PR 1. The current root worktree +is `2d719f78025059158a35023701fdff52b855a65b`; the intended main base changes +only history terminology. The accepted PR 1 patch changes private presentation, +not these Core execution paths. + +| Boundary | What it establishes | Why it is insufficient alone | +| --- | --- | --- | +| `Component.importComponent` | Resolves a name to a definition. | Resolution finishes before props, body work, result acceptance and cleanup. Protected and closed imports also do not permit substituting wrappers. | +| `expandComponent` | Resolves and validates a named element, then expands its selected Markdown or function body and accepts its result. | It is private and has no complete invocation middleware operation. Engine structural constructs bypass it. | +| `withInvocation` | Owns content/body/persistent teardown in that order and preserves body and cleanup failures. | It starts after early resolution and prop refusal, and ends before some bindings and function failure disposition. | +| `Execution.document` | Surrounds canonical document expansion with request middleware. | It provides the entry anchor, rather than individual child occurrences. | +| Component dispatch in `expandListSegments` | Establishes an element path before both structural and ordinary component branches. | It needs an observation wrapper around those branches, without changing what dispatch executes. | +| `spawnChild` and installed region producers | Expand region occurrences that their parent consumes rather than dispatching independently. | Observing only ordinary dispatch would omit these real child executions. Unselected regions must not be reported as having run. | +| Generated-XMD `expand` | Starts a narrowed fragment with its own environment under the Evaluate body. | The observation parent must cross this boundary without inheriting or widening execution capabilities. | + +Code references: `packages/core/src/expand.ts` (component dispatch, +`expandComponent`, `expandFunctionComponent`, `spawnChild`, +`expandInstalledStructural`), `src/invocation.ts`, `src/document-request.ts`, +`src/execute.ts` and `src/generated-xmd.ts`. Governing contracts include +executable-MDX §§4.4, 5.6 and 6.9. The existing REPL Elicitation and Agent adapters +already publish actual pending questions and permissions; the expansion +controller already owns pause holds. + +## System-boundary interview + +The interview is required because this adds a public cross-package operation, +request, occurrence identity and observer lifetime. The accepted middleware +direction does not itself approve those members. `.agents/architect.md` requires +reviewing this boundary one member at a time. Local REPL helper names and types +remain delegated. + +Revised inventory: **all 5 review items accepted** by the Product Owner. +The consolidated boundary is [pr2-invocation-contract.md](pr2-invocation-contract.md). +Process keys and nesting remain private REPL view data, as described in item 2. +No accepted public member is removed. + +1. `ComponentApi.expand`: the complete element expansion operation. +2. `ComponentExpansionRequest.expansion`: the detached occurrence being observed. +3. `ComponentExpansionRequest.phases`: lifecycle stream, initial reading and subscription lifetime. +4. `ComponentExpansionPhase`: ordered body/exit/completion observations. +5. Completion payload: accepted success, semantic failure and cancellation. + +Observer-failure behavior and cancellation publication are lifetime decisions +within items 1, 3 and 5. The Product Owner specifies an Effection Stream rather +than a callback registration interface and names it `phases`; its accepted +contract appears in item 3. Parent tracking remains private presentation composition +and changes no identity or permission boundary. No `ExecutionEnvironment` member +is proposed or needed to transport this private reading through inherited +middleware scopes. + +## Item 1 of 5: `ComponentApi.expand` + +**Feature.** Let middleware surround one complete executable element, so the +REPL can follow its progress without wrapping or replacing its implementation. + +**Example.** A `` occurrence enters before resolution. Its +middleware remains attached through prop checks, body execution, projected +content, teardown, accepted return and binding. A nested `` uses the +same observation contract through its structural expansion path. A source branch +never selected has no live occurrence. + +**Current.** `ComponentApi` exposes import, content, capture, modifiers and +failure operations, but no operation surrounds the whole expansion. The closest +established complete wrapper is: + +```ts +interface ExecutionApi { + document(request: DocumentRequest): Operation; +} +``` + +**Proposed addition.** + +```ts +interface ComponentApi { + /** + * Surround one executable element's complete expansion. + * + * Canonical Core issues the request before resolution or validation and + * delegates through this chain once. The request reports the occurrence; + * it carries no definition, props, resource scope or result authority. + * Completion includes owned teardown and final result acceptance. + * Returned values are ignored; Core retains its output, binding and failure + * decisions independently of what a handler returns or catches. + */ + expand(request: ComponentExpansionRequest): Operation; +} +``` + +Add this member to the existing `Component` Api rather than inventing a tracing +namespace. Export the consumer-facing contextual API and its new contracts from +`@executablemd/core/api`, following architecture rule 7. Keep `expandComponent` +and the selected definition private. + +Canonical dispatch uses an occurrence-specific terminal, following the +`Execution.document` request pattern. A handler delegates the exact request with +`next(request)`; returning a value is not producing output or an outcome. A +copied request, another occurrence's request, missing delegation and repeated +delegation cannot manufacture a successful expansion or execute its body twice. +Canonical failure remains failure even if a wrapper catches it. These checks +reuse the established request pattern and do not create durable identities. + +The wrapper encloses actual structural and component expansion, not only the +generator body. For constructs without a component resource scope, completion +follows their existing join/producer teardown. It does not add component resource +lifetimes to structural syntax. A code block remains work inside its containing +element in this slice; it does not gain a fabricated component invocation. + +The observer is installed in the session's entry execution lineage. It does not +own or cancel the invocation and supplies no permission, result or continuation +replacement. The canonical result and failure precedence remain Core's own. +The request is a live observation boundary, never something a cold historical +reader acquires. + +**Decision for item 1: accepted.** The Product Owner confirmed that this is the +intended middleware: it observes a component from start through cleanup so the +REPL can show its progress. `Component.expand(request)` supplies that complete +boundary. Core retains execution, bindings and outcomes; no Journal records are +added. This is a feature decision, not a new reusable architecture rule. + +## Item 2 of 5: `expansion: Expansion` + +**Feature.** Give the REPL one read-only description of the component this +middleware call surrounds, so a progress badge stays beside the right source. + +**Example.** A Plan and its nested Elicit need separate badges. Two File calls +also need separate readings even though their tag names match. The observation +reports the executing occurrence rather than asking the REPL to guess from an +import name or the most recent transcript row. + +**Current.** `getExpansion()` returns the existing detached `Expansion` snapshot: +deterministic `id`, authored `name` and optional `position`. It exposes no props, +definition, resource scope or authority. A middleware hook before body execution +cannot assume that reading this context describes the new occurrence: the body +publishes its snapshot later. The complete hook therefore receives its own +description directly from Core. + +**Proposed request member.** + +```ts +interface ComponentExpansionRequest { + /** + * The actual occurrence this call surrounds, reported by Core. + * Read-only presentation information; it grants no execution capability. + */ + readonly expansion: Expansion; +} +``` + +Core creates a detached, frozen description before dispatch. Every observer of +this call receives that description, including when resolution fails and no +body starts. It supplies no definition, props, bindings, Scope or permission. +The REPL may keep these plain facts in its process-local view after completion; +keeping the description does not keep the invocation alive. No source bytes are +loaded merely to construct it. Identity and source position remain facts reported +by Core rather than facts an observer assigns back to execution. + +**Assessment and proposed type.** Use the existing `Expansion` directly. It +already supplies the deterministic id, authored tag name and optional source +position. Each middleware call has its own request and phases stream, so two +actual executions may carry the same logical id without sharing a stream or a +live badge. The session allocates a private key for each observed call and binds +its enclosing view key around delegation. Repeated executions and concurrent +siblings therefore remain distinct without adding public process keys to Core. + +The existing REPL expansion controller establishes the composition pattern: +`bracket` reads the enclosing walk, allocates its local child and binds it around +`next`. Component body/content hosts inherit the execution lineage, and generated +expansion changes its capability environment while retaining that lineage. Agent +permission attribution continues to use the bridge's actual owning turn; it does +not guess from a shared current badge. The private key/parent reading determines +presentation only. Core never trusts it for durable identity, authorization, +result acceptance or resource lifetime. + +The deterministic source id is not used as a unique process-instance key, and +the private context is not execution authority. This keeps Core's existing +`Expansion` meaning unchanged. Local REPL view types remain delegated under +architecture rules 2, 9 and 11 and the repository's shared-state rule. + +**Decision for item 2: accepted.** The Product Owner accepts +`readonly expansion: Expansion`, reusing the existing Core type and keeping +process keys and nesting in the REPL's live view. Core supplies the frozen +logical id/name/position directly on the request. The member is required; +source position remains optional under its existing contract. + +## Item 3 of 5: `phases` + +**Feature.** Let the REPL follow this expansion's current progress and completion +with an ordinary scope-owned Effection subscription. + +**Example.** A subscriber attaches before delegation and sees ENTER, then ACTIVE. +When the body ends it sees EXIT while cleanup runs. The terminal observation is +delivered after cleanup and result acceptance; the stream then finishes. A view +which attaches later begins at the latest observed phase and receives subsequent +changes. It does not replay or execute the component to discover that phase. + +**Current.** The REPL already exposes Effection Streams for live changes, output +and Agent reading. `Stream` is an operation producing an independent +`Subscription`, and that subscription belongs to its consumer scope. +The Product Owner requests the same abstraction for phases, rather than a +callback registration/disposer. + +**Proposed request member.** + +```ts +interface ComponentExpansionRequest { + /** + * Observe this expansion's latest phase and subsequent changes. + * Each subscription is independent and ends after the terminal observation. + * Subscribing or cancelling a subscription does not start or cancel the body. + */ + readonly phases: Stream; +} +``` + +Subscribe without a gap between the initial phase and subsequent changes. Each +subscriber has its own queue; one reader cannot consume another reader's phase. +There is no replay of preceding phases, retained history, provider call or +terminal reader. A subscription after completion receives the terminal +observation and finishes. The `void` return means the outcome is in the terminal +phase value; stream completion is not a second result authority. + +The session owns its phase consumers and keeps them alive through entry cleanup. +Effection removes a subscription when its consumer scope ends. Removing one +does not release or cancel component work. The component's canonical operation +continues with no reader, and a slow UI does not hold it waiting for a frame +acknowledgment. On cancellation the canonical operation still unwinds first; +the terminal observation describes the completed unwind. If the session itself +is cancelled, its own teardown clears the live view and joins its consumers; +no late delivery may revive a removed entry. + +The exact phase values and completion payload are the next two review items. +This member accepts their transport and lifetime rather than deciding every +state label or error-reporting field. + +**Decision for item 3: accepted.** The Product Owner accepts +`readonly phases: Stream` with independent +scope-owned subscriptions, a current reading followed by subsequent changes, +and completion after unwind. The terminal phase carries the reporting outcome. + +## Item 4 of 5: phase values + +**Feature.** Show preparation, body execution, cleanup and final completion as +different parts of the same expansion, without calling a returned body settled. + +**Example.** The body returns a valid Plan source, but an owned resource is still +closing. Its phase is EXIT until that cleanup finishes and Core accepts its +result. An early failed import never reaches ACTIVE. A cancelled question clears +its wait but keeps EXIT until its unwind completes. + +**Proposed phase type.** + +```ts +type ComponentExpansionPhase = + | { readonly phase: "enter" } + | { readonly phase: "active" } + | { + readonly phase: "exit"; + readonly reason: "returned" | "failed" | "cancelled"; + } + | { readonly phase: "complete"; readonly result: Result } + | { readonly phase: "cancelled" }; +``` + +| Value | Observable meaning | +| --- | --- | +| `enter` | Core began the element and is resolving/validating it; its body has not started. | +| `active` | Core entered the accepted body or structural expansion, including work it owns below it. | +| `exit` | Body work ended, or preparation refused the occurrence. Owned cleanup and final acceptance are not yet finished. The reason describes what began the exit, not its final outcome. | +| `complete` | Core finished cleanup and result acceptance. Successful Result draws SETTLED; failed Result draws FAILED, including semantic failures Core prints. | +| `cancelled` | Cancellation completed its unwind with no canonical failure taking precedence. Draw the existing cancelled wording. A teardown failure taking precedence instead produces `complete` with failed Result. | + +A late result-validation failure may follow EXIT with reason `returned`, because +the body returned before Core rejected its result. An early refusal can leave +ENTER without ever becoming ACTIVE; it still finishes with failed Result. +Cancellation is not successful settlement or a fabricated ordinary failure. + +WAITING remains a private reading of actual Elicit questions, interactive +permissions and owned pause holds. The phase stream does not equate suspension +with waiting for a person. The REPL combines the latest execution phase with +its actual pending wait reasons; it retains the underlying exit phase when +cleanup itself is waiting. Closing a drawer changes no phase or wait. + +Only executed occurrences produce phases. Unselected branches have source but +no live phase. ENTER and EXIT have no minimum display duration; execution does +not wait for a rendered frame. Final phases remain readable in the live session +snapshot, and historical panes receive none of this overlay. + +The Result payload and failure reporting are item 5. This proposal determines +the lifecycle states and their ordering, without granting the observer result +authority or changing canonical failure precedence. + +**Decision for item 4: accepted.** The Product Owner accepts ENTER, ACTIVE, +EXIT with its reason, COMPLETE with Result, and distinct cancellation. WAITING +comes from actual pending questions, interactive permissions and pause holds, +combined with the underlying phase by the REPL. Final completion follows unwind +and result acceptance; no minimum animation duration is added. + +## Item 5 of 5: completion reporting + +**Feature.** Tell the REPL whether this expansion finished successfully, failed +or was cancelled, while Core remains the sole owner of execution results. + +**Example.** A function component prints its own failure and returns normally +through its printing boundary. The component's final phase still reports failed +Result. A parent that recovered a child's failure can finish successfully under +Core's existing recovery rules. A cancellation with clean teardown reports +cancelled; a cleanup failure taking precedence reports failed completion. + +**Current.** Effection `Result` carries success under `value` and failure as +an `Error`. Core's document middleware retains canonical settlement in private +state and reconciles it independently of middleware returns or catches. +`withInvocation` combines body and teardown failures without losing the body's +cause. Those contracts continue to decide expansion and parent outcomes. + +**Proposed completion members.** + +```ts +type ComponentExpansionCompletion = + | { readonly phase: "complete"; readonly result: Result } + | { readonly phase: "cancelled" }; +``` + +This excerpt describes the final two branches of `ComponentExpansionPhase`; +it need not introduce another exported type. Core publishes `Ok(undefined)` for +accepted completion or `Err(reportingError)` for the occurrence's failure. +The observer receives no rendered value, binding, provider object or scope. +The Result describes completion for presentation; Core does not consume it as +the result of executing a component. + +The failure Error is a detached reporting snapshot preserving the selected +failure's existing diagnostic name/message and explanatory Error causes where +Core supplies them. It exposes no original mutable canonical Error or arbitrary +resource object. Core keeps its actual cause graph, identities and authoritative +outcome private and unchanged. No new structured stage or general tracing data +is required for the original badge contract; stage information present in the +existing diagnostic stays available. Phase values and detached Result data are +immutable published observations. + +Final reporting follows the complete middleware dispatch and its cleanup, +after Core selects the effective outcome. A handler's returned value is ignored; +catching a canonical failure cannot change that failure into accepted success. +A middleware refusal or fault follows the existing policy-failure pattern: it +may refuse work or fail a success but cannot rescue a canonical failure. +Durability/Files fatal precedence and body/teardown cause accounting stay as Core +currently defines them. No observer supplies an outcome for Core to rank. + +Phase consumers belong to the session and are not joined from inside the +middleware handler waiting for terminal publication. Otherwise the handler and +publisher would wait for each other. Subscribe before delegation in the +session-owned consumer lineage, which lasts through entry unwind. Consumer +failure follows its ordinary Effection owner; it does not submit a fabricated +completion. Session cancellation joins its owned execution and consumers and +clears the live view. + +Exactly one terminal phase is published for an observed occurrence, followed by +stream completion. Clean cancellation ends with `cancelled`, without inventing +a successful Result or a failure Error. When actual failure wins during unwind, +the final phase is `complete` with failed Result. Observer-installed and +observer-absent conforming runs retain the same canonical output, bindings, +failure disposition and Journal bytes. + +**Decision for item 5: accepted.** The Product Owner accepts reporting-only +`Result` completion and distinct cancellation. Core retains its existing +outcome, failure precedence and cleanup rules. Reporting exposes a detached +diagnostic, never the mutable canonical result or failure objects. + +## Accepted boundary shape + +All members below are accepted. The consolidated contract with documentation, +coverage, lifetime and attribution is in +[pr2-invocation-contract.md](pr2-invocation-contract.md). + +```ts +interface ComponentApi { + expand(request: ComponentExpansionRequest): Operation; +} + +interface ComponentExpansionRequest { + readonly expansion: Expansion; + readonly phases: Stream; +} + +interface Expansion { + readonly id: string; + readonly name: string; + readonly position?: Readonly; +} + +type ComponentExpansionPhase = + | { readonly phase: "enter" } + | { readonly phase: "active" } + | { + readonly phase: "exit"; + readonly reason: "returned" | "failed" | "cancelled"; + } + | { readonly phase: "complete"; readonly result: Result } + | { readonly phase: "cancelled" }; +``` + +`Operation`, `Stream` and `Result` are Effection types; `Expansion` and `SourcePosition` +already exist in Core. The completion event maps successful Result to SETTLED +and failed Result to FAILED. Failure observations carry a detached reporting +Error, never Core's mutable canonical Error. Cancellation has its own terminal +event after unwind. All five boundary items are accepted. Generated-source +presentation and product verification still precede the full PR 2 handoff. + +`Expansion` is the existing detached id/name/position snapshot. Its deterministic +id continues to locate a logical authored element. The session's private reading +adds entry identity, process keys and nesting. None reaches the Journal. + +The Product Owner corrected the callback proposal: lifecycle observation is an +Effection Stream. Each subscription reads the latest phase first, then receives +subsequent transitions in order through its own queue. It finishes after the +terminal observation. A subscription is owned and removed by the consumer's +Effection scope; no public callback registration or disposer is needed. Reading +the stream neither starts another expansion nor owns or cancels the existing +one. The session consumer's lifetime must cover entry teardown, and session +shutdown clears its private live view even if that consumer is itself cancelled. +An absent or slow UI consumer must not hold canonical execution waiting for a +render acknowledgment. Public observations cannot expose the canonical result +object, mutable Error or private failure ledger. Completion data, fault +behavior and cancellation ordering are settled in item 5. Stream semantics follow +the installed Effection `Stream`/`Subscription` types; publisher mechanics remain +an implementation decision under the accepted lifetime contract. + +The Product Owner proposes `expansion` for the description and `phases` for its +stream; these property names are accepted for this feature. The accepted +description type reuses the existing `Expansion` without an additional wrapper. +The property remains required: even a failed import has an element +which Core began expanding. Source position may be absent under its existing +contract. A root occurrence has no enclosing private presentation key. + +WAITING is derived privately from actual questions, interactive permissions and +owned pause holds. It is not every suspended generator, import or Prompt. Wait +reasons are counted independently, clear on their own resolution/cancellation, +and cannot overwrite a terminal outcome. Closing an Answer drawer changes no +wait. A parent may show an outstanding descendant without inheriting every child +failure. Canonical recovery decides the parent's own result. + +## Product verification proposed for PR 2 + +1. Run the original nested Plan journey. Source and occurrence rails remain + readable; a resolved import with its body held remains unfinished. Two sibling + occurrences remain distinct, and generated children belong beneath Evaluate. +2. Hold an Elicit and an interactive permission request. Each waits until its + actual request ends; hiding a drawer changes nothing. Overlapping waits do + not clear one another. Ordinary Agent streaming remains active. +3. Return from a body while cleanup is deliberately held. EXIT stays visible; + final success appears only after cleanup and binding acceptance. Report early + refusal, printed semantic failure, failed result acceptance and cleanup + failure truthfully. A recovered child failure does not automatically fail its + parent. +4. Cancel while waiting. Owned cleanup completes, waits disappear and no late + observer publication revives the occurrence. Preserve Core's established + precedence when cleanup also fails. +5. Inspect an earlier prefix while the live run changes, then return live. The + inspected panes remain prefix-only; returning live shows the latest snapshot. + Cold reopen shows retained facts with no provider call or Journal mutation. + +Lower-level discriminating evidence compares conforming observed and unobserved +runs for identical canonical outcomes and Journal bytes. It uses actual runtime +fixtures rather than invented durable events. Exact commands and the later +visual matrix are frozen by the Planner after product/boundary approval. + +## Continuity + +Accepted direction: middleware feeds the session-owned live lifecycle view; +completion follows teardown; live observations stay separate from retained +inspection; no persistence change. PR 1 feedback remains complete. + +Current review: **all 5 API items accepted** and consolidated in +[pr2-invocation-contract.md](pr2-invocation-contract.md). +All five presentation decisions are also accepted in pr2-source-presentation.md. +The main verification journey is accepted in pr2-product-verification.md. +Canonical static source inspection is accepted in pr2-source-inspection.md. +The ready pr2-planner-handoff.md consolidates all PR 2 contracts. History +adaptation and product verification are accepted in pr3-planner-handoff.md; +the Planner owns complete-story scene mapping and finite evidence. +No persistence question is reopened. diff --git a/.reviewer/issue-881/pr2-architecture-review.md b/.reviewer/issue-881/pr2-architecture-review.md new file mode 100644 index 000000000..38a484b95 --- /dev/null +++ b/.reviewer/issue-881/pr2-architecture-review.md @@ -0,0 +1,178 @@ +# PR 2 — architecture review + +Against the seven frozen structural checks in `pr2-planner-handoff.md`, at +`9d8bc463`. + +The handoff asks the Implementor for this: its documentation-and-handback +section says to return "all review/control/cold evidence", and constrains this +one — "the architecture review uses the seven frozen checks in +pr2-planner-handoff.md; it adds no speculative permutation." So it is written +here, by the person who wrote the code, and it says so rather than pretending +otherwise. + +**What that means for how to read it.** Authorship is mine; confirmation is +not. An author reviewing himself finds what he was already looking for, so +every "met" below is a claim with its evidence attached, offered for the +Planner to confirm or reject — not a verdict that closes anything. Where I +think a check is met, the test or control that would fail if it were not is +named, so confirming it is reading a named thing rather than re-deriving the +diff. + +No criterion is added. Ordinary visual correctness and evidence sufficiency are +the Planner's, and a new structural criterion would need an architecture +amendment rather than a review that quietly grew one. + +Where a check rests on a test, the test is named; where it rests on a control, +the control is named and its record is in `pr2-evidence/.controls.json`. + +--- + +## 1. Core retains canonical execution, delegation, bindings and outcome + +**Met.** + +`ComponentApi.expand` is an observation seam and nothing else. The request Core +issues carries a private-field brand and is claimed once; a handler that +delegates a copy, a counterfeit, the same request twice, a request from another +expansion or no request at all runs no body +(`component-expansion.test.ts` CX1 ×4). What middleware returns is discarded: +the chain's return value reaches no decision, and `Result` is the whole of +what a phase carries, so there is no shape in which an observer could supply an +outcome. + +Failure selection stays Core's. A handler that catches what canonical expansion +raised does not rescue it — the failure is recorded at the point it propagated, +not at the point somebody stopped it (CX3, control **K5**). Bindings never cross +the seam: a phase has a phase name, a `Result` and, on failure, a detached +frozen `Error` with no `cause` chain into the original. + +## 2. Owners and cleanup order intact; consumers neither deadlock nor outlive + +**Met.** + +`withInvocation`'s three ordered teardown stages are unchanged; the observation +is a `settled?` callback told the body's own outcome *before* those stages run, +registered after them so it runs first. It is an observer, not a participant: +nothing it does changes the outcome and it cannot see what the body produced. +An element whose body returned therefore stays in EXIT while its own cleanup +runs (CX2), and cleanup that fails still completes the element as a failure +(CX2). + +The terminal phase follows the whole dispatch, middleware cleanup included — so +a consumer joined inside the handler would wait for the handler. Consumers are +started before the delegation on an owner that outlives it, which is what the +REPL's `lifecycle.ts` does with the session scope. Three cases decide the rest: +a reader that never reads delays nothing, one that takes a phase and stops +delays nothing, and one whose scope is cancelled mid-expansion cancels nothing +(CX4 ×3). Session teardown clears the reading and revives nothing: an entry that +closes takes its observations with it, and a late producer update cannot bring +them back (`repl-lifecycle.test.ts` L3). + +## 3. Generated execution keeps narrowed capabilities; presentation grants none + +**Met.** + +The presentation lineage is an ordinary `Context` bound around the delegation, +which a descendant may rebind — which is exactly why nothing authoritative reads +it. It decides where a call is *shown* and nothing else: no permission, no +durable identity, no reconciliation authority and no capability travels with it. +A generated fragment inherits where it is being shown while its capability +environment stays as narrow as it was (`repl-lifecycle.test.ts` L1). + +The reading is detached and immutable at every hand-off, so a consumer holding +one cannot reach back into the session's state. + +## 4. Inspection uses canonical parsing and runs nothing; replacement is anchored + +**Met.** + +`inspectSource` is the scanner's own walk with an element collector threaded +through it — not a second grammar. A fence, an inline code span, a quoted `>`, a +tag-like expression and an incomplete tag are decided by the same code that +decides them for execution, so the two cannot disagree +(`source-inspection.test.ts`, 12 cases including CRLF, BOM, non-ASCII and header +offsets). No name is resolved, no schema compiled, no prop evaluated, no module +loaded and no component invoked. + +The document envelope is read lexically, and `parseSource` asserts the two agree +— a divergence is loud rather than a quiet offset drift. + +Replacement is anchored in retained ownership and exact ranges: exactly one +`Evaluate` opening at the owner's canonical recorded position, substituting only +`opening.end..closing.start` so the enclosure bytes stay as authored. A refused, +absent or ambiguous admission keeps the producer, and nothing is matched by name +or sibling order (`repl-source-reading.test.ts` S1 ×5, control **K3**). + +## 5. No persistence change; observed and unobserved runs are identical + +**Met.** + +No record type, no field and no write path changed. The claim is decided by +comparison rather than by inspection: an observed run and an unobserved one are +serialized and compared byte for byte — the same elements, the same identities, +the same positions and the same rendered result, through a success, a failure +and a durable eval in one document (CX3). `repl-lifecycle.test.ts` L3 makes the +same comparison through a real session. + +Nothing of the reading reaches the Journal: no offset, width, phase or probe is +retained, and a cold process reconstructs none of it. + +## 6. Inspected content is prefix-only; cold reads do nothing; output has an owner + +**Met.** + +A reading belongs to an entry and its observations are matched on the entry key, +the recorded source position and the fragment that position belongs to — so a +retained prefix, whose lifecycle reading is empty, shows every element as +unobserved rather than borrowing a live one (S4). Live text belongs to the entry +producing it, which is the last the prefix admitted; a reader looking at an +earlier entry is given that entry's retained reading +(`repl-entries.test.ts` EU1). + +Output's owner is read from the typed record, never from the text: a document +whose prose contains `failed` is still output, and a root that closed `err` is a +failure whatever it rendered (S3). Nothing is attributed to an `` or +``, reconstructed by concatenating block results, or invented as a receipt +for a bound value that emitted nothing. + +Cold reads perform no provider activity and no source load: reopening the +settled head left the Journal at 49 022 bytes and the provider log at 8 014, +both with the same SHA-256 before and after (`cold-before.json` / +`cold-after.json`). + +## 7. View data and actions use the existing measured boundary; absent rows cost nothing + +**Met.** + +The reading produces immutable view data through the existing description, +reconciliation, admission and frame-target path. It introduces no second +rendering route: a row is composed as token runs on an ordinary description, and +the runs are drawn by the presentation that already existed. The engine-fit +preparation is measured with independent probe elements under their own +structural ids and its bytes are discarded; it creates no child reader and is +never called from a pure description. + +Windowed-out rows have no node, no target and no Tab stop, because they are not +described — `shown()` slices the admitted range. The two window controls sit +outside the moving content and consume their capacity in the pass that measures +the window, which is what keeps the admitted count and the drawn rows one list. +A narrow frame publishes one routed outlet holding the catalog and the reading, +each with its own measured window, and the surface the route did not choose is +described nowhere — so its rows contribute no resource and no target. + +Inspection owns no execution: `inspectSource` is a pure function over text, and +the reading calls it. + +--- + +## Superseded + +The Planner's `pr2-independent-architecture-review.md` returned REQUEST CHANGES +on checks 1, 4 and 5 at the reviewed commit — a terminal accepting another +invocation's request, a lexical envelope disagreeing with the installed +extractor, and mutable published observations. This file said all seven were +met; on those three it was wrong, which is what a self-review is for the +Planner to catch and did. + +All three are fixed. Read the independent review for the findings and the +handback for the corrections; read this only for the evidence it names. diff --git a/.reviewer/issue-881/pr2-fatal-precedence-architecture-review.md b/.reviewer/issue-881/pr2-fatal-precedence-architecture-review.md new file mode 100644 index 000000000..509198cf2 --- /dev/null +++ b/.reviewer/issue-881/pr2-fatal-precedence-architecture-review.md @@ -0,0 +1,98 @@ +# PR 2 architecture review — fatal-precedence correction + +**PASS** on `ecca5c459b77bed653bcdeab5efd4f9ab656bb2e`. +The fatal-precedence blocker is resolved. No architecture blockers remain for +the PR 2 implementation at this exact commit. + +## Reviewed boundary + +Reviewed local feedback on 2026-10-10. Parent: +`a85c36cb2edc184055b9aa3e270ba1d70b20670f`. Main base: +`160e354e47f6fbeb1c792e6799c1fe26b2f155fc`. + +This is the unpublished correction handed over in +[pr2-fatal-precedence-implementation-handback.md](pr2-fatal-precedence-implementation-handback.md), +on `agent/issue-881-pr2-fatal`. It changes only +`packages/core/src/component-expansion.ts` and its focused test file. +The preceding [architecture re-review](pr2-published-architecture-rereview.md) +remains the historical verdict on `a85c36cb`; this PASS applies to `ecca5c45`. + +The seven frozen checks in [pr2-planner-handoff.md](pr2-planner-handoff.md) +remain the review boundary. The preceding complete review found only failure +selection blocking. This review examines the complete correction, checks it +against established reconciliation and reruns the discriminating evidence. + +## Blocker resolved + +`selectedFailure` examines both canonical and middleware failures after the +complete dispatch unwinds. It uses the existing cause-graph searches and +established ordering: durability first, Files fatal second, then canonical +ordinary failure. Canonical preference within a fatal kind is preserved. +`chainFailed` retains the distinction between no middleware failure and a +middleware operation that raised `undefined`. + +The raised branch selects once. That same selected failure supplies the +authoritative throw and the detached terminal report. The existing reporting +boundary preserves diagnostic name, message and explanatory causes without +exposing canonical failure identity or fatal branding. + +The previously failing public-middleware reproducer now passes for both the +successful-body control and the ordinary-body/fatal-teardown competition. +The four new production-suite regressions pass for persistence precedence, +Files precedence, canonical ordinary-failure precedence and failure after a +successful body. Their terminal-report assertions verify the selected outcome +and reporting detachment. + +The success and refusal paths, once-only delegation, publication, cleanup and +cancellation ownership are unchanged. The correction adds no execution +capability, public API, persistent state, resource owner or session consumer. +Source inspection, generated capability narrowing, prefix isolation and the +measured presentation boundary retain the previously reviewed implementation. +No new architecture decision or amendment is needed. + +## Independent focused evidence + +Ran these checks in the already prepared, clean implementation worktree +`.claude/worktrees/pr2-fatal`, verified at the exact feedback SHA before and +after execution: + +```sh +deno task test packages/core/tests/component-expansion.test.ts packages/core/tests/source-inspection.test.ts packages/core/tests/component-api.test.ts packages/core/tests/invocation-scope.test.ts packages/core/tests/invocation-failures.test.ts packages/core/tests/invocation-identity.test.ts packages/core/tests/expansion-metadata.test.ts packages/core/tests/scanner.test.ts packages/core/tests/document-targets.test.ts packages/core/tests/document-target-execution.test.ts packages/core/tests/evaluate-component.test.ts +# exit 0 — 53 tests / 418 steps +deno task test packages/cli/tests/repl-lifecycle.test.ts packages/cli/tests/repl-agent-execution.test.ts +# exit 0 — 14 tests / 52 steps +git diff --check 160e354e ecca5c45 +# exit 0 +``` + +Saved outputs: [Core](evidence/pr886-ecca5c45-core.log) and +[lifecycle/Agent execution](evidence/pr886-ecca5c45-lifecycle.log). +Total: 67 tests / 470 steps, all passing. + +Adapted only the exact-worktree import paths in the original independent +[reproducer](evidence/pr886-ecca5c45-fatal-precedence.test.ts). Ran from the +repository containing this record: + +```sh +deno test --allow-all --node-modules-dir=manual --cached-only --frozen --config .claude/worktrees/pr2-fatal/deno.json .reviewer/issue-881/evidence/pr886-ecca5c45-fatal-precedence.test.ts +# exit 0 — 1 test / 2 steps +``` + +Its [output](evidence/pr886-ecca5c45-fatal-precedence.log) confirms the prior +failure is corrected independently of the implementation's new tests. +The source digest is +`2aed06e7108ea104ffd6d8ea87b6c258a8e83ee6a1a89e7d325051f1d1b313bb`, matching +the handback's restored implementation. The implementation worktree remains +clean. + +The handback's mutation control is reported evidence; this review did not +repeat the mutation or modify production code. Existing CLI visual evidence +belongs to its recorded revisions and was not recaptured here. No CI was +inspected and no GitHub review was posted. + +## Continuity + +PR 2 architecture review is complete at `ecca5c45`. The reviewed correction +remains local; nothing was pushed or applied to the published stack by this +review. PRs #887 and #889 retain their separate contracts and reviews. This +verdict does not close the complete #881 parity Story. diff --git a/.reviewer/issue-881/pr2-fatal-precedence-implementation-handback.md b/.reviewer/issue-881/pr2-fatal-precedence-implementation-handback.md new file mode 100644 index 000000000..96b8f67d1 --- /dev/null +++ b/.reviewer/issue-881/pr2-fatal-precedence-implementation-handback.md @@ -0,0 +1,249 @@ +# PR #886 — fatal precedence through expansion middleware: implementation handback + +**Corrected at `ecca5c459b77bed653bcdeab5efd4f9ab656bb2e`.** Not pushed; #886, +#887 and #889 are untouched. + +## Base + +| | | +| --- | --- | +| Feedback commit | `ecca5c459b77bed653bcdeab5efd4f9ab656bb2e` (signed, `%G?` = `G`) | +| Parent / exact base | `a85c36cb2edc184055b9aa3e270ba1d70b20670f` | +| Main | `160e354e47f6fbeb1c792e6799c1fe26b2f155fc` | +| Branch | `agent/issue-881-pr2-fatal`, worktree `.claude/worktrees/pr2-fatal` | + +Changed files, 176 insertions / 2 deletions: + +- `packages/core/src/component-expansion.ts` — +39/-2 +- `packages/core/tests/component-expansion.test.ts` — +139 + +The lifecycle-suite cleanup at `a85c36cb` is preserved untouched. + +## Reproduced first + +The Planner's reproducer, adapted to this checkout's relative imports as +`packages/core/tests/zz-fatal-probe.test.ts` (temporary; deleted before the +commit). First failing output, verbatim: + +``` +{"bodyFails":false,"thrown":{"name":"DurablePersistenceError",…},"fatalPreserved":true} +{"bodyFails":true,"thrown":{"name":"Error","message":"ordinary body failure"},"fatalPreserved":false} +Expected: [DurablePersistenceError: Failed to persist durable yield event] +Received: undefined +FAILED | 0 passed (1 step) | 1 failed (1 step) +``` + +The positive control (`bodyFails=false`) already preserved the persistence +failure; only the competition lost it. + +## The correction + +`observeExpansion` captured `chainFailure`, then reported and threw +`settlement.raised` without consulting it. Both halves can fail — the body +raises, and middleware's own unwind raises something else on the way out — and +the canonical half was winning unconditionally. + +A new private `selectedFailure(canonical, laterFailed, later)` sits beside +`observeExpansion` and reconciles after the whole dispatch has unwound, in the +order `rankBoundFailure` in `expand.ts` already ranks bound failures: + +1. `durabilityFailure(canonical) ?? durabilityFailure(later)` +2. else `filesFatalFailure(canonical) ?? filesFatalFailure(later)` +3. else `canonical` + +`??` on the canonical side first keeps the existing preference for the earlier +failure within each fatal kind. `laterFailed` gates the middleware side, so the +distinction between "no failure" and "raised `undefined`" survives — a raised +non-Error value still reaches `reported(String(value))` unchanged. + +The raised branch now computes `selected` once and uses the same value for the +authoritative `throw` and for the single `Err(reported(selected))` terminal +observation, so the report cannot name a different failure from the one that +escaped. + +Deliberately scoped: the `"absent"` (refusal) branch and the `chainFailed` +success branch are unchanged — rule 4 ("canonical succeeded, middleware failure +still fails the expansion") already held there, and the regression keeps it as +the positive control rather than rewriting the path. No shared helper with +`expand.ts`: the two reach the decision with different shapes, and a common +helper would be a third boundary to keep in step. No resource owner, public API, +dependency or persistence change. + +One non-behavioral repair in the same file: the first draft inserted the new +helper between `observeExpansion`'s docstring and `observeExpansion`, orphaning +the docstring onto the helper. The helper and its own docstring now precede it. + +## Regressions + +Four cases in `packages/core/tests/component-expansion.test.ts`, all driven +through the suite's existing `watch()` helper — the public +`Component.around({ expand })` chain and the real `expandSegments` boundary, not +a direct call to `observeExpansion`: + +| Case | Asserts | +| --- | --- | +| `CX3: durability raised while middleware unwinds outranks the body's failure` | `durabilityFailure(failure)` is the `DurablePersistenceError` **by identity**; the terminal report is named/messaged for it, carries its explanation, and is detached | +| `CX3: a Files fatal raised while middleware unwinds outranks the body's failure` | `filesFatalFailure(failure)` is the `FilesProviderUnavailableError` by identity; same report assertions | +| `CX3: a later ordinary middleware failure does not displace the body's` | the body's failure propagates and is reported; the unwind's message appears nowhere | +| `CX3: a body that succeeded still fails when middleware's unwind raises` | positive control: no competition, same failure is the outcome, nothing rendered | + +Detachment is asserted on the report, not merely on the thrown failure: +`report !== raised`, `Object.isFrozen(report)`, and — the branding check — +`durabilityFailure(report)` / `filesFatalFailure(report)` are both `undefined`. +The report conveys the selected name, message and explanatory cause while +recognizing as neither a durability nor a Files fatal failure, so catching an +observation cannot be mistaken for catching the failure. + +A small local `reportedBy(watched)` reads the terminal `complete` phase and +throws if the element did not complete with a failure, rather than casting. + +Existing publication, rescue and once-only checks are untouched. No permutation +matrix was added. + +## Mutation control + +Restored the pre-fix selection in place — +`const selected = selectedFailure(settlement.raised, chainFailed, chainFailure);` +→ `const selected = settlement.raised;` — and re-ran the suite: + +``` +CX3: durability raised while middleware unwinds outranks the body's failure ... FAILED + Expected: [DurablePersistenceError: Failed to persist durable yield event] + Received: undefined +CX3: a Files fatal raised while middleware unwinds outranks the body's failure ... FAILED + Expected: [FilesProviderUnavailableError: Files provider is not installed] + Received: undefined +CX3: a later ordinary middleware failure does not displace the body's ... ok +CX3: a body that succeeded still fails when middleware's unwind raises ... ok +FAILED | 0 passed (26 steps) | 1 failed (2 steps) +``` + +Both competition cases break and reproduce the original symptom exactly +(`Received: undefined`). The ordinary-precedence case and the positive control +stay green under the mutation, which is what shows they are not restating the +fix. + +Restoration verified by digest, not by eye — `shasum -a 256` of +`component-expansion.ts` before the mutation and after the restore: +`2aed06e7108ea104ffd6d8ea87b6c258a8e83ee6a1a89e7d325051f1d1b313bb`, `OK`. All +focused commands below were run after that restoration. + +## Focused commands + +| Command | Result | +| --- | --- | +| `deno task test packages/core/tests/component-expansion.test.ts` | `ok \| 1 passed (28 steps) \| 0 failed` | +| frozen Core command (11 suites) | `ok \| 53 passed (418 steps) \| 0 failed` | +| `deno task test packages/cli/tests/repl-lifecycle.test.ts packages/cli/tests/repl-agent-execution.test.ts` | `ok \| 14 passed (52 steps) \| 0 failed` | +| `deno check` on both changed files | clean | +| `pnpm lint` | exit 0; no diagnostic on either changed file | +| `git diff --check 160e354e HEAD` | clean | + +No full corpus, gallery rerun or CI wait, per the handoff. + +## Next action + +Return the corrected execution boundary for Architect review and Planner +accept-or-request-changes. Stopped before pushing, updating PRs, merging or +touching the dependent stack. + +## Pushed and restacked (authorized follow-up) + +The correction is on #886, and the two dependent PRs were rebased onto it so +they carry both pr2 commits rather than branching below them. + +| PR | Branch | Was | Now | Push | +| --- | --- | --- | --- | --- | +| #886 | `agent/issue-881-pr2` | `a85c36cb` | `ecca5c45` | fast-forward | +| #887 | `agent/issue-881-pr3` | `ad4a0d4d` | `a9905f3c` | forced, lease held | +| #889 | `agent/issue-881-pr4` | `db4896fc` | `f3024b6b` | forced, lease held | + +`origin/agent/issue-881-pr3` had branched from `3815aef4` — the pr2 tip *before* +the lint fix `a85c36cb` — so neither #887 nor #889 had ever carried it. Both +now do, which is what the restack was for. + +Rebased in a dedicated `.claude/worktrees/restack-881` detached checkout, so no +other worktree's branch was moved: `--onto ecca5c45 3815aef4` for pr3's seven +commits, then `--onto a9905f3c ad4a0d4d8` for pr4's two. No conflicts — +`a85c36cb` touches only `repl-lifecycle.test.ts` and `ecca5c45` only +`packages/core/`, and neither pr3 nor pr4 touches either path. + +Verified rather than assumed: + +- All nine replayed commits are signed (`%G?` = `G` for each). +- `git diff ad4a0d4d a9905f3c` and `git diff db4896fc f3024b6b` are each + *exactly* `git diff 3815aef4 ecca5c45` — 3 files, +301/-143. The two + dependent slices' own content is byte-identical to what was reviewed; only + the inherited base changed. +- On the restacked top of the stack (`f3024b6b`), the three slices' focused + suites together: `ok | 81 passed (261 steps) | 0 failed` + (`component-expansion`, `repl-lifecycle`, `repl-source-reading`, + `repl-presentation-style`, `repl-journey`, `repl-entries`, + `repl-layout-admission`). +- GitHub agrees: #886 `ecca5c45` → `main`, #887 `a9905f3c` → pr2, #889 + `f3024b6b` → pr3, all three MERGEABLE, diffs 40/20/8 files with no + cross-contamination. + +Left stale on purpose: the local branches in the `issue-881-pr2`, `-pr3` and +`-pr4` worktrees still point at `acadbbdb`, `05ba70d5` and `db4896fc`. Git +refuses to move a branch checked out elsewhere, and those are other worktrees' +to reset. The PRs track the remote, which is correct. + +## #886 merged; the stack moved onto main + +You squash-merged #886 at 10:01:53Z as `9fe494d7` and the branch was deleted, so +GitHub retargeted #887's base to `main` and it went CONFLICTING — its history +still carried the pr2 commits that main now holds squashed. `git diff ecca5c45 +9fe494d7` is empty, so the squash is content-identical and the replay is safe. + +Rebased both remaining slices onto the new main, dropping the absorbed commits: + +| PR | Branch | Base | Head | Own commits | +| --- | --- | --- | --- | --- | +| #887 | `agent/issue-881-pr3` | `main` (`9fe494d7`) | `3edcee39` | 8 | +| #889 | `agent/issue-881-pr4` | `agent/issue-881-pr3` | `6749fa8c` | 2 | + +`--onto origin/main ecca5c45` for #887's eight commits, then +`--onto 3edcee39 ff7a2f8d` for #889's two. Both clean. Every replayed commit +signed. `git diff` between each old and new tip is **empty** — identical trees, +so nothing of either slice's content changed when its base did. + +Both now MERGEABLE: #887 20 files / +3048/-236 against main, #889 8 files / ++923/-69 against #887. + +## #887's test-node failure, found and fixed + +All ten `test-node (n/10)` shards failed on #887, and `test-node` is a `green` +dependency. Not the rebase, and not a test: the **Typecheck** step, which runs +before the tests and is identical on every shard. + +``` +packages/cli/tests/repl-history.test.ts(174,22): error TS2550: Property 'toSorted' does not exist on type 'number[]' +packages/cli/tests/repl-history.test.ts(426,33): error TS2550: Property 'toSorted' does not exist on type 'string[]' +packages/cli/tests/repl-history.test.ts(593,45): error TS2339: Property 'toSorted' does not exist on type 'readonly number[]' +Process completed with exit code 2. +``` + +`tsconfig.node.json` pins `"lib": ["ES2022"]`; `toSorted` is ES2023. The three +calls are PR 3's own, in a file it creates. Reproduced locally in under a +minute with `pnpm exec tsc --project tsconfig.node.json --noEmit` — the same +three errors — rather than from CI logs. + +Three gates said yes and only the CI-only one said no: `deno check`, +`deno task test` and `pnpm lint` all pass, and oxlint's +`unicorn(no-array-sort)` actively *recommends* `toSorted` over mutating +`sort()`. That is why it reached CI at all. + +Fixed in `ff7a2f8d` (now `7789b21f` after the main rebase): sort a copy. That +keeps what `toSorted` was chosen for — `group.ordinals` arrives `readonly`, and +nothing observes the order of the array sorted at either other site. +`Object.keys` already returns a fresh array, so that one sorts in place; oxlint +flagged my first attempt's spread there as redundant, and it was right. One +comment at the first site gives the reason, so the next reader does not restore +`toSorted`. + +After the fix: `tsc --project tsconfig.node.json --noEmit` exit 0; +`repl-history.test.ts` `ok | 6 passed (24 steps) | 0 failed`; `deno check` +clean; `pnpm lint` exit 0. Re-run after the second edit, not just the first. +Three `no-array-sort` warnings remain and are the lib's cost, not a regression — +`pnpm lint` exits 0 with warnings, and main already carries others. diff --git a/.reviewer/issue-881/pr2-fatal-precedence-implementation-handoff.md b/.reviewer/issue-881/pr2-fatal-precedence-implementation-handoff.md new file mode 100644 index 000000000..08548b4e5 --- /dev/null +++ b/.reviewer/issue-881/pr2-fatal-precedence-implementation-handoff.md @@ -0,0 +1,134 @@ +# PR #886 — preserve fatal failures through expansion middleware + +**REQUEST CHANGES at `a85c36cb2edc184055b9aa3e270ba1d70b20670f`.** + +Correct the component expansion boundary so a persistence or Files fatal failure +raised during middleware teardown remains the authoritative outcome even when +the component body already failed ordinarily. The ordinary body error currently +hides that fatal failure. + +This consolidates the Architect's exact-head re-review in +[pr2-published-architecture-rereview.md](pr2-published-architecture-rereview.md) +and the Planner's independent current-head reproduction. It implements the +existing invocation contract and frozen structural check 1. No product decision +or architecture amendment is outstanding. + +## Base and scope + +Work from PR #886 head `a85c36cb2edc184055b9aa3e270ba1d70b20670f`, parent +`3815aef4eb72000c2c59f8b06a8e01ed8c9070b5`, against main +`160e354e47f6fbeb1c792e6799c1fe26b2f155fc`. Preserve the current lifecycle-test +cleanup: it removes redundant scopes, retains the comparison's separate run +scopes and passes all eight steps. That change contains no production repair. + +Read repository AGENTS.md, the required Effection instructions, architecture.md, +the affected executable-MDX sections and the Architect's re-review. The +original PR 2 implementation handoff and invocation contract remain governing +documents. + +Own the correction in `packages/core/src/component-expansion.ts` and focused +regressions in `packages/core/tests/component-expansion.test.ts`. Reuse existing +error classification and reconciliation semantics. Do not refactor unrelated +boundaries merely to share a helper. + +#885 is merged. #887's History slice and #889's responsiveness slice are +dependent work with separate contracts and reviews. Do not repair this defect +in a descendant, rewrite their behavior, rebase the stack, or update those PRs +as part of this feedback task. + +## Reproduce before changing code + +Use the Architect's exact-head reproducer at +`evidence/pr886-a85c36cb-fatal-precedence.test.ts`, or the Planner's copy at +`pr886-planner-review-evidence/fatal-precedence.test.ts`. Their absolute imports +name the retained review worktrees; adapt them to the implementation checkout +before using them as local evidence. Put the permanent regression in the +existing Core suite rather than depending on these local paths. + +The public `Component.around({ expand })` handler delegates the exact request +once. A function component throws an ordinary body error. The middleware's +synchronous `finally` then raises a genuine `DurablePersistenceError`. + +Expected: the persistence failure wins. Actual: `observeExpansion` selects the +ordinary canonical failure, and `durabilityFailure(caught)` is undefined. The +same middleware after a successful body preserves the persistence failure and +serves as the positive control. Keep the first failing output. + +## Required correction + +`observeExpansion` captures `chainFailure` at lines 369–371, but its raised +canonical settlement branch at lines 377–380 reports and throws the canonical +error before examining the middleware failure. Reconcile both after the full +middleware dispatch has unwound, following `reconcileExpansion` in execute.ts +and `rankBoundFailure` in expand.ts: + +1. Durability failure wins across either outcome. +2. Otherwise, Files fatal failure wins across either outcome. +3. Otherwise, an ordinary canonical failure wins over a later ordinary + middleware failure. Middleware cannot rescue canonical failure by catching it. +4. When canonical work succeeded, middleware failure still fails the expansion. + +Within each fatal kind, preserve the existing preference for the earlier +canonical failure. Preserve the distinction between no failure and a raised +value, including non-Error values. + +Use the same selected outcome for the authoritative throw and detached terminal +report. Publish exactly one terminal observation after cleanup. The reporting +Error remains detached and immutable: it conveys the selected diagnostic and +explanations without exposing the canonical Error's identity, resource handles +or fatal branding. + +Preserve exact-request delegation, once-only execution, private canonical +result acceptance, cancellation and cleanup ownership, existing failure +precedence, subscriber independence, and observed/unobserved execution +equivalence. Add no resource owner, public API, dependency or persistence change. + +## Frozen focused evidence for this correction + +Add regressions through the public expansion middleware and actual expansion +boundary for: + +- Ordinary body failure competing with a middleware teardown persistence + failure: persistence wins. +- The corresponding Files fatal competition: Files fatal wins. +- Ordinary body failure competing with a later ordinary middleware failure: + the canonical failure remains authoritative. +- Successful body followed by fatal middleware teardown: retain the positive + control. + +Assert the selected authoritative outcome and the corresponding detached +terminal report, including its detachment. Retain the existing publication +checks for one terminal phase after cleanup and the existing canonical-failure +rescue/once-only tests. Use the accepted precedence above when reviewing any +shared reconciliation helper's existing tests; do not add a permutation matrix +without a distinct missing invariant. + +The regression must fail on `a85c36cb`; restore the old selection in a controlled +local mutation after the fix and require the persistence competition to fail +again. Preserve the first substantive failure and verify exact source-byte +restoration before final focused checks. + +Run the boundary regression first, then the frozen affected Core command: + +```sh +deno task test packages/core/tests/component-expansion.test.ts packages/core/tests/source-inspection.test.ts packages/core/tests/component-api.test.ts packages/core/tests/invocation-scope.test.ts packages/core/tests/invocation-failures.test.ts packages/core/tests/invocation-identity.test.ts packages/core/tests/expansion-metadata.test.ts packages/core/tests/scanner.test.ts packages/core/tests/document-targets.test.ts packages/core/tests/document-target-execution.test.ts packages/core/tests/evaluate-component.test.ts +deno task test packages/cli/tests/repl-lifecycle.test.ts packages/cli/tests/repl-agent-execution.test.ts +git diff --check 160e354e HEAD +``` + +No full runtime corpus, gallery rerun or CI wait is required for this feedback +commit. Delivery verification remains separate. + +## Handback and next action + +Commit promptly once focused evidence passes. Return the exact signed feedback +SHA, parent, base, changed files, every focused command/result, the original +failure, the restored mutation control and the selection/reporting evidence. +Return the corrected execution boundary for Architect review and Planner +accept-or-request-changes. Stop before pushing, updating PRs, merging or changing +the dependent stack. + +Continuity: exact base `a85c36cb2edc184055b9aa3e270ba1d70b20670f`; artifact +`pr2-fatal-precedence-implementation-handoff.md`; established failure ordering +above is settled; one reproduced fatal-precedence blocker remains; next +Implementor action is to reproduce it and correct the boundary. diff --git a/.reviewer/issue-881/pr2-fatal-precedence-planner-acceptance.md b/.reviewer/issue-881/pr2-fatal-precedence-planner-acceptance.md new file mode 100644 index 000000000..88260a433 --- /dev/null +++ b/.reviewer/issue-881/pr2-fatal-precedence-planner-acceptance.md @@ -0,0 +1,78 @@ +# PR #886 fatal-precedence correction — Planner acceptance + +**PASS at `ecca5c459b77bed653bcdeab5efd4f9ab656bb2e`.** + +The correction satisfies +`pr2-fatal-precedence-implementation-handoff.md`. The reproduced fatal-precedence +finding is closed for Planner review. This record does not issue the separate +Architect review verdict requested by that handoff. + +## Reviewed revision + +- Branch: `agent/issue-881-pr2-fatal`. +- Exact parent: `a85c36cb2edc184055b9aa3e270ba1d70b20670f`. +- Recorded main base: `160e354e47f6fbeb1c792e6799c1fe26b2f155fc`. +- Signature: valid (`G`). Worktree: clean. +- Delta: only `packages/core/src/component-expansion.ts` and its existing test + suite. The lifecycle-test cleanup is unchanged. + +## Finding closure + +The raised canonical-settlement branch now examines both the canonical failure +and the middleware-chain failure after unwind. The private selector applies +the established order: durability first, Files fatal second, canonical ordinary +failure otherwise. Canonical-first nullish selection preserves the earlier +failure within each fatal kind. A separate chain-failed flag preserves failure +presence independently of its raised value. The absent and successful canonical +branches retain their existing behavior. + +One selected value feeds the authoritative throw and the detached terminal +report. Existing terminal publication still occurs after dispatch unwind and +uses the once-only terminal guard. No public API, persistence, cancellation +owner or subscriber lifetime changes. + +The four new regressions use public expansion middleware and real expansion. +They prove persistence and Files fatal competition, ordinary canonical +precedence, and the successful-body fatal control. The fatal reports preserve +the selected diagnostics while remaining frozen, distinct from the canonical +Error, and without its fatal branding. Existing publication, teardown, rescue +and once-only checks remain green. + +The Planner independently reran the original two-case reproducer against this +exact checkout. Both cases now throw the original DurablePersistenceError and +report `fatalPreserved:true`; the ordinary-body competition failed at the +parent in the previous review. The supplied mutation record restores the old +selection and breaks both competition assertions while preserving the ordinary +case and positive control. Its reported restored SHA-256 matches the current +source: `2aed06e7108ea104ffd6d8ea87b6c258a8e83ee6a1a89e7d325051f1d1b313bb`. +The Planner did not rerun the mutation against the implementation worktree. + +## Independent commands + +Run from `.claude/worktrees/pr2-fatal`: + +```sh +deno task test packages/core/tests/component-expansion.test.ts packages/core/tests/source-inspection.test.ts packages/core/tests/component-api.test.ts packages/core/tests/invocation-scope.test.ts packages/core/tests/invocation-failures.test.ts packages/core/tests/invocation-identity.test.ts packages/core/tests/expansion-metadata.test.ts packages/core/tests/scanner.test.ts packages/core/tests/document-targets.test.ts packages/core/tests/document-target-execution.test.ts packages/core/tests/evaluate-component.test.ts +# 53 tests / 418 steps; exit 0 + +deno task test packages/cli/tests/repl-lifecycle.test.ts packages/cli/tests/repl-agent-execution.test.ts +# 14 tests / 52 steps; exit 0 + +deno test --allow-all --node-modules-dir=manual --cached-only --frozen --config deno.json /private/tmp/pr886-fatal-review-ecca5c45/fatal-precedence.test.ts +# Original reproducer: 1 test / 2 steps; exit 0 + +git diff --check 160e354e HEAD +# exit 0 +``` + +Outputs and the exact-head probe are retained in +`pr2-fatal-precedence-planner-evidence/`, with a SHA-256 manifest. No full corpus, +gallery rerun, production edit, commit, push, PR update or CI inspection was +performed by this review. + +## Next action + +Return `ecca5c459b77bed653bcdeab5efd4f9ab656bb2e` and the handback to the +Architect for the requested execution-boundary re-review. No Planner blocker +remains for this correction. The Implementor remains stopped before publication +or dependent-stack changes. Delivery verification remains separate. diff --git a/.reviewer/issue-881/pr2-implementation-handback.md b/.reviewer/issue-881/pr2-implementation-handback.md new file mode 100644 index 000000000..7f3895917 --- /dev/null +++ b/.reviewer/issue-881/pr2-implementation-handback.md @@ -0,0 +1,564 @@ +# PR 2 — follow execution and read its result + +Implementor handback for `.reviewer/issue-881/pr2-implementation-handoff.md`. +Not pushed; no PR opened. + +| | | +| --- | --- | +| Branch | `agent/issue-881-pr2` | +| Head | `acadbbdb` (full SHA in `pr2-evidence/revision.txt`) | +| Parent | `9163a16b` | +| Integrated base | `c7d54769` = accepted PR 1 `080b6ec80ca74e614789e8d2252857ac281df7e5` + main `4c0414be1010f69f11bff0d1d634623a5b08f886`, merged mechanically with no conflict | +| Commits on the base | 17 | +| Gallery | `.reviewer/issue-881/pr2-evidence/` — 44 pairs, 16 contact sheets, captured from this unchanged head | + +## The frozen focused commands, and what they returned + +Run from the prepared implementation worktree at `acadbbdb`, **exactly as the +handoff writes them**. + +``` +deno task test packages/core/tests/component-expansion.test.ts \ + packages/core/tests/source-inspection.test.ts packages/core/tests/component-api.test.ts \ + packages/core/tests/invocation-scope.test.ts packages/core/tests/invocation-failures.test.ts \ + packages/core/tests/invocation-identity.test.ts packages/core/tests/expansion-metadata.test.ts \ + packages/core/tests/scanner.test.ts packages/core/tests/document-targets.test.ts \ + packages/core/tests/document-target-execution.test.ts packages/core/tests/evaluate-component.test.ts +→ ok | 53 passed (414 steps) | 0 failed exit 0 + +deno task test packages/cli/tests/repl-source-reading.test.ts \ + packages/cli/tests/repl-execution.test.ts packages/cli/tests/repl-entries.test.ts \ + packages/cli/tests/repl-layout-admission.test.ts packages/cli/tests/repl-presentation-style.test.ts \ + packages/cli/tests/repl-forms.test.ts packages/cli/tests/repl-journey.test.ts \ + packages/cli/tests/repl-agent-journey.test.ts +→ ok | 94 passed (316 steps) | 0 failed exit 0 +``` + +The previous handback folded two more files into the CLI half. That was the +frozen command altered, so it is undone: the command above is the handoff's, +unchanged, and the two files are reported beside it rather than inside it. +`repl-lifecycle.test.ts` and `repl-agent-execution.test.ts` hold this slice's +session reading and its waiting reasons, so the rows L1–L3 are decided there: + +``` +deno task test packages/cli/tests/repl-lifecycle.test.ts \ + packages/cli/tests/repl-agent-execution.test.ts +→ ok | 14 passed (52 steps) | 0 failed exit 0 +``` + +git diff --check → clean +deno check --frozen packages/core packages/cli/src → 0 errors +``` + +Reported actual results, not an acceptance number. The whole CLI corpus was also +run at the previous head (`b1264a6d`): **290 passed (1423 steps), 0 failed**; it +is not re-run here because the handoff says no full corpus precedes the feedback +commit. + +## What was built + +**Layer 1 — the canonical invocation is surrounded.** `ComponentApi.expand` +dispatches one branded request per expansion, claimed once; a handler delegates +it or refuses, and decides nothing about the outcome. Settlement is readable +whether or not the chain returned. Phases are ENTER, ACTIVE, EXIT and then one +terminal COMPLETE or CANCELLED carrying `Result` and a detached frozen +report — no canonical identity, binding or resource crosses. Completion follows +the whole dispatch, middleware cleanup included. Subscriptions register with the +latest phase and then receive each change in order; a slow, absent or cancelled +reader delays and cancels nothing. Every authored path is surrounded: components, +``, ``, ``, ``, ``, the selected ``, the +`` that runs, and each ``. + +**Layer 2 — static boundaries without execution.** `inspectSource(text, kind)` +answers where each recognized element's delimiters are, from the scanner's own +walk, with no name resolved, no schema compiled, no prop evaluated and no +component invoked. The document envelope is read lexically and `parseSource` +asserts the two agree, so a divergence is loud rather than a quiet offset drift. + +**Layer 3 — a session-owned live reading.** Private `lifecycle.ts`: one +occurrence key per actual call, lineage bound around the delegation with +`Context.with`, consumers run on the session's own owner so they outlive the +dispatch, waits counted per element by whoever actually waits, and the whole +reading dropped when the entry closes. `Component.expand` is classified as a +gate in the boundary inventory. The liveness release moved into the entry's +finalizer. + +**Layer 4 — the reading on the screen.** `source-reading.ts` turns one model +entry into Output and then Source; `fitting.ts` cuts that reading to the +transcript's measured inner width by asking the engine how wide text actually +is. Rails say which region a row is in; badges say what the element owning it is +doing, glyph and word, against the pane's right inner edge, on each delimiter's +first row only. Generated source replaces its producer inside the enclosure +bytes the author wrote and keeps its own offsets as a child region. The reading +has its own process-local window, keyed by execution, prefix and entry, with +`[↑ earlier]`/`[↓ later]` outside the moving content. + +**Specifications.** `architecture.md` (the `Component.expand` capability row, +the expansion-observation section, three REPL module rows), +`specs/executable-mdx-spec.md` §5.7 and §5.8, `specs/repl-spec.md` (observation +versus syntax, output and source, canonical inspection, wrapping, arrow labels). +Present tense; recovery, resource ownership and prefix isolation preserved; it +states explicitly that observations are ephemeral and that static syntax or a +retained admission does not prove active execution. Core root and `/api` exports +remain distinct. + +## R4, from the re-review + +`pr2-planner-rereview.md` closed R1–R3 and every housekeeping finding, and +found one blocking defect left. + +**A question's preview lost long lines.** The message was split at its newlines +and each logical line became one drawer row. A drawer row is one row — so a +long line had nowhere to put its tail, and a window can only scroll to rows +that were prepared. At 72×20 the README confirmation showed +`"summary": "A lightweight workspace for coordinati` and no continuation, in +all eleven windows the review walked. Approve stayed reachable, which is why +reaching the controls never caught it. + +The preview is now fitted by the same engine-measured wrapping the reading +uses, at the drawer's own width, prepared in `prepareFrame` beside it. Its rows +are what the description places, what the window counts and what a scroll moves +through. `fitPlain` is the reading's cutting without the rail and status +reservation: read-only text in a box uses all of the box. + +`drawerContentRows` is deleted. The review cited it as counting logical lines, +which it did — and nothing called it. A dead function stating a rule the +product no longer follows is worse than no function. + +**The regression took two corrections, both worth recording.** Asserting on +description labels proved nothing: a label always held the whole line, and the +loss happened at the row. Asserting the decisions stay reachable proved nothing +either — the reviewed build satisfied that. What discriminates is that no +message row is wider than the drawer it was measured for, together with every +logical line being recoverable from the rows it was cut into. **K14** restores +one row per logical line and fails on `drawer:message:4` overflowing. + +**And the terminal agrees.** `pr2-evidence/preview-traverse.py` walks the real +confirmation at 72×20 the way the review did — thirteen windows, through the +drawer's own control — and `preview-traverse.json` records every row it saw: +the tail `agents."` is present and the whole summary is recovered from the +fragments. Worth noting the needle: the value now wraps as +`A lightweight workspace for` / `coordinating coding` / `agents."`, so the +review's contiguous `ng coding agents.` appears in no window and my first probe +reported a false failure on it. The frozen gallery capture +`plan-review-160x36.txt` shows the same fix on the Plan schema: it continues +past `description: "Name` instead of stopping there. + +## The Planner's journey review, and the three things it found beyond R1–R3 + +`pr2-planner-review.md` returned REQUEST CHANGES alongside the independent +structural review. Its journey findings and packet findings were all mine, and +all are fixed: + +**A 2.8 MB test log was committed into the branch.** `.cliall.log` entered at +`108fa00c` and `.controls.json` at `a210e4eb`, and +`git diff --check c7d54769..HEAD` exits 2 on the log's trailing whitespace. I +had been running `git diff --check` against the *working tree*, which is clean +and checks nothing about the committed change — so this gate had been failing +for six commits while I reported it passing. Both files are removed and +`.gitignore` names them; the endpoint check now exits 0. + +**K1 was not the control it claimed.** It said "remove the rails" and +recoloured one. Making it actually remove them returned **UNBROKEN**: every +case read `line.rail`, the model's answer, and nothing asserted a rail reaches +a row — the reading could have lost its rails entirely and the suite would have +passed. There is now a case checking that each composed row opens with the rail +glyph under the role naming its region, with an observed rail among them so +painting every row alike does not satisfy it. K1 removes the rails and fails. +The recolouring mutation stays as **K1b**, named for what it does. + +**A control record kept only the matcher line.** The runner now preserves the +whole first failure; K1's reads `- "│" + " "` against the row key. + +The review also records that the evidence packet was being rebuilt while it was +read — only 37 of 319 listed files matched, and the manifest and sheets were +absent. The packet is now built once from the reviewed SHA and checksummed +last, and `shasum -c` verifies every listed file against the tree. + +Its own live walk stopped at step 3's approval on a missing Plan session +directory, with another evidence run active against the same host storage. The +review names that as a possible cause rather than an established one, keeps the +remaining live steps, and says not to reassign them. They are not reassigned +here. + +**The other run was mine**, and the collision is now impossible from my side. +On macOS the REPL keeps its histories under `$HOME/Library/Application Support` +and the Plan provider keeps its sessions under `$HOME/.xmd`, with no override +for either — so my gallery harness and a concurrent review walk were writing to +and deleting from the same directories. The harness is given a home of its own +(`DENO_DIR` still points at the real module cache, because `--cached-only` has +to find what is there). The journal this packet's cold counters measure is now +under `/private/tmp/xmd-881-pr2-home/...`, which the counter files record. + +This does not establish the cause of that failure — only that a review run +after this revision will not be sharing storage with mine. + +**The same change would protect the review run itself, and has not been made +to it.** `pr2-planner-evidence/harness.py` still resolves the journal under the +real home (line 399, `/Users/…/Library/Application Support/xmd/repl/…`) and +sets only its own `CWD` (line 24). So the remaining live steps are still +exposed to *any* other run on this Mac, not only to mine — and three other +sessions are open on it. I have not touched that file: it is the review's +harness and its evidence, and editing either would contaminate what the +Planner is measuring with. + +The change, if wanted, is the one in `pr2-evidence/harness.py`: give the tmux +command its own `HOME` and keep `DENO_DIR` on the real module cache so +`--cached-only` still resolves — + +```python +HOME = pathlib.Path("/private/tmp/xmd-881-planner-home") +COMMAND = " ".join(["HOME=%s" % HOME, "DENO_DIR=%s/Library/Caches/deno" % pathlib.Path.home(), ...]) +``` + +— and read the journal from `HOME / "Library" / "Application Support" / …` +instead of the user's. On macOS neither path has an environment override, which +is why the collision is possible at all. + +## The Planner's independent review, and what it found + +`pr2-independent-architecture-review.md` returned **REQUEST CHANGES** with +three findings against the reviewed commit. All three reproduced on the +Planner's own probe, all three are fixed, and the probe now passes clean: + +**R1 — a terminal carried a request its invocation did not issue.** The brand +check proved a request was Core's and unspent; nothing proved it was *this* +element's. An authentic, unconsumed request belonging to another live +invocation, delegated through this one's `next`, reached the claim — it spent +that element's one claim and ran this body, and the refusal that followed came +after the effect had happened. Each terminal now compares the delegated +request with the one it issued, by identity, before the claim and before any +body. The probe went from `bodies:["A"]` to `bodies:[]`. + +**R2 — the lexical envelope disagreed with the installed extractor**, and the +assertion I added to `parseSource` turned that disagreement into a refusal of +documents the engine accepts: a BOM with no header, an unterminated header, and +a closing delimiter with text after it. I had written the helper from the +delimiter prose; I derived the real rule by comparing against `matter()` over +twenty-four envelope shapes. A BOM is never body even with no header; an opener +with no closing line consumes the whole text; a closing line *starts with* +`---`, and the body begins immediately after those three characters plus one +line ending if one is there. + +One of my own C5 cases asserted the opposite of all of this — +`SI2: an unterminated header is not a header` — and is corrected. That text is +a header with no body, and its value parser refuses it outright, so inspection +claiming an executable element inside a document nothing will run was the worse +of the two answers. A new case checks offset *and* suffix against `matter()` +across every shape. + +**R3 — published observations were mutable.** One phase object reaches every +subscriber and is retained as the latest, so a reader could rewrite a terminal +phase to `active` and a late reader would be told that. Phases are frozen +before publication, and an `AggregateError`'s `errors` array is frozen as well +as the error around it — freezing the error alone leaves the explanation every +other reader holds editable. + +K11, K12 and K13 join the controls, one per finding. + +## A handback claim the review corrected + +The review is right and I was wrong: `renderer.measure` already copies each +bound into a new map and freezes it, so `ReplMeasured.boundsOf` does **not** +close over live engine state. My note claiming otherwise is withdrawn, and the +geometry snapshot it justified is removed — the journeys pass without it, which +is the test that says it was never the fix for the drawer defect I attributed +to it. That defect's real cause was the reading's controls not being reserved +in the pass that measures the window, which the same commit fixed separately. + +## Two defects this slice found in itself + +**The engine's geometry dies at the next render.** `ReplMeasured.boundsOf` +closes over engine state, not over a copy. Preparing the reading between the +third measurement pass and `admissionFor` meant every window's capacity came +from the probe tree: the question drawer was admitted shorter than the one on +screen, a form field's row fell outside its window and lost its Tab stop, and +the agent journey typed two answers into one field. Every bound the pass gives +is now copied into a map before anything else is measured. This is the rule +`planning-measurement.md` states; the existing passes satisfied it only by +accident of ordering. + +**A self-closing element lost the badge it settled with**, because the reading +it had was attached to a closing delimiter it does not have. Also: badges align +at the right inner edge rather than at a shared start column — `▶ ENTER` and +`✓ SETTLED` are different widths — and the reading's two controls must be +reserved in the pass that measures the window, or the one it grows is drawn over +the reading's last row. + +## Replaced presentation premises, itemized + +The transcript's per-record rows are gone, so fourteen assertions across five +suites were re-anchored. Every behavioural claim is preserved; none was deleted +and none was weakened without saying so. + +| Suite | Assertion | Old anchor | New anchor, and why | +| --- | --- | --- | --- | +| `repl-presentation-style` | a settled document's result is output, not an outcome | `line::0` | `reading:output:0`, plus the caption saying it is the retained result and not live | +| | a root with no result shows its outcome and its reason | `line::0/1` | `reading:output:outcome:0` and `reading:output:reason:0`; the caption now says the absence of rendered text is what is being reported | +| | live text reads as output | `line:live:0` | `reading:output:live:0`, plus the caption saying it is still arriving | +| | the ink of each of those | row's first cell | the text's own span — every reading row opens with its rail, which says where the row is, not what it is | +| | output, metadata and two outcomes are four readings | a transcript `binding` record beside the output row | a subordinate row that still carries that reading; the Bindings column's row is a *value*, not a fact about an event | +| | a long row stays inside its pane | the transcript's `entry`/`scope`/`agent` records, bounded by shortening | the reading's rows, fitted by measuring; the exercise is a line that needed more than one row | +| | an empty screen's pane surfaces | the pane's bottom-right cell | the bottom-right of its viewport — the reading's `[↓ later]` is now the pane's last row, and a control carries the draft's surface wherever it is (this terminal's existing rule) | +| `repl-entries` | each entry shows its own transcript | with nothing selected, every entry's records concatenated | with nothing selected, the last entry admitted; the claim this case exists for — no reading shows another entry's — is unchanged and still asserted | +| | the live overlay belongs to the entry running it | `… ` prefixed rows | the Output half's rows plus its `Output · live` caption; the ellipsis per row is redundant once the caption says it once | +| | no prefix shows output it had not retained | the whole transcript | the Output half alone; the Source half correctly shows the source each prefix *did* admit | +| | a long recorded reason is on screen and bounded | one clipped row ending in `…` | the reason recovered from the rows it was wrapped into, and asserted to contain no `…` — the stronger claim | +| `repl-agent-interface` | a filtered or narrow frame mounts no transcript rows | `line:` | `reading:` | +| `repl-journey` | nothing is waiting | `Decide?` absent from the screen | no question is pending; the reading shows the `` the word is written in, and source on the screen never proved anything was waiting | +| | a drawer covers what it is in front of | two transcript record texts | two lines of the reading; `Source` and `Checklist` would have collided with `summarySource` and ` admitted` in the drawer's own list | +| | the generated fragment's source is on screen | its row above the effect row admitting it | recovered from the Transcript column's rows, because the reading wraps rather than clips; the admission row is no longer in this pane | +| | a cold process reconstructs the fragment | `generated admitted:` | the catalog row naming the reconstructed region | +| `repl-agent-journey` | both Plan reviews are retained where they were asked | counted anywhere on screen | counted after selecting the scope that holds them, which is where the product says they were asked | +| | the program's own two questions | same | same, under the generated fragment | +| | answering the form | clicked the first matching label | clicked inside the drawer that is asking — the reading shows the question's own schema, so its `title` is on the screen twice | + +## The seventeen controls + +Run alone against `acadbbdb`, one mutation at a time, each restored from the +source and byte-compared afterwards. Record: `pr2-evidence/.controls.json`; +runner: `pr2-evidence/.controls.py`. + +| Control | Mutation | First failure | Restored | +| --- | --- | --- | --- | +| K1 rails | the rail is removed from every reading row | S4 — a composed row no longer opens with its rail | bytes identical | +| K2 badges | `badgeRuns` returns nothing | S4 — no glyph and no word where a phase was observed | bytes identical | +| K3 appended | the enclosure's own content is emitted *as well as* the fragment | S1 — the producer is on the screen beside what replaced it | bytes identical | +| K4 clipped | a wrapped line stops after its first row | S2 — the line cannot be recovered from its rows | bytes identical | +| K5 rescued | a caught canonical failure is not recorded as raised | CX — a handler that catches it turns it into silence | bytes identical | +| K6 unheld | a pending permission counts no wait | L2 — the element the request was asked inside does not read as waiting | bytes identical | +| K7 collapsed | only the last call of a repeated element is read | S4 — the earlier call is not on the screen | bytes identical | +| K8 unindented | a continuation starts at the margin | S2 — the rows of one line no longer begin at one column | bytes identical | +| K9 early liveness | the entry says it is not live before releasing what it held | L3 — the installation is released into a session that already called itself finished | bytes identical | +| K10 narrow empty | a narrow frame routed to Entries shows no reading | UI13 — the 72×20 frame places no reading row | bytes identical | +| K11 foreign | a terminal carries a request its invocation did not issue | CX1 — another element's body runs on the invalid delegation | bytes identical | +| K12 mutable phase | a published phase is not frozen | CX3 — a reader rewrites the terminal observation | bytes identical | +| K13 envelope | the lexical envelope disagrees with the extractor | SI2 — the offsets differ and `parseSource` would refuse | bytes identical | +| K1b exit rail | an exiting element takes the unobserved rail | S4 — the rail is not the archive's `exit` literal | bytes identical | +| K14 preview clipped | a question preview takes one row per logical line | F3 — `drawer:message:4` is wider than the drawer it was measured for | bytes identical | +| K15 badge adrift | the badge pad is three columns short | P1-T3 — the badge's last cell is at 121, not the interior's 124 | bytes identical | +| K16 twice badged | every row of a delimiter carries its badge | P1-T3 — two rows say `● ACTIVE` where one element is expanding | bytes identical | + +All seventeen break; none is vacuous — K1 and K14 did not, until the assertions +they needed were written. Both gaps were found by making the control honest +rather than by reading the code. + +**A self-audit from that pattern.** Twice a control was vacuous because the +assertion read the model where the claim was about the screen. Badge alignment +had the same shape: "aligned at the measured source pane's right inner edge" is +frozen, and everything checking it read the composed run strings — this +terminal's own answer about itself. P1-T3 now commits a frame with one observed +element, finds the row that says `● ACTIVE`, and asserts its last cell is the +transcript interior's last cell, in the archive's literal, with the source +beside it keeping its own colours. It also asserts that every reading row +opens with its rail in cells, and that exactly one row says the badge. +**K15** and **K16** are their controls. + +K16 came back **UNBROKEN** first: putting the badge on every row of a +delimiter broke nothing, because the fixture's tag fitted on one row — a rule +about continuation rows cannot be tested by an element that has none. That is +the third vacuous control this slice produced, all the same shape: an +assertion that cannot reach the thing it claims. Each was found by making the +control honest, never by reading the code. The one-bit palette control is PR 1's own +record and returns in the assembled PR 3 evidence. + +## The gallery + +`pr2-evidence/` — **44 pairs**: the fourteen frozen states at 160×36, 120×30 and +72×20, plus `question-resize-refused-60x15` and +`question-resize-recovered-160x36`. Captured from this unchanged head in one +continuous journey against the real Deno entrypoint, terminal adapter, input +decoder, mounted tree and TTY renderer, in a private tmux PTY. Every state is +reached by normalized input and real operations; nothing is injected. Each +window is moved with that window's own control, in the pane that owns it. + + - `captures/` — the raw ANSI and plain text of each screen + - `pairs/` — each production screen beneath the archive study it is compared + against, per `final-gallery-matrix.md`'s mapping + - `sheets/` — 16 contact sheets, one state across its three profiles + - `comparison.html` — the whole gallery + - `gallery-manifest.json`, `actions.jsonl`, `provider.jsonl`, `run.log` + - `cold-before.json` / `cold-after.json` / `cold-command.txt` + - `sha256sums.txt` — 317 files + +**Cold counters.** Reopening the settled head at +`xmd://repl/07d87025c2ca24f68cc33ff746060551/entries` left the Journal at 49 022 +bytes and the provider log at 8 014 bytes, both with the same SHA-256 before and +after: the cold read appended nothing and called nobody. + +## C2, C3 and C4, row by row + +The first handback said these were partly covered and the second said C3 and C4 +were complete while quietly dropping C2. Both statements were wrong about +something. Here is each frozen clause and the case that decides it, in +`component-expansion.test.ts` unless named otherwise. + +| C2 clause | Case | +| --- | --- | +| Import returns with body held | an import that returned is not an element that finished — entered, active, nothing terminal, while the body is held | +| Body returns with cleanup held | a body that has returned stays in EXIT while its cleanup runs | +| Early resolution / props refusal | an element that resolves to nothing is never active, and still completes | +| Return validation fails | a return the schema refuses is reported as content and completes `Ok` | +| Printed failure | a body whose component prints its own errors does the same | +| Recovered child | recovering a child's failure does not fail the parent, with the unrecovered case beside it | +| Full dispatch middleware cleanup held | COMPLETE follows the whole dispatch: a subscription on the handler's own frame never sees it, one on an outliving owner does | + +| C3 clause | Case | +| --- | --- | +| Body and teardown failures | a body that throws exits failed with a detached report; cleanup that fails completes the element with a failure | +| Clean wait cancellation | clean cancellation publishes CANCELLED after unwind | +| Cancelled cleanup failure | an actual cleanup failure publishes a failed COMPLETE instead | +| Fatal/cause precedence, reporting detachment | catching a canonical failure does not rescue it (control **K5**); the report is a frozen detached `Error` with no identity reachable through it | +| Compare observed/unobserved output, bindings, failure, Journal bytes | an observed run and an unobserved one serialize identically — same elements, identities, positions and rendered result | + +| C4 clause | Case | +| --- | --- | +| Two readers | two readers of one element each get the whole sequence | +| Slow reader | a reader that takes one phase and stops delays nothing | +| Absent reader | a reader that never reads delays nothing | +| Cancelled reader | a reader whose scope is cancelled mid-expansion cancels nothing | +| Late terminal reader | a late subscriber is told where it is, without earlier replay | +| Ordered latest registration, one terminal then void | each reader registers with the latest phase and is then told each change in order | +| Execution never awaits a frame | every case above renders and completes with no frame in the run | + +Two of these were first written as guesses and were backwards — the product +completes a *printed* failure `Ok`, and the drain order of an asynchronous +consumer cannot witness a publication order. A probe against the real engine +replaced both. + +**L1–L3** are decided in `repl-lifecycle.test.ts` and +`repl-agent-execution.test.ts`. L3's ordering clause — held installation and +outer release precede `live = false` and the ready wake, with no input — is +observed by an installation that reads what the session was still saying about +itself at the moment it was released (control **K9**), not read off the comment +that states it. + +## A claim this handback withdraws + +The last version reported that a *fence*-admitted generated fragment's source +is not substituted. **There is no such fragment.** +`packages/core/src/components/Evaluate.ts` is the only caller of the +generated-XMD admission, so `` is the only element that makes one and +the frozen rule covers every admission that exists. The earlier reasoning +confused a fence that *computed* a fragment's text with one that admitted it — +in the reference entry the fence computes `summarySource` and +`` admits it, which is the paired case S1 +already covers. Withdrawn, not explained. + +## The narrow outlet, which was the last open claim + +The previous handback left 72×20 showing only the catalog and called it the +frozen rule. It was not. The matrix routes every PR 2 scene to `entries` at +narrow and requires the scene to be captured there, so a narrow capture holding +nothing of the scene is the claim unmet, not the claim satisfied. + +The Entries surface is the catalog **and** the reading of the entry it has +selected — the same two things the sidebar and the transcript are at a wider +size. A narrow frame has one column for both, so both are in it: the catalog +takes its own height while it fits and its share when it does not, which is the +rule the sidebar already uses, and the reading takes what is left. + +Nothing about routing moved. Which surface a narrow frame shows is still the +route's and the footer still keeps its seven rows; what changed is that the +outlet shows what the surface *is*. The narrow captures now carry Output, +Source, the rails and the badges — `nested-running-72x20` has `● ACTIVE` +against the pane's right inner edge at 72 columns, and `failed-72x20` has +`No rendered output.`, the outcome and the recorded reason. + +Two assertions moved with it, both named in the commit: `UI13`'s narrow leg +asserted that no reading row is placed at this size, which is the premise this +replaces — it now asserts placement at all three profiles, in whichever region +the profile has for it. And `TL6` skips a covered line that is only a window +control's label, because the outlet and the drawer spell `[↑ earlier]` the same +way: finding one inside the drawer's rectangle says the drawer has its own, not +that something behind it showed through. Control **K10** keeps the first +honest. + +## The accepted eight-step journey, and where each step is answered + +The journey in `pr2-product-verification.md` is the **Planner's** to walk, and +walking it is how this slice gets a verdict — that has not happened and is not +claimed. What is here is the evidence it can be walked against: the gallery +journey drives the same Plan-to-README story through the real command, so every +accepted step is either captured at all three profiles or asserted by the run. +The mapping, so the Planner reads rather than re-runs: + +| Step | Captures | What they show of it | +| --- | --- | --- | +| 1. Submit; Evaluate containing Plan; rails; full-word statuses right-aligned; an import alone is not SETTLED | `nested-running-{160x36,120x30,72x20}` | both elements reading `● ACTIVE` against the right inner edge, rails running opening to closing, nothing settled | +| 2. Open the Plan review; reach its preview and decisions with the arrow controls; close and reopen, still WAITING | `plan-review-*`, `plan-review-controls-*` | the drawer, and its decisions reached with `[↓ later]`. The close-and-reopen half is now **asserted by the journey** rather than captured: it reads the source with the drawer shut, dismisses the drawer, checks the question is still being offered, and fails if the source moved. No scene is added for it — the list is frozen at 44 | +| 3. Approve; the generated heading and first Elicit replace Evaluate's inner producer; its tags remain | `generated-inline-*` | the admitted program inside the author's own `` enclosure, the producer gone | +| 4. Empty values, then Northstar; at 72×20 reach the schema's closing delimiters and every decision control; wrapping keeps text and colours; continuations add no badge | `invalid-details-*`, `completed-details-*` | the validation, the populated form. The 72×20 reach is in `readme-preview-tail-72x20` | +| 5. Read the whole preview, approve; settled entry from its first window — Output before Source, beginning with the rendered document; reach `README.md was created.`; the write happens once | `readme-preview-tail-*`, `settled-output-first-*`, `settled-output-last-*`, `settled-source-*` | the four states in order, from the reading's own window | +| 6. Inspect a prefix from before admission — Plan again, no future text, no live badges; advance offscreen; return live | `historical-before-admission-*`, `returned-live-*` | the retained producer with unobserved rails, and the live head afterwards. The offscreen advance is now **asserted by the journey**: a second Plan entry is held at the provider's gate, an earlier prefix is inspected while it runs, the gate is opened with nothing typed and nothing activated, the prefix is checked not to have moved, and returning live is checked to show the advanced head | +| 7. Resize through the profiles while reading wrapped content; the status column stays inside the pane and its reservation is stable | every scene at three profiles, plus `question-resize-refused-60x15` and `question-resize-recovered-160x36` | the refusal below the minimum and the same question with its values after recovery | +| 8. Cold-open the settled entry **and the earlier retained prefix**; same retained source and output, no live badges, no provider activity, no Journal mutation | `cold-settled-*`, `cold-before.json`, `cold-after.json`, `cold-after-historical.json`, `cold-command.txt` | the reopened head; then the same cold process reading a position from before the generated admission, **asserted** to show the producer and neither generated text nor a live badge. The Journal and the provider log are identical SHA for SHA across *both* reads | + +All eight steps now have evidence. Three of them — step 2's close-and-reopen, +step 6's offscreen advance and step 8's cold open of the earlier prefix — are +**assertions the journey makes**, not scenes: the list is frozen at 44 and these +are things a journey does, not states a gallery holds. The run fails if any of +them is false. + +Getting them right took several corrections worth recording, because each was a +harness error that would have read as a product defect: + + - a pane sliced from the "Transcript" heading rightwards is the *drawer* while + one is open, not the reading behind it; + - the guidance row above the reading changes when focus does, and the status + column beside it changes while work moves — neither is the source, and both + had to leave the comparison; + - a retained position refuses a submission, so an offscreen advance has to be + work already in flight rather than something typed from the frozen view; + - a frozen position cannot report the head moving — that is what it is for — + so the advance is observed after returning live, not during; + - `exit_location` took the first location in the pane's scrollback, which + after several sessions is a stale one. + +One of those corrections produced a real finding and then retired it. With the +offscreen stage running *before* the cold read, the provider log grew by 450 +bytes across the cold reopen — which would have been a violation of step 8's +"no provider activity". The cause was my own harness: it left an entry +unfinished, and a cold process reopening one reconnects its provider. Moving +the stage after the cold evidence restores the true reading, and both counters +are now byte-identical across both cold reads. The frozen claim holds; the +earlier number was the harness measuring its own leftovers. + +## The architecture review + +`pr2-architecture-review.md`, against the seven frozen structural checks in +`pr2-planner-handoff.md`. All seven are met, each naming the test or control +that would fail if it were not. + +It is written by the Implementor, because the handoff asks the Implementor for +it — "return ... all review/control/cold evidence", and "the architecture +review uses the seven frozen checks in pr2-planner-handoff.md; it adds no +speculative permutation". It says so in its own opening rather than pretending +otherwise: authorship is mine, confirmation is not, and an author reviewing +himself finds what he was already looking for. Every "met" in it is a claim +with its evidence attached, for the Planner to confirm or reject. + +I withdrew this file for two turns, renamed to a "self-assessment", on the +reading that a review by the author is no review. That was an over-correction: +the complaint it answered was that the review had not been *confirmed* by the +Planner, which is a Planner action and not a reason the deliverable should not +exist. It is restored. + +Its renderer note was wrong and has been removed: see the correction above. + +## What is not done, and is not mine to do + +The handoff's next action for me is to implement the ordered layers and return +focused feedback. That is what this is. Two things remain, and both belong to the +Planner: + + - the **Planner's** walk of the accepted eight-step journey at all three + profiles — mapped above, with every step now answered by a capture or an + assertion, but a verdict on it is theirs and not in this packet; + - the **Planner's** acceptance or request for changes on this slice. + +Nothing in this handback is claimed as #881 parity, and neither of those two +has happened. + +Next action: the Planner re-reviews R4 at `acadbbdb`, and completes the live +journey steps its own run could not reach. diff --git a/.reviewer/issue-881/pr2-implementation-handoff.md b/.reviewer/issue-881/pr2-implementation-handoff.md new file mode 100644 index 000000000..401b62ad7 --- /dev/null +++ b/.reviewer/issue-881/pr2-implementation-handoff.md @@ -0,0 +1,348 @@ +# PR 2 implementation handoff: follow execution and read its result + +**Frozen; ready for implementation.** Show an entry's rendered Output before +its Source. Source carries nested rails and independently observed live phases +in a stable right-hand column. Admitted generated XMD occupies its Evaluate +enclosure. Wrapped content and its tail remain reachable at every supported +profile. This slice does not implement the new History rail. + +The Product Owner accepts the contracts consolidated in +[pr2-planner-handoff.md](pr2-planner-handoff.md). This implementation plan freezes +ordinary mechanics and evidence against those decisions. The +[stack and evidence rules](stack-and-evidence.md) and +[44-pair PR 2 gallery](final-gallery-matrix.md) are part of this handoff. +There is no production verdict or completed test claim here. + +## Base, scope and ownership + +Start PR 2 from accepted PR 1 +080b6ec80ca74e614789e8d2252857ac281df7e5 and integrate main +4c0414be1010f69f11bff0d1d634623a5b08f886 as specified in the shared stack record. +Record the resulting base SHA. Preserve PR 1's token runs, independent reference +fixture, focus cue, surfaces and drawer rule. Use the current `entries` route and +owner-level Interrupt behavior. Prepare a new worktree with deno task setup. + +Core owns execution, results, binding acceptance and failure precedence. Its +middleware supplies observations. The session owns the live view and its +consumers. The Journal supplies retained source/output/history only. The root +combines immutable readings for the selected route and passes them directly to +children. Typed actions return to the root; Freedom owns focus; one prepared +reading owns visible rows and their mounted targets. Renderer input stays ops. + +No Journal format, sidecar, timestamps, general tracing, dependency/vendor +change, extra terminal reader, provider during inspection, automatic drawer, +new schema/editor, fork or newer reference feature belongs here. PR 3 owns full +History navigation and rail geometry. Existing History actions are used for +PR 2's prefix checks. Do not publish PR 3 behavior in this slice's specifications. + +## 1. Surround the complete canonical invocation + +Add this exact member and types in packages/core/src/component-api.ts. Export +Component and consumer-facing request/phase/Expansion types from +packages/core/api.ts; preserve existing packages/core/mod.ts exports. +Operation, Stream and Result are Effection types. + +```ts +interface ComponentApi { + expand(request: ComponentExpansionRequest): Operation; +} +interface ComponentExpansionRequest { + readonly expansion: Expansion; + readonly phases: Stream; +} +type ComponentExpansionPhase = + | { readonly phase: "enter" } + | { readonly phase: "active" } + | { readonly phase: "exit"; readonly reason: "returned" | "failed" | "cancelled" } + | { readonly phase: "complete"; readonly result: Result } + | { readonly phase: "cancelled" }; +``` + +Expansion keeps its existing frozen id/name/optional SourcePosition meanings. +It describes a logical source element, not a unique process call or capability. +No process key, parent or rendered value is added to it. + +Implement occurrence-specific dispatch in component-api.ts and expand.ts using +the Execution.document/importThroughTerminal pattern. A private terminal closes +over the issued request, a once-only delegation guard and the canonical result. +Only exact next(request) delegates work. Copied, foreign, omitted and repeated +requests refuse; an outside Component.operations.expand call refuses unissued +work. Ignore middleware return values. Reconcile a handler refusal/failure with +the canonical outcome through the existing policy-failure pattern: it may refuse +work or fail success, but cannot rescue canonical failure or replace durability/ +Files fatal precedence. Do not trust a replaceable context for that authority. + +Place dispatch before expandComponent's cycle/depth, resolution and props +checks, rather than around importComponent alone. Use the equivalent element +dispatch for structural work in expandSegments, expandSwitch, selected Case, +selected Else, All/Spawn and executed declared structural regions. Preserve +their current source/structural path and scopes. Actually executed consumed +regions get one boundary; passive syntax, unselected branches and restored work +get none. Code blocks remain within their containing element. Do not wrap the +same work at both its structural caller and consumed-region implementation. + +Use invocation.ts's existing ordered content/body/eval teardown; do not replace +its owner or create resource scopes for structural syntax. In Markdown, +function and value/captured paths, publish ACTIVE where accepted work starts. +Publish EXIT when that work ends, before owned cleanup and return/binding +acceptance. An early preparation refusal has ENTER then EXIT, with no ACTIVE. +Body return alone never supplies SETTLED. A returned EXIT can complete with an +error after validation or cleanup. Recovery of a child failure does not itself +fail the parent. + +Publish COMPLETE only after the entire middleware dispatch has unwound and +canonical acceptance is reconciled. This includes middleware cleanup outside +the terminal. Keep the outgoing result/binding candidate private until that +reconciliation; middleware cannot publish or validate it on Core's behalf. +Preserve already-performed effects and existing canonical failure disposition; +this adds no rollback protocol. Success is Ok(undefined); failure is Err of a +detached reporting +Error preserving selected name/message and explanatory Error causes. Keep +canonical error identities and arbitrary resource objects private. Freeze all +published observations. Clean cancellation publishes CANCELLED after unwind; +an actual cleanup failure instead publishes failed COMPLETE. Exactly one +terminal phase is followed by stream closure with void. Preserve printed +semantic failure, body/teardown cause accounting, caller-retained resources and +existing failure/recovery behavior. No minimum phase animation delay exists. + +The stream registers each scope-owned subscriber atomically with its latest +phase, then queues ordered updates independently. A late terminal subscriber +gets that terminal observation and completion, without earlier replay. Reading +or cancelling a subscription neither invokes nor cancels work. Absence or +slowness of readers never blocks execution or waits for a frame. + +Verification: C1–C4 below discriminate dispatch, phase timing, authority and +subscription behavior with real invocation and cleanup gates. + +## 2. Expose static source boundaries without execution + +Add a pure packages/core/src/source-inspection.ts helper, exported from Core's +root mod.ts with these exact shapes. Reuse/export existing SourceRange; do not +change document-target coordinates. + +```ts +function inspectSource(text: string, kind: "document" | "fragment"): + Result; +interface SourceElement { + readonly name: string; + readonly opening: SourceRange; + readonly closing?: SourceRange; +} +interface SourceRange { readonly start: number; readonly end: number; } +``` + +Extend scanner.ts's successful parseComponentTag/parseChildren result collection +where opening and matching closing delimiters are recognized. Commit a nested +collector only if its enclosing parse succeeds, so an incomplete passive tag +cannot leave guessed children. Keep scanComponentSpans's top-level heading +masking behavior equivalent. Preserve scanner handling of quotes, expressions, +fences and inline code; there is no CLI parser or delimiter search after parsing. +Return every recognized nested element in opening order, recursively frozen. +Paired empty content still has closing; exactly self-closing syntax lacks it. +Ranges are half-open UTF-16 slices into the exact input, including a document +header prefix. Name preserves authored dotted spelling and says nothing about +resolution or permission. Passive/incomplete text and empty lists are success; +scanner refusals become Error Results. + +Document inspection needs a private lexical envelope boundary beside +definition.ts's parseSource. Match the installed gray-matter envelope extraction +without calling its value parser: account for BOM, leading `---` except `----`, +its first newline closing delimiter, absent closing delimiter, optional header +language and the following CR/LF removal. Preserve the verbatim body suffix and +its original offset. Fragment scanning uses the entire input. Share this body +boundary with definition parsing and assert equivalence to its existing suffix; +execution continues to interpret declarations exactly as before. Do not call +parseMarkdownDefinition, compile schemas, evaluate props or a frontmatter engine +from inspection. C5 covers safe envelope equivalence and an executable-header +sentinel proving no evaluator ran. + +## 3. Feed a session-owned live reading + +Add a private lifecycle module under packages/cli/src/repl/ and install its +Component middleware in session.ts before the entry can start. Each actual call +gets an entry-owned private occurrence key. Bind the enclosing presentation key +around next(request), following expansion.ts's CurrentWalk composition. Generated +descendants inherit this presentation lineage while their capability environment +remains narrowed. Repeated logical ids never overwrite an occurrence. Context +supplies presentation only, never authorization or durable identity. + +Subscribe before starting its consumer. Run consumers under the captured entry +owner as siblings of dispatch, not children whose join blocks handler return. +Core publishes terminal phases after handlers unwind, so waiting for that phase +inside the handler's own destructor would deadlock. Keep consumers until their +terminal observation or entry shutdown. Failure follows their actual Effection +owner. Cancellation joins owned execution/consumers and clears waits; a closed +entry generation rejects late updates rather than reviving removed live data. + +WAITING overlays counted reasons: actual Elicitation requests, permissions +attributed through the bridge's actual turn owner, and expansion controller +holds. Each resolves/removes itself. Close/reopen of a drawer changes no wait. +Ordinary suspension, resolution and Prompt activity alone are not waits. +A cleanup wait retains EXIT and WAITING together. Snapshots are detached, +immutable and outside ReplModel. Completed process observations may remain in +the live snapshot until entry removal; cold reads reconstruct none. + +In expansion.ts classify Component.expand as a **gate**, not a new walk. Gate +before delegation using the inherited CurrentWalk; retain existing document, +content, tryContent and declared structural walk owners. Update the complete +COMPONENT_BOUNDARIES inventory and its test. Structural work now crosses the +new seam without duplicating invocation observations or releasing holds twice. + +Move session.live's final false transition from runEntry's return/catch to the +entry's first-registered, last-running release finalizer in begin(). All work, +output consumers and the Agent attachment release before that transition. +Preserve the settled-only rule for freeing the submission slot: cancelled or +refused work does not become submittable merely because its active task ended. +Publish the completion wake on the existing session changes path even when no +Journal append or input occurs. This existing private liveness fact also supplies +PR 3's head reading. Do not conflate it with a retained root Close or merely the +execution Future returning. Verify attachment/consumer release order in addition +to the held execution-installation cleanup. + +In program.ts and application.ts pass the live reading down the existing view +path, and suppress lifecycle, question, permission, Agent and emitted-output +overlays whenever route.at is historical. Observe offscreen work continuously; +return live takes the latest session snapshot. L1–L3 verify ownership and waits. + +## 4. Prepare Source and Output as one measured reading + +Use a private source-reading helper beside presentation-text.ts. Start from the +selected retained source owner/kind and inspectSource ranges. For a successful +generated admission, match exactly one Evaluate opening at its canonical +recorded position in that known owner. Paired replacement substitutes only +opening.end..closing.start, keeping exact enclosure bytes. A self-closing +Evaluate keeps its row and receives a connected child region underneath. Before +admission the producer remains; refused, missing or ambiguous ownership follows +existing projection refusal, never a name/sibling guess. Keep each generated +region's original identity and offsets. Replacing display text never rewrites +submitted source or Journal records. + +Derive nesting from canonical interval containment. Rails continue from opening +through closing, including wrapped rows and generated children. Attach actual +occurrences by entry, lineage and source position. Static elements have rails +without invented phases. Repeated calls receive separate readings in their +owned source group. All lifecycle glyphs/words align at the measured source +pane's right inner edge; only the first visual row carries each badge. +Observed closing EXIT/terminal markers use that same column. Historical rails +remain without live badges. + +Start a prepared source segment at each canonical opening/closing tag boundary +as well as each explicit newline. This makes inline nested tags separately +readable in the status column. These display breaks alter no logical source +byte or offset; concatenate segments within each source occurrence to recover +its exact text. A multiline tag's continuation rows still have no second badge. + +Use independent original L literals: ▶ ENTER #5aa87c, ● ACTIVE #7fd3e8, +● WAITING #c99a3f, ◀ EXIT #c2766e, ✓ SETTLED #4f8468, × FAILED #d24b3f. +Cancellation keeps existing cancelled wording. Focus adds weight and its cyan +cue without recolouring tokens or these statuses. + +For rails, use the original timetravel RAIL literals with the occurrence's actual +reading: active #2f6272, waiting #4a3a1c, exit #5d3c39 and settled #2e3c35. +Static/unobserved source uses pend #252b30; it acquires no phase from retained +syntax. Preserve EXIT's rail during a cleanup wait. Copy these source literals +alongside L in the independent reference fixture and sample them in S1/S2. + +An entry reading contains Output then Source within the existing transcript +pane, sharing one vertical window. Running emitted text is `Output · live`. +Retained final root text replaces it once and the label becomes `Output`. +Empty final text reads `No rendered output.` with the actual outcome. A selected +prefix with no entry output reads `No entry output recorded at this checkpoint.` +No later/live text is borrowed. Keep diagnostics/outcomes truthful independently +of words in rendered prose. The first reading position begins with actual +rendered content; newly arriving output does not auto-scroll an existing window. + +Nested source may show `Recorded block output` only at its established retained +owner. Entry output is never attributed to an Elicit/File or reconstructed by +concatenating block results. Bound values emitting nothing supply no output; +Agent text remains in its Agent reading. There is no synthesized write receipt +or component rendered value in lifecycle Result. + +Apply [the private engine-fit preparation method](planning-measurement.md) in +program.ts's prepareFrame after pane widths are known. Share prepared rows +between application descriptions, layout boxes, row count and admission. +Measure stable rails/status reservations and actual token ops, then wrap all +source, source previews and rendered text at preferred fitting word boundaries, +breaking long tokens at fitting grapheme boundaries. Preserve whitespace, +newlines, blank lines and every character/role. UTF-16 indexes are slice offsets, +not terminal widths. The engine probe already distinguishes wide/combining text. +Do not use PR 1's clipping guard as the new reading's wrapping policy. + +Add the main reading to existing process-local windows, keyed by execution, +selected prefix and source/entry reading. Earlier/later controls stay outside +moving content and consume capacity before rows. Clamp after remeasurement on +resize. Windowed-out rows have no node, target or Tab stop. Metadata fitting, +editable fields and the single-row draft retain their existing policy. Change +all Sessions, Entries, drawer and reading control labels to `[↑ earlier]` and +`[↓ later]`, keeping semantic actions and normal activation. No arrow shortcut +or horizontal scroll is introduced. Keep seven footer rows and narrow routing. + +S1–S4 and the gallery verify these relationships through committed cells, +normalized actions, source tails and mounted targets. + +## Frozen focused evidence + +Add component-expansion.test.ts and source-inspection.test.ts in Core tests; +add repl-source-reading.test.ts in CLI tests. Extend named existing regressions +instead of building a second execution/renderer harness. + +| ID | Concrete cases and required result | Defect discriminated | +| --- | --- | --- | +| C1 | Markdown, function, value/capture; Switch selected Case, If selected Else, All/Spawn and executed declared region; unselected/restored work absent. Exact request delegates once; counterfeit/copy/repeat/missing/outside refuse. | Incomplete observation, duplicate work or forged execution. | +| C2 | Import returns with body held; body returns with cleanup held; early resolution/props refusal; return validation fails; printed failure; recovered child. Full dispatch middleware cleanup is also held. | Import/body/terminal alone supplies success; parent inherits recovered failure. | +| C3 | Body and teardown failures, clean wait cancellation, cancelled cleanup failure; preserve fatal/cause precedence and reporting detachment. Compare observed/unobserved output, bindings, failure and serialized Journal bytes. | Observation changes execution or exposes canonical mutable errors. | +| C4 | Two readers, slow reader, absent reader, cancelled reader and late terminal reader. Ordered latest registration has no gap, exactly one terminal then void; execution never awaits a frame. | Shared reader, deadlock or lost registration update. | +| C5 | Nested same-name/dotted/empty/self-close tags; quoted `>` and tag-like expressions, fence/inline inert text, CRLF/BOM/non-ASCII/header offsets, passive incomplete tags and canonical refusal. Document versus fragment envelope; executable-header sentinel unchanged. Heading target/execution equivalence. | Second parser, offset drift or inspection execution. | +| L1 | Repeated logical ids and real concurrent siblings; generated descendants keep parent lineage and narrowed capabilities. | Id conflated with process occurrence or generated authority widened. | +| L2 | Concurrent question/permission/hold reasons; resolve one, close/reopen drawer, ordinary Prompt/suspension, EXIT with a cleanup wait. | Session-wide waiting boolean or false waiting. | +| L3 | Entry shutdown/cancellation joins consumers and clears waits; late producer update cannot revive them. Held installation and outer attachment/consumer release precede live=false and ready wake, with no input. | Early readiness, leaked subscriber or dispatch-consumer join deadlock. | +| S1 | Original paired admission, earlier prefix and return live; self-closing Evaluate of a File read; missing/ambiguous admission refuses. | Appended generated text, fabricated pair or wrong owner. | +| S2 | All three profiles: long schema and preview tail, unbroken `x`×160, `界é🙂` and combining accent, explicit blank lines. Concatenated fragments recover logical text and roles; continuations have one owner and no duplicate badge. | Clipping, character-width estimate or colour fallback. | +| S3 | Live/final replacement, empty output, successful prose containing `failed`, bound value emitting nothing and narrower block output. Output first; no auto-window jump. | Fabricated output/outcome or duplicated final result. | +| S4 | Phase-only updates keep source cuts/status width; supported resize and undersized recovery; controls/rows/targets agree; selected-prefix windows and cold start offsets. Journal/provider/source-load counters unchanged in settled cold head and early-prefix opens. | Geometry drift, invisible targets or historical/live leakage. | + +Run these exact focused commands from the prepared implementation worktree: + +```bash +deno task test packages/core/tests/component-expansion.test.ts packages/core/tests/source-inspection.test.ts packages/core/tests/component-api.test.ts packages/core/tests/invocation-scope.test.ts packages/core/tests/invocation-failures.test.ts packages/core/tests/invocation-identity.test.ts packages/core/tests/expansion-metadata.test.ts packages/core/tests/scanner.test.ts packages/core/tests/document-targets.test.ts packages/core/tests/document-target-execution.test.ts packages/core/tests/evaluate-component.test.ts +deno task test packages/cli/tests/repl-source-reading.test.ts packages/cli/tests/repl-execution.test.ts packages/cli/tests/repl-entries.test.ts packages/cli/tests/repl-layout-admission.test.ts packages/cli/tests/repl-presentation-style.test.ts packages/cli/tests/repl-forms.test.ts packages/cli/tests/repl-journey.test.ts packages/cli/tests/repl-agent-journey.test.ts +git diff --check +``` + +These explicit files cover scanner/generated and owned host boundaries that +import selection alone can miss. Test step counts are reported actual results, +not a guessed acceptance number. Existing assertions stay unless their exact +presentation premise changed; itemize replacements and preserve behavioral +assertions. No full runtime corpus, lint or CI wait precedes the feedback commit. + +After the positive feedback revision, run five controls alone: remove rails +(S1/frame geometry fails); remove lifecycle glyph/words (C2/S2 committed reading +fails); append generated source instead of replacing (S1 fails); clip the last +wrapped row (S2 tail fails); rescue a caught canonical failure (C1/C3 fails). +Save each first failure and verify byte restoration. The independent one-bit +palette control returns in the assembled PR 3 evidence, preserving PR 1's own +control record. + +## Documentation and handback + +Update architecture.md's Component/middleware and private REPL sections, +specs/executable-mdx-spec.md's expansion/invocation contract and specs/repl-spec.md +for implemented observation, output/source, canonical inspection, wrapping and +arrow labels. Use present tense. Preserve recovery, resource ownership and +prefix isolation. State explicitly that observations are ephemeral and static +syntax/retained admission does not prove active execution. Core root versus +/api exports remain distinct. The architecture review uses the seven frozen +checks in pr2-planner-handoff.md; it adds no speculative permutation. + +Return the focused commands and their outputs, exact SHA/parent/integrated base, +44 gallery pairs and all review/control/cold evidence under +pr2-evidence/ and pr2-implementation-handback.md. Capture from the unchanged +feedback SHA. Explain any unmet frozen claim instead of declaring complete +#881 parity. Do not push or open a PR without separate authorization. + +Continuity: accepted predecessor 080b6ec80ca74e614789e8d2252857ac281df7e5; +main integration input 4c0414be1010f69f11bff0d1d634623a5b08f886. Artifacts: +this handoff, stack-and-evidence.md, planning-measurement.md and the PR 2 portion +of final-gallery-matrix.md. All architecture/product decisions are settled. +**Planning blockers: none.** Next action: prepare and integrate the PR 2 worktree, +then implement the ordered layers above and return focused feedback. diff --git a/.reviewer/issue-881/pr2-independent-architecture-review.md b/.reviewer/issue-881/pr2-independent-architecture-review.md new file mode 100644 index 000000000..bd2535af1 --- /dev/null +++ b/.reviewer/issue-881/pr2-independent-architecture-review.md @@ -0,0 +1,122 @@ +# PR 2 independent structural review + +Reviewed commit: `9d8bc463297c39edd8893c8404c1dd674700cb23`, on +`agent/issue-881-pr2`, against integrated base `c7d54769`. + +**REQUEST CHANGES.** The invocation terminal accepts an authentic request from +another invocation, and source inspection changes which documents execution +accepts. Published observations are also mutable. These violate the accepted +contract; no architecture amendment or persistence change is needed. + +This is an independent code review by the Planner, who did not implement this +slice. It checks the seven settled structural requirements in +`pr2-planner-handoff.md`; it does not adopt the Implementor's self-assessment as +a verdict or introduce a new architecture decision. + +## Required corrections + +### R1: reject a foreign request before executing any body + +`packages/core/src/component-expansion.ts:132` checks the private brand and +whether a request was consumed. It does not establish that the request belongs +to the terminal receiving it. `expandThroughTerminal` in +`packages/core/src/component-api.ts:466` passes the delegated request to the +current invocation's continuation without comparing it with that invocation's +issued request. + +The review probe starts two genuine canonical invocations, A and B. Middleware +holds B's request and delegates it through A's `next`. A's body executes, then A +fails with “returned without delegating the expansion.” Refusing after the body +has run is too late: an effect can already have happened, and B's private claim +has been consumed by the wrong invocation. + +Bind each terminal to its exact issued request. Reject a different request +before claiming it or entering work. Extend the existing C1 regression with an +authentic, unconsumed request from another invocation; a fabricated object or +copied request does not exercise this defect. The foreign body and current body +must both remain unexecuted by the invalid delegation, and the foreign request +must remain usable by its own terminal. + +This is frozen checklist item 1 and the accepted invocation contract's explicit +foreign-request rule. + +### R2: preserve the existing document envelope + +`packages/core/src/source-inspection.ts:83` computes a different body boundary +from the installed extractor. The new assertion in +`packages/core/src/definition.ts:50` turns this disagreement into an execution +failure. + +A normal BOM-prefixed document with no frontmatter, `\uFEFF\n`, has +existing body offset 1. The new lexical helper returns 0, and `parseSource` +throws “frontmatter boundary disagrees with the lexical envelope (0 vs 1).” +The probe also records disagreement for an unterminated header and a closing +delimiter followed by text, both accepted by the installed extractor. + +Make lexical extraction agree with the existing extractor while evaluating no +header values. Preserve execution's accepted inputs and exact body suffix. +Cover the BOM-without-header case in the existing C5 envelope-equivalence +regression and keep the executable-header sentinel inert. Removing the +assertion alone leaves the two readings inconsistent. + +This is frozen checklist item 4 and C5's explicit BOM/envelope/execution +equivalence requirement. + +### R3: freeze published observation data + +`packages/core/src/component-expansion.ts:57` puts the same mutable phase object +into every queue and retains it as `latest`. Freezing the request does not +freeze that object. A reader can change a terminal phase's `phase` to `active`; +a late reader then receives `active` from an already closed publication. + +The Effection Result is already frozen. The detached reporting Error is frozen +too, but an AggregateError's `errors` array remains mutable. Readers can change +the explanatory observation shared with other readers, even though Core's +canonical Error remains detached. + +Freeze each phase before publication and make the published explanatory cause +data immutable, including aggregate member arrays. Extend the existing C3/C4 +checks to attempt these mutations and confirm another reader still receives +the original terminal observation and explanation. Independent subscriptions +can share immutable values; no new persistence or public API is required. + +This is the accepted invocation contract's “Published phases and Result data +are immutable observations” requirement and C3/C4's reporting and independent +reader boundary. + +## Evidence + +The exact frozen Core and CLI commands and the supplemental lifecycle command +pass at the reviewed commit: Core 53 tests / 411 steps; CLI 94 / 313; +supplemental 14 / 52. Logs are in `pr2-planner-evidence/core.log`, `cli.log` and +`lifecycle.log`. No full runtime corpus or CI was used for this feedback review. + +`pr2-planner-evidence/contract-probe.ts` reproduces R1–R3 without editing +production code. Its decisive output is `contract-probe-final.log`. The two +earlier probe logs preserve corrections to the review harness: the first used +the wrong WithResolvers member; the second incorrectly treated WithResolvers +as an operation. Neither is a product failure or an intermittent test result. + +Run the final probe from the repository root: + +```sh +deno run --allow-all --config .claude/worktrees/issue-881-pr2/deno.json --node-modules-dir=manual --cached-only --frozen .reviewer/issue-881/pr2-planner-evidence/contract-probe.ts +``` + +The remaining checklist items are recorded with the Planner journey findings +in `pr2-planner-review.md`. They cannot override the failed canonical and +immutable-observation requirements above. + +## Handback correction + +The self-assessment's renderer note is inaccurate at this commit. +`packages/cli/src/repl/renderer.ts:217` already copies measured bounds into a +new Map and freezes each bounds object before returning `ReplMeasured`. +Correct the handback rather than opening a renderer architecture decision. + +## Next action + +Implement R1–R3 under the existing contracts, add the discriminating assertions +to their existing focused suites, run the frozen commands and supplemental +lifecycle command, then promptly return an exact feedback SHA and refreshed +evidence. Keep PR 1's accepted record and PR 3's scope unchanged. diff --git a/.reviewer/issue-881/pr2-invocation-contract.md b/.reviewer/issue-881/pr2-invocation-contract.md new file mode 100644 index 000000000..292634f7a --- /dev/null +++ b/.reviewer/issue-881/pr2-invocation-contract.md @@ -0,0 +1,188 @@ +# PR 2: accepted invocation observation contract + +All five middleware interview items are accepted by the Product Owner. +This contract settles the Core-to-REPL observation boundary. Presentation choices +are accepted in [pr2-source-presentation.md](pr2-source-presentation.md). +The main product verification journey is accepted in pr2-product-verification.md. +The static source-range boundary is accepted in pr2-source-inspection.md. +All contracts are consolidated in the ready pr2-planner-handoff.md. +PR 1 feedback is complete at +`080b6ec80ca74e614789e8d2252857ac281df7e5`. + +The REPL observes one executable element from preparation through cleanup and +final acceptance. For example, an Elicit remains WAITING until its question is +answered; a returning component remains EXIT while its destructor runs. +Core owns execution and outcomes. The session owns the live reading. + +## Accepted interface + +Add `expand` to the existing `Component` contextual Api. Export `Component` +and its consumer-facing types from `@executablemd/core/api`, including the +existing `Expansion` type needed by this request. Preserve existing root exports. +`Operation`, `Stream` and `Result` come from Effection. + +```ts +interface ComponentApi { + /** + * Surround one executable element's complete expansion. + * Core issues the request before resolution or validation. + * Delegate the exact request once; returned values carry no result authority. + * Completion includes owned teardown and final result acceptance. + */ + expand(request: ComponentExpansionRequest): Operation; +} + +interface ComponentExpansionRequest { + /** + * Core's detached description of the element this call surrounds. + * Presentation information only; it grants no execution capability. + */ + readonly expansion: Expansion; + + /** + * Observe the latest phase, then subsequent changes in order. + * Independent scope-owned subscriptions end after the terminal observation. + * Reading or cancelling a subscription does not start or cancel the body. + */ + readonly phases: Stream; +} + +// Existing Core type; its meaning is unchanged. +interface Expansion { + readonly id: string; + readonly name: string; + readonly position?: Readonly; +} + +type ComponentExpansionPhase = + | { readonly phase: "enter" } + | { readonly phase: "active" } + | { + readonly phase: "exit"; + readonly reason: "returned" | "failed" | "cancelled"; + } + | { readonly phase: "complete"; readonly result: Result } + | { readonly phase: "cancelled" }; +``` + +No separate completion alias, public callback/disposer, process key or parent +wrapper is required. Local helpers and publication mechanics remain delegated. + +## Canonical expansion and coverage + +Core dispatches through an occurrence-specific terminal following its existing +`Execution.document` request pattern. An observer delegates `next(request)` +with the exact issued request once. Copied, foreign, missing or repeated +delegation cannot fabricate success or execute a body twice. Outside canonical +Core dispatch, the operation refuses an unissued request. + +The terminal keeps execution results, bindings and failure decisions in private +state. Middleware return values are ignored. Catching a canonical failure +cannot rescue it. Middleware refusal or failure follows the existing policy +failure pattern: it may refuse work or fail success, while Core's canonical +failure and fatal precedence remain authoritative. + +Coverage starts before resolution and props validation, includes the accepted +Markdown or function body, owned child/content/generated work, ordered cleanup, +and final result acceptance and binding. Value/captured invocations receive the +same coverage. Structural engine paths such as Switch and actually executed +consumed regions use equivalent boundaries. Unselected branches and restored +work that does not execute receive no invented invocation phases. Code blocks +remain work within their containing element in this slice. + +Use existing invocation machinery and lifetimes. Structural syntax gains no +component resource scope. Caller-retained resources keep their existing owner. +Preserve printed semantic failure, recovery, body/teardown cause accounting and +durability/Files fatal precedence. + +## Phase and subscription behavior + +| Phase | Meaning | +| --- | --- | +| `enter` | Core begins preparation, before resolution and validation. | +| `active` | Core enters accepted body or structural work, including owned nested work. | +| `exit` | Work ends or preparation is refused; cleanup and final acceptance remain pending. The reason describes why exit began. | +| `complete` | Full middleware dispatch, cleanup and final acceptance finish; the effective outcome is selected. | +| `cancelled` | Cancellation finishes its unwind without an actual failure taking precedence. | + +An early refusal never reports `active`. An exit reason of `returned` does not +promise success: return validation or cleanup can still fail. Publish exactly +one terminal phase, then close the stream with `void`. Do not delay execution +to make ENTER or EXIT visible for a minimum animation time. + +Each subscriber gets the latest phase followed by ordered changes, without an +initial registration gap. Subscribers have independent queues. A late subscriber +after completion gets the terminal phase and then finishes. There is no replay +of earlier phases and no provider call or execution caused by observation. +An absent or slow UI consumer does not stall Core or wait for frame acknowledgment. + +The session owns consumers through entry teardown. Do not join a consumer from +inside a handler while it waits for a terminal phase that Core publishes only +after that handler unwinds. Consumer failures follow their Effection owner; +they do not supply a fabricated completion. Session shutdown joins its owned +execution and consumers, clears the live view, and prevents late publication +from reviving a removed entry. Subscription cleanup has its consumer's lifetime. + +## Completion reporting + +Successful completion reports `Ok(undefined)`. Failure reports +`Err(reportingError)`. The Result is reporting-only: it carries no component +rendered value, binding, provider, resource scope or authoritative result. + +The reporting Error is detached from Core's mutable canonical Error. Preserve +the selected diagnostic name/message and explanatory Error causes that Core +already supplies, without exposing arbitrary resource objects. Keep Core's +actual cause graph and identities private. Published phases and Result data are +immutable observations. No new structured stage or general tracing fields are +required; existing diagnostic stage information remains available. + +Clean cancellation reports `cancelled`, without inventing success or an Error. +When an actual cleanup failure takes precedence, report `complete` with failed +Result. A recovered child failure does not automatically fail its parent. + +## Session attribution and presentation + +Core creates the frozen `Expansion` description before dispatch, including on +resolution failure. Its deterministic id locates a logical source element; +it is not a unique key for a process execution. Position remains optional under +the existing source-position contract. + +The REPL allocates a private key for each actual middleware call and binds its +enclosing presentation key around delegation, following the existing private +CurrentWalk composition pattern. Entry identity and nesting remain session view +data. Generated expansion retains this execution lineage while receiving its +own narrowed capability environment. No new `ExecutionEnvironment` member is +required. Core never trusts presentation context for security, durable identity, +reconciliation or resource ownership. + +WAITING is a private overlay from actual unanswered Elicitation requests, +interactive permissions and owned pause holds. Count reasons independently and +remove each on its own resolution or cancellation. Closing a drawer does not +answer a question. Ordinary suspension, an import or an in-flight Prompt alone +does not imply WAITING. Permission attribution uses the Agent bridge's actual +owning turn. A wait during cleanup preserves the underlying EXIT phase. + +Completion Result maps to SETTLED or FAILED; cancellation uses existing cancelled +wording. Session snapshots may retain completed live badges. They stay outside +ReplModel and the Journal. Historical inspection suppresses all live overlays +while observation continues offscreen. Returning live uses the latest snapshot. +Cold inspection shows retained facts without reconstructing ephemeral phases. + +## Planner constraints and evidence + +Classify the new operation in the REPL expansion controller's boundary inventory +and update its discriminating tests in `repl-execution.test.ts`. Cover ordinary, +structural and consumed-region expansion without duplicate observations. +Verify subscriptions, late attachment, early refusal, printed failure, recovery, +held cleanup, cleanup failure and cancellation using real operation boundaries. + +Compare conforming observed and unobserved execution for identical output, +bindings, failure disposition and Journal bytes. Exercise repeated logical ids, +concurrent siblings, generated descendants and independent wait reasons. +History inspection must stay prefix-only while the live snapshot changes. + +These are boundary checks derived from the accepted API. The broader product +journey is accepted; the Planner freezes visual cases and exact focused commands +under pr2-planner-handoff.md. No production implementation, persistence change, +dependency change, GitHub mutation or reusable rule promotion is authorized +by this record. diff --git a/.reviewer/issue-881/pr2-planner-acceptance.md b/.reviewer/issue-881/pr2-planner-acceptance.md new file mode 100644 index 000000000..f55ff0ef3 --- /dev/null +++ b/.reviewer/issue-881/pr2-planner-acceptance.md @@ -0,0 +1,154 @@ +# PR 2 Planner acceptance and independent structural re-review + +**PASS — PR 2 feedback accepted at acadbbdb4fa7d8c8c86fa85f6657d29c5d95bc3e.** +R1–R4 and the previous housekeeping findings are closed. The seven frozen +structural checks, accepted eight-step live journey and 44-pair visual gallery +are satisfied. PR 3 may start from this exact revision under its frozen handoff. +This accepts the PR 2 slice; delivery verification and complete #881 acceptance +remain separate. + +Branch: `agent/issue-881-pr2`. Parent: +`9163a16b9f5b83e9c042f47e90ac307f4679d239`. Integrated base: +`c7d54769d56661bef38cee8549b148f3bf87a904`, combining accepted PR 1 +`080b6ec80ca74e614789e8d2252857ac281df7e5` and recorded main +`4c0414be1010f69f11bff0d1d634623a5b08f886`. +The implementation worktree is clean at the reviewed SHA. The Planner did not +implement this slice and issues this independent review without adopting the +Implementor's self-assessment as a verdict. No production changes, subagents, +commit, push, PR creation or CI verdict form part of this review. + +The [previous re-review](pr2-planner-rereview.md) remains the historical record +for 82a915ae. This acceptance supersedes its outstanding-finding list. +All evidence below is in [pr2-planner-acceptance-evidence/](pr2-planner-acceptance-evidence/). + +## Finding closure + +| Finding | Independent result at acadbbdb | +| --- | --- | +| R1: foreign request executes before refusal | **Closed.** The original read-only probe still reports `bodies: []` and ComponentExpansionProtocolError. CX1 passes, including continued use of each authentic request by its own terminal. Exact identity precedes claiming and work. | +| R2: lexical envelope changes accepted execution inputs | **Closed.** BOM/no-header, unterminated header, delimiter-with-suffix and ordinary header agree with the installed extractor and execute through parseSource. C5's envelope and inert-header regressions pass. | +| R3: mutable shared observation and aggregate explanation | **Closed.** The original probe confirms frozen published phase, Result, detached reporting Error and aggregate member array. A late reader receives the unchanged complete phase. C3/C4 pass. | +| R4: question preview loses long-line text | **Closed.** The real Plan preview recovers the complete first Elicit schema at all profiles. The real README preview recovers the full summary and closing quote, including `coordinating coding agents.` at 72×20. Existing decisions and submit remain reachable. | +| Earlier housekeeping | **Closed.** Scratch outputs stay outside the product diff; the base-to-head whitespace gate exits 0. The redundant bounds copy remains removed. K1 really removes rails, K1b separately changes EXIT colour, and K14–K16 discriminate preview clipping, misplaced badges and repeated badges. The packet remains stable across both integrity reads. The independent live walk completes without a shared-home storage collision. | + +R4 uses the existing private engine fitter at the measured drawer inset width. +`prepareFrame` prepares the preview before admission; the same fitted list feeds +message descriptions, total row count and scrolling. Measurement-only passes +retain their unmounted logical fallback. Fields, focus and answer semantics keep +their existing behavior. No public interface, Journal change, persistence or +additional reader is introduced. + +Decisive live evidence: + +- [Complete narrow Plan schema traversal](pr2-planner-acceptance-evidence/plan-preview-72x20.json), with [schema body](pr2-planner-acceptance-evidence/captures/plan-preview-72x20-20.png) and [final delimiters](pr2-planner-acceptance-evidence/captures/plan-preview-72x20-24.png). +- [Complete narrow README traversal](pr2-planner-acceptance-evidence/readme-preview-72x20.json), [summary and closing quote](pr2-planner-acceptance-evidence/captures/readme-preview-72x20-04.png), and [decisions plus submit](pr2-planner-acceptance-evidence/captures/readme-decisions-72x20.png). +- The 160×36 and 120×30 traversal JSON files establish the same recovery. These records gather actual terminal rows in order, normalizing display padding/continuation indentation whitespace. They do not claim byte-identical displayed whitespace. Exact grapheme and token retention remains covered by the focused fitter regressions. + +## Independent structural verdict + +These are the seven requirements frozen in pr2-planner-handoff.md; no new +architecture criterion is added. The R4 delta and its cell-evidence corrections +preserve the previously reviewed invocation and inspection contracts. + +| Frozen check | Verdict and evidence | +| --- | --- | +| 1. Canonical execution, exact delegation and outcome authority | **Pass.** C1–C4 and the independent R1/R3 probe preserve exact once-only dispatch, Core-owned binding/outcome acceptance and failure precedence. Observation cannot rescue canonical failure. | +| 2. Existing owners, ordered cleanup and consumer lifetime | **Pass.** C2–C4 and L3 hold body, invocation cleanup, whole middleware cleanup and installation teardown. Terminal observation follows unwind; entry readiness follows consumer/attachment release. Cancellation and cleanup failure retain their owners and precedence. | +| 3. Narrow generated capabilities; presentation grants no authority | **Pass.** L1 and generated-execution regressions preserve narrowed capabilities. Private occurrence/lineage context supplies presentation association, not authorization or durable identity. | +| 4. Pure canonical inspection and retained replacement ownership | **Pass.** C5, R2 probe and S1 use the canonical scanner/envelope and exact retained owner/range. Inspection evaluates, compiles and loads nothing; generated content replaces the producer inside its authored enclosure. | +| 5. No persistence extension; observed/unobserved equivalence | **Pass.** C3 compares canonical output, bindings, failure disposition and serialized Journal bytes. Live lifecycle data remains session-owned and ephemeral. | +| 6. Prefix isolation, cold reads and actual output owner | **Pass.** S1/S3/S4, frozen cold regressions and the live offscreen/cold walk preserve selected-prefix content, suppress live overlays and retain entry-owned output. Cold source-load/compile counters remain zero in the focused regressions. | +| 7. Immutable root view, measured admission and mounted targets | **Pass.** Published observations remain immutable. Main reading and question previews use engine-prepared rows before admission. S2/S4 and composed drawer regressions hold visible rows/actions/targets; P1-T3 now measures badge alignment, rail ink and single-badge wrapping in committed cells. | + +## Planner-owned live journey + +The Planner drove the ordinary CLI in its own PTY and working directory using +real fixture-provider gates and normalized input. No lifecycle/head state was +injected. Each recorded stage visited 160×36, 120×30 and 72×20. Full inputs, +actions, provider records and raw terminal captures are retained with +planner-journey.py and planner-journey.log; the driver exited 0. + +| Accepted step | Independent result | +| --- | --- | +| 1. Nested Plan and ACTIVE statuses | **Pass.** Actual held execution shows Evaluate containing Plan, source rails and full-word status at all profiles. | +| 2. Plan review, decisions, close/reopen | **Pass.** Complete original first Elicit schema recovered through 47/53/73 preview windows at wide/medium/narrow; decisions reached. Closing and reopening leaves the unanswered question available and the source unchanged. | +| 3. Generated source inside Evaluate | **Pass.** Generated source replaces the producer after approval while the authored enclosure remains. Narrow traversal reaches the schema tail and closing Evaluate. | +| 4. Validation and populated form | **Pass.** Empty submission reports validation; Northstar and the complete description are entered. Populated resize through supported profiles, 60×15 refusal and 160×36 recovery preserves both values in the Answer drawer. The established wide focus workaround is recorded. | +| 5. Whole README preview, approval and result | **Pass.** Full summary and closing quote recovered through 1/3/13 preview windows. Approval creates the actual README with both complete values. The settled first window shows Output and the document heading; the actual creation report and generated source end are reachable. Canonical once-only evidence comes from the focused suites; file existence is not a write-count measurement. | +| 6. Earlier prefix and offscreen advance | **Pass.** While the provider completes offscreen and supplies the Plan question, the selected early source remains unchanged at all profiles, with no future content or live badges. Returning live reveals the current question. | +| 7. Resize and reachable reading | **Pass.** Supported profiles, populated undersized refusal/recovery, narrow schema, preview, output report and source tail remain reachable. Focus/admission follows the existing rules. The frozen focused tests establish phase-stable reservation and mounted target agreement. | +| 8. Cold settled entry and earlier prefix | **Pass.** Fresh-process head begins at the initial Output window. Cold early-prefix reopen shows the original Plan, no future generated source/output and no live badges at all profiles. Journal/provider bytes are identical before, between and after both reads and final exit. | + +The additional `output-first-72x20` capture is excluded as initial-window proof: +the helper stopped early on identical blank windows. The correct +[settled initial window](pr2-planner-acceptance-evidence/captures/settled-output-first-72x20.png) +and [fresh cold initial window](pr2-planner-acceptance-evidence/captures/cold-head-72x20.png) +both show Output and the document heading. Raw evidence and the correction are +preserved in driver-notes.md. This is a harness limitation, not an intermittent +product failure. The driver's generic success text does not override this +explicit evidence boundary. + +Cold locations: + +```text +xmd://repl/297fa76751aed957aad572408663a2d1/entries/entry-1 +xmd://repl/297fa76751aed957aad572408663a2d1/entries/entry-1?at=yield:root:0&inspect +``` + +| Retained data | Unchanged reading across cold head/prefix and final exit | +| --- | --- | +| Journal | 47,323 bytes; 35 lines; SHA-256 `1538585a895c53dbdc10a8632ed0a394b298fc442634b8c4cd05b61d15bbcee3` | +| Provider log | 8,521 bytes; 11 lines; SHA-256 `32701c51800010656b33f712f51f813c886b0f6c0b742da8a6a346545f1b42ab` | + +These hashes prove byte stability. Source-load/compile absence is separately +established by the focused cold regressions, rather than inferred from hashes. + +## Focused and visual evidence + +The Planner reran the exact frozen Core and CLI commands plus the supplemental +lifecycle command from the prepared implementation worktree. All exit 0: +**Core 53 tests / 414 steps; CLI 94 / 316; supplemental 14 / 52.** +The exact commands, working directories and logs are recorded in +[focused-commands.json](pr2-planner-acceptance-evidence/focused-commands.json). +The independent contract probe exits 0, and +`git diff --check c7d54769..acadbbdb` exits 0. No full suite or CI is a feedback +prerequisite. + +All **17 supplied controls** have nonzero failures, substantive first-failure +records and matching before/after restoration hashes for current production +bytes. The Planner inspected these records and mutation recipes; the Planner +did not rerun the controls. Copies are supplied-controls.json/py, with independent +checks in control-review.json. K14 removes fitted preview rows and fails the +composed overflow assertion. K15 moves a badge three cells and fails its actual +right-edge assertion; K16 repeats it across a genuinely wrapped delimiter and +fails the one-badge assertion. Rail removal and EXIT colour remain distinct +controls. + +All **44 frozen comparison pairs** were opened through **16 supplied contact +sheets**. Their original archive provenance is +`86be64318121546f3208342edaf17f0a3aed35f3fde2766b523423e6c708c77b`. +The accepted terminal adaptations and scene mapping remain unchanged. +[image-review.md](pr2-planner-acceptance-evidence/image-review.md) lists every +sheet and additional live image opened. The frozen gallery's last cold scene +shows its separate failed entry; the independent walk above additionally proves +the successful README entry's cold head and early prefix directly. + +Both packet integrity reads match **322/322** supplied files, with an unchanged +checksum list and exact acadbbdb revision. The Planner evidence has its own +sha256sums.txt. Supplementary traversal captures do not enlarge the frozen +44-pair acceptance matrix. The two accepted, pre-existing PR 1 focus observations +remain unchanged; they are not new PR 2 findings. + +## Next action + +Implement PR 3 from **acadbbdb4fa7d8c8c86fa85f6657d29c5d95bc3e** using the +[updated frozen handoff](pr3-implementation-handoff.md) and +[stack record](stack-and-evidence.md). Their contracts, implementation layers, +focused tests and fresh 77-pair assembled gallery remain frozen; only the exact +accepted base and continuity status are updated. + +Continuity: no PR 2 feedback blocker remains. PR 1's accepted record is unchanged. +The next Implementor action is to branch from the accepted PR 2 SHA, prepare the +worktree and implement PR 3's snapshot, head and rail layers. Return focused +feedback and the assembled gallery; stop before push or PR creation. This review +issues neither PR 3 implementation acceptance nor complete #881/delivery acceptance. diff --git a/.reviewer/issue-881/pr2-planner-handoff.md b/.reviewer/issue-881/pr2-planner-handoff.md new file mode 100644 index 000000000..88ae3f479 --- /dev/null +++ b/.reviewer/issue-881/pr2-planner-handoff.md @@ -0,0 +1,352 @@ +# PR 2 Planner handoff: nested execution source and rendered output + +**Ready for planning.** The Product Owner accepts the invocation middleware, +static source inspection, five presentation decisions and main verification +journey. Prepare a self-contained implementation handoff for this slice of +[Story #881](https://github.com/taras/executable.md/issues/881). Do not send the +Implementor back to choose public API names, lifecycle semantics, source +replacement, wrapping, arrow labels, status placement or output ownership. + +This is an architecture/design handoff, not a review verdict on PR 2 code. +No PR 2 implementation, production test run or feedback commit exists in this +record. The Planner derives and freezes its concrete plan, focused commands, +visual cases and negative controls before implementation. + +## Outcome and smallest example + +An entry's useful rendered result appears in Output before Source. The execution +source shows nested rails and truthful live statuses in a shared right-aligned +column. After admission, generated XMD replaces paired Evaluate's producer +content while preserving its enclosure. Source and output are different readings. + +Abbreviated live source example; ellipses here omit attributes for illustration: + +```text +│ ● ACTIVE +│ │ ● ACTIVE +│ │ │ ● WAITING +``` + +Source wraps in the measured space to the left of the stable status column. +`[↑ earlier]` and `[↓ later]` reach every row at all supported profiles. +The labels also replace the existing caret/letter labels in Sessions, Entries +and drawer windows, preserving their semantic actions. + +## Stack and authority + +- PR 1 Planner feedback is PASS at **080b6ec80ca74e614789e8d2252857ac281df7e5**. + Its parent is f0b8eb1f323c1ad5826eafba978ef9c2e9f5fffa and its recorded base is + e68f128121cd802623ab7797a016b0c66ce91176. See pr1-planner-acceptance.md. + PR 2 depends on that accepted slice; record the actual stack base and refresh + overlapping changes before implementation. Do not replace PR 1's evidence + with a claim that later work was already accepted there. +- The architecture workspace HEAD is + 2d719f78025059158a35023701fdff52b855a65b. No current remote-head or CI verdict is + asserted by this handoff. Merged #876/#877/#878 are the measured-layout, + reveal-retention and semantic styling foundations. +- Use the older corrected reference archive, SHA-256 + **86be64318121546f3208342edaf17f0a3aed35f3fde2766b523423e6c708c77b**, + retained at evidence/reference.zip. The newer Downloads archive adds a feature + and supplies no requirement. The old archive owns visual intent; current + architecture and specifications own execution and interaction. +- Detailed accepted records are pr2-invocation-contract.md, + pr2-source-inspection.md, pr2-source-presentation.md and + pr2-product-verification.md. This handoff consolidates their consequential + contracts. The old full-story matrix is not an additional frozen PR 2 oracle. + +Read repository AGENTS.md, the required Effection instructions, architecture.md +and the affected REPL/executable-MDX sections. Reuse installed dependencies, +Freedom, contextual adapters and the model-blind renderer. Preparation belongs +to deno task setup; verification does not reinstall or mutate dependency state. + +## Accepted Core invocation interface + +Add this member to the existing Component Api and export it with its consumer +types through **@executablemd/core/api**. Preserve existing root exports. +Operation, Stream and Result are Effection types. Expansion is Core's existing +frozen id/name/optional-position description with its meaning unchanged. + +```ts +interface ComponentApi { + /** + * Surround one executable element's complete expansion. + * Core issues the request before resolution or validation. + * Delegate the exact request once; returned values carry no result authority. + * Completion includes owned teardown and final result acceptance. + */ + expand(request: ComponentExpansionRequest): Operation; +} + +interface ComponentExpansionRequest { + /** Core's detached description of the element this call surrounds. */ + readonly expansion: Expansion; + /** + * Observe the latest phase, then subsequent changes in order. + * Independent scope-owned subscriptions end after the terminal observation. + * Reading or cancelling a subscription does not start or cancel the body. + */ + readonly phases: Stream; +} + +type ComponentExpansionPhase = + | { readonly phase: "enter" } + | { readonly phase: "active" } + | { + readonly phase: "exit"; + readonly reason: "returned" | "failed" | "cancelled"; + } + | { readonly phase: "complete"; readonly result: Result } + | { readonly phase: "cancelled" }; +``` + +Core issues the exact request through an occurrence-specific canonical terminal, +following Execution.document. Delegate next(request) once. Copied, foreign, +missing or repeated delegation cannot fabricate success or run a body twice. +The operation refuses an unissued request outside canonical dispatch. +Core keeps rendered results, bindings and effective outcomes private. Returned +middleware values are ignored; catching canonical failure cannot rescue it. +Middleware faults follow the existing policy-failure reconciliation pattern. + +Cover resolution/validation before the body, accepted body and owned nested +work, ordered cleanup, final result acceptance and binding. Include Markdown, +function and value/captured invocations; equivalent structural dispatch paths +and actually executed consumed regions receive the same coverage. Unselected +and restored work that does not execute receives no invented phases. Code blocks +stay work inside their containing element. Add no resource scope to structural +syntax and change no caller-retained resource lifetime. + +ENTER precedes preparation; ACTIVE begins accepted work. EXIT reports why work +ended while cleanup/final acceptance remain pending. Early refusal never reports +ACTIVE. Returned EXIT can still become failed completion. Completion publishes +Ok(undefined) or Err(detachedReportingError), preserving the selected existing +diagnostic and explanatory Error causes without exposing canonical mutable +objects or resource handles. Clean cancellation reports cancelled after unwind; +actual cleanup failure follows Core's existing precedence. Publish exactly one +terminal phase and then close with void. Preserve recovery, printed semantic +failure, durability/Files precedence and body/teardown cause accounting. + +Independent subscribers receive the latest phase without a registration gap, +then ordered updates. Late attachment receives the terminal phase then ends. +Observation does not replay execution. A missing or slow UI does not delay Core +or wait for a rendered frame. ENTER/EXIT have no minimum animation duration. + +## Session ownership and attribution + +Install middleware in the owned entry execution lineage. The session allocates +private keys for actual calls and binds private enclosing presentation keys +around delegation, following CurrentWalk. Logical Expansion ids are not process +instance keys. Generated work keeps this lineage while its execution environment +and capabilities remain narrowed. No new ExecutionEnvironment member is needed. +Core never trusts presentation context for authorization or durable reconciliation. + +The session owns phase consumers through entry teardown. Do not join a consumer +inside a middleware handler awaiting terminal publication after that handler +unwinds. Session shutdown joins owned execution/consumers, removes subscriptions, +clears the view and prevents late revival. Use generators, scoped cleanup and +the repository's listener-registration rules. Never yield in finally. + +WAITING comes from actual unanswered Elicitation, interactive permissions and +owned expansion holds. Count independent reasons and release each on its own +resolution/cancellation. Hiding a drawer answers nothing. An import, ordinary +suspension or in-flight Prompt alone is not WAITING. Agent permission attribution +uses the bridge's actual owning turn. Waiting during cleanup preserves EXIT. +Recovered child failure does not automatically fail its parent. + +Live snapshots are immutable session data passed through the root, separate +from ReplModel and Journal history. Historical panes suppress live questions, +permissions, output and component badges while observations continue offscreen. +Return live uses the latest snapshot. Cold reads never reconstruct ephemeral +phases. A retained source region is not an invocation lifetime. + +## Accepted static source inspection + +Export this **pure helper and types from Core's existing root entrypoint**, +alongside parsing helpers. It is not a contextual runtime operation. +Reuse the existing SourceRange type; existing document-target coordinates stay +unchanged. Returned ranges index the exact inspectSource input string. + +```ts +/** + * Read executable element boundaries from source without executing it. + * Document input excludes frontmatter; fragment input follows generated + * expansion's whole-string scanning behavior. Ranges index the exact input. + */ +function inspectSource( + text: string, + kind: "document" | "fragment", +): Result; + +interface SourceElement { + /** The authored tag name, exactly as Core's scanner reads it. */ + readonly name: string; + /** Complete opening or self-closing tag, as a half-open slice of input text. */ + readonly opening: SourceRange; + /** Complete closing tag for a paired element; absent for a self-closing tag. */ + readonly closing?: SourceRange; +} + +interface SourceRange { + readonly start: number; + readonly end: number; +} +``` + +Use canonical scanner decisions, not a second CLI parser or delimiter searches. +Return all recognized nested executable elements in opening-source order as a +detached, recursively frozen list. The existing lexical incomplete-tag behavior +stays passive text; scanner refusals become Error Results. An empty list is +successful absence. Read no file, provider, contextual binding or imported +definition; evaluate no frontmatter language or prop expression, compile no +schema, and execute no code block. Document envelope extraction preserves the +execution parser's exact body boundary without interpreting its values. + +Ranges are half-open UTF-16 offsets. Opening includes the entire opening or +self-closing tag. Closing exists for every paired element, even empty content, +and is absent exactly for a self-closing element. It has no lifecycle meaning. +For paired source, 0 <= opening.start < opening.end <= closing.start < +closing.end <= text.length. Inner content is the slice opening.end to +closing.start; containment gives static nesting. Name preserves authored spelling +and does not prove resolution, execution or permission. + +## Accepted source and output presentation + +- Before paired Evaluate admission, show its original producer content. After + successful admission in the selected prefix, replace only that inner content + with exact admitted source. Keep opening/closing tags and its enclosure. + Earlier prefixes still show the producer. Self-closing Evaluate keeps its + authored row with admitted source directly beneath it as a generated child. +- Match retained admission to the known source owner and exact canonical opening + position. Require one appropriate Evaluate. Preserve existing missing/ambiguous + ownership refusals. Do not attach to a guessed sibling or invent successful + replacement for a refused admission. Original/Journal bytes remain unchanged. +- Static rails connect enclosing paired source and nested regions. Continuations + carry their enclosure. Actual calls use the right-aligned status column on the + first visual row; continuations leave it blank. Closing EXIT/terminal markers + use the same column when observed. Separate actual calls remain distinct even + when logical source ids repeat. Unselected source receives no execution badge. +- Reserve a stable measured status width for all supported readings, including + EXIT with a cleanup wait. Source retains token colours and wraps in the remaining + width. No glyph remains in the left source gutter, and no status word is cut. +- Soft-wrap source, previews and rendered output without changing logical text, + explicit newlines or blank lines. Long unbroken values continue across rows. + Use the engine's measured fit, not string length as terminal-cell width. + Metadata keeps established fitting; fields and the single-row draft retain + their current behavior. No horizontal scrolling interaction is added. +- The main reading uses the established vertical window pattern. Controls and + decoration consume capacity before admission and remain outside moving rows. + Off-window content has no nodes or targets. Positions stay process-local and + reading-owned; resizing remeasures and clamps through existing admission rules. +- At entry level, Output precedes Source in the existing transcript pane and + shares its reading window. Output is actual rendered text. Source is the + authored/generated projection. Output arriving does not automatically move a + window already being read. There is no additional pane or route. +- Use Output · live while showing session-emitted text. The retained final output + replaces it once; use Output for that reading. An empty retained result says + No rendered output. An inspected prefix lacking an entry output record says + No entry output recorded at this checkpoint. Preserve truthful outcomes and + existing diagnostics; prose containing "failed" does not decide status. +- Nested source readings show Recorded block output only where it has a known + retained owner. Do not relabel the entry's whole result as a component result, + concatenate local block outputs into a fabricated entry result, emit a bound + value implicitly, or synthesize a write receipt. Agent text stays in Agent + readings; bindings stay in binding readings. + +Lifecycle glyph/word colours come from the older reference: + +| State | Glyph | Colour | +| --- | --- | --- | +| ENTER | ▶ | #5aa87c | +| ACTIVE | ● | #7fd3e8 | +| WAITING | ● | #c99a3f | +| EXIT | ◀ | #c2766e | +| SETTLED | ✓ | #4f8468 | +| FAILED | × | #d24b3f | + +Cancellation keeps existing cancelled wording. The palette is an independent +expectation, not an import of production constants. Existing source, focus, +selection, surfaces and drawers retain PR 1's accepted roles. + +## Frozen structural checklist for architecture feedback + +1. Core retains canonical execution, exact once-only delegation, bindings and + authoritative failure/outcome selection independently of observer reporting. +2. Existing invocation/resource owners and cleanup order remain intact; final + phases follow unwind and acceptance. Session consumers neither deadlock + dispatch nor outlive session teardown or revive removed entries. +3. Generated execution retains its narrowed capabilities. Private presentation + context supplies no permission, durable identity or reconciliation authority. +4. Static inspection uses canonical parsing and evaluates/executes/loads nothing. + Replacement is anchored in retained ownership and exact source ranges. +5. No persistence change occurs. Conforming observed/unobserved runs retain + identical canonical output, bindings, failure disposition and Journal bytes. +6. Inspected content stays prefix-only and receives no live overlays; cold + reads perform no provider activity or source load. Output has its actual owner. +7. Root-owned immutable view data and semantic actions use the existing measured + admission, mounted tree, focus and frame-target boundary. Absent rows/outlets + contribute no resources or targets, and inspection owns no execution. + +This checklist freezes architecture review. Ordinary visual correctness and +evidence sufficiency belong to the Planner. New structural criteria require an +explicit architecture amendment, not a later implicit review expansion. + +## Planner work and evidence + +Use the accepted eight-step main journey in pr2-product-verification.md at +160×36, 120×30 and 72×20. Derive companion evidence from the accepted contracts: +self-closing source, unselected branches, actual repeated/concurrent calls, +overlapping waits, held/failing cleanup, early refusal, printed failure, +recovery, cancellation, independent/late subscriptions and cold inspection. +Use real runtime records and owned operations, never fabricated lifetimes. + +The plan names exact coverage sites: ordinary/structural dispatch, consumed +regions and generated work; source-range collection and no-evaluation envelope +extraction; session observations/waits; root source/output descriptions and +window admission. Classify Component.expand in the existing REPL expansion +controller boundary inventory and its repl-execution.test.ts regression. + +The current renderer exposes measured bounds, not a public line-break map. +Explain the private engine measurement that yields wrapped rows and their +window count before implementation. Width, rail/status reservation, wrapping, +row count and visible targets must use one consistent prepared reading. Keep +renderer input engine operations, preserve measurement/commit isolation, and +register no extra host reader or frame subscriber merely to draw static rails. +If the concrete plan needs another public boundary, return that specific choice +to the Architect before adding it. + +Freeze a finite PR 2 gallery for M2/M4/M6 and the necessary narrow, prefix/cold +and wrapping cases. Map older JSX/reference frames with archive hash, scene, +profile and provenance. Freeze focused tests and meaningful isolated break +controls for source rails, canonical lifecycle, source replacement and status/ +wrapping/output ownership. Do not silently inherit PR 1's exact 35-pair count +or claim the complete-story gallery. Planner evidence sufficiency is delegated. + +Candidate affected tests include Core component-api, invocation-scope, +invocation-failures, invocation-identity, expansion-metadata, scanner, +document-targets and document-target-execution; CLI repl-execution, repl-model, +repl-presentation-style, repl-layout-admission, repl-forms and repl-agent-journey. +Select the smallest discriminating files, add explicit black-box/fixture cases, +and publish every actual focused command. No exhaustive runtime battery is +required for feedback. After focused evidence passes, create the stable feedback +commit promptly and return its exact SHA and stack base. Preserve first failure +output and follow the repository's flake rules where applicable. + +Update architecture.md and affected specifications when their corresponding +behavior exists, in present tense. Do not publish completed #881/PR 3 contracts +ahead of their implementation. Required CI and delivery verification retain +their normal authority; neither is architecture feedback evidence. + +## Exclusions and next action + +No Journal/sidecar/timestamp protocol, general tracing framework, dependency or +vendor change, additional terminal reader, new schema capability, automatic +drawer, multiline editor, fork or newer reference feature belongs to PR 2. +History rail geometry/head-summary presentation belongs to PR 3, whose accepted +contracts are now in pr3-planner-handoff.md. Its full-story gallery remains +Planner work. Existing History selection is used only to prove PR 2's +prefix isolation and return-live behavior. + +Next Planner action: freeze the conforming PR 2 implementation plan and evidence +against these accepted contracts, then issue its implementation handoff. +PR 3's architecture interviews are complete under its separate ready handoff. +No GitHub mutation, production change, implementation verdict or delivery +approval is issued here. diff --git a/.reviewer/issue-881/pr2-planner-rereview.md b/.reviewer/issue-881/pr2-planner-rereview.md new file mode 100644 index 000000000..4e2492031 --- /dev/null +++ b/.reviewer/issue-881/pr2-planner-rereview.md @@ -0,0 +1,189 @@ +# PR 2 Planner re-review and independent structural review + +**REQUEST CHANGES** at **82a915ae70cb96bc03d61d84c501d96430a86c08**. + +R1–R3 are closed. The remaining blocking finding is **R4: question previews +still lose long-line text**. The Plan source preview and README confirmation +use one drawer row per logical line; they do not receive the lossless measured +wrapping added to the main reading. This fails the existing S2 requirement and +accepted journey steps 2/5. No architecture amendment or persistence change is +needed. PR 1 remains accepted. PR 3's implementation dependency remains unmet. + +## Reviewed revision and prior findings + +Branch: `agent/issue-881-pr2`. Parent: +`670eb21af74c17db304f083cf5640d00e368b037`. Integrated base: +`c7d54769d56661bef38cee8549b148f3bf87a904`, combining accepted PR 1 +`080b6ec80ca74e614789e8d2252857ac281df7e5` and main +`4c0414be1010f69f11bff0d1d634623a5b08f886`. +The implementation worktree stayed clean at the reviewed SHA. This review +changes review artifacts only. It uses no production edits, subagents, GitHub +mutation or CI verdict. + +| Prior finding | Independent result at this revision | +| --- | --- | +| R1: authentic foreign invocation request runs work before refusal | **Closed.** The terminal compares exact request identity before claiming/delegating. The original read-only probe now reports `bodies: []` and ComponentExpansionProtocolError. CX1 also proves both genuine requests remain usable by their own terminals. | +| R2: lexical envelope changes accepted execution inputs | **Closed.** BOM/no-header, unterminated header, delimiter-with-suffix and ordinary header probes agree with the installed extractor and execute through parseSource. The focused envelope regression covers 24 shapes; inspection still evaluates no header values. | +| R3: mutable shared phases and aggregate explanation | **Closed.** Publication freezes each phase; detached aggregate member arrays are frozen. The probe's late reader receives the unchanged complete observation, with frozen phase/Result/error/member data. | +| K1 described recolouring as rail removal | **Closed.** K1 now removes the rail glyph and fails the composed-row assertion. K1b retains the separate EXIT-colour check. All 14 supplied controls have nonzero results, substantive first failures and restored hashes matching current production bytes. These records were inspected, not rerun by the Planner. | +| Committed scratch outputs and vacuous diff check | **Closed.** Scratch log/control outputs are removed from the product diff. `git diff --check c7d54769..82a915ae` exits 0. | +| Copied-bounds explanation and unstable evidence packet | **Closed.** The redundant geometry copy is removed; renderer.measure already copies bounds. The packet is stable: 320/320 listed hashes match both integrity reads, with 44 frozen pairs. All 16 contact sheets were opened. Opening them does not establish visual acceptance: R4 remains. | + +The prior requests in pr2-planner-review.md and +pr2-independent-architecture-review.md remain historical records for 9d8bc463. +This review supersedes their outstanding-finding list for the new SHA. + +## R4: preserve every character of question preview content + +In the real Plan-to-README journey, enter Northstar and +`A lightweight workspace for coordinating coding agents.`, submit the details, +and open the README confirmation. At **72×20**, scroll its own `[↓ later]` +control through the entire drawer. The summary reads: + +```text +"summary": "A lightweight workspace for coordinati +} +``` + +There is no continuation containing `ng coding agents.` or the closing quote. +All eleven captured narrow preview windows omit that tail. Approve, Decline and +submit are reachable, so reaching the controls alone misses the defect. +The 160×36 preview and the actual README contain the complete value; this is +presentation loss, not malformed input or a missing program result. + +Decisive evidence: + +- [Narrow summary and next row](pr2-planner-rereview-evidence/captures/readme-preview-traverse-72x20-04.png), with raw ANSI/text beside it. +- [Last decision controls](pr2-planner-rereview-evidence/captures/preview-last-controls-72x20.png). +- [Full wide preview](pr2-planner-rereview-evidence/captures/preview-open-wide.txt) and [actual README](pr2-planner-rereview-evidence/actual-README.md). +- [Traversal comparison](pr2-planner-rereview-evidence/preview-clipping-probe.json): full value present wide/in-file, absent tail in every narrow window. +- The supplied frozen `pr2-evidence/captures/plan-review-160x36.txt` exposes the same boundary in the Plan source preview: its first Elicit opening ends at `description: "Name y`, then the next logical content appears. The rest of that schema has no continuation. + +The affected boundary is `application.ts:3386`: question.message is split into +logical lines and each becomes one drawerLine. `drawerContentRows` at 3659 also +counts logical lines. `program.ts:1439` prepares the main Output/Source reading, +but not this preview content. Vertical scrolling can only reveal rows that +were prepared; it cannot recover the remainder of these single-row lines. + +Apply the existing private engine-measured wrapping approach to the question's +read-only message/source preview at its actual inset content width. Preserve +all text, explicit blank lines and token roles. Use the resulting visual rows +consistently for drawer description, row count, admission, scroll bounds and +mounted targets. Keep the established field, metadata, focus and answer +semantics. This asks for no public interface, new reader or persistence. + +Extend the existing S2/journey evidence through the **actual composed drawer**: +read the full long Plan schema and the full README summary through normalized +scroll controls, including closing delimiters/quotes, and reach the existing +decisions afterward. Concatenating the displayed fragments must recover the +original logical text and roles. An assertion on prepareReading alone, or on +Approve's visibility, is insufficient. This is a frozen criterion, not another +scenario added to acceptance. + +## Focused commands and independent structural checks + +From `.claude/worktrees/issue-881-pr2`: + +```sh +deno task test packages/core/tests/component-expansion.test.ts packages/core/tests/source-inspection.test.ts packages/core/tests/component-api.test.ts packages/core/tests/invocation-scope.test.ts packages/core/tests/invocation-failures.test.ts packages/core/tests/invocation-identity.test.ts packages/core/tests/expansion-metadata.test.ts packages/core/tests/scanner.test.ts packages/core/tests/document-targets.test.ts packages/core/tests/document-target-execution.test.ts packages/core/tests/evaluate-component.test.ts +deno task test packages/cli/tests/repl-source-reading.test.ts packages/cli/tests/repl-execution.test.ts packages/cli/tests/repl-entries.test.ts packages/cli/tests/repl-layout-admission.test.ts packages/cli/tests/repl-presentation-style.test.ts packages/cli/tests/repl-forms.test.ts packages/cli/tests/repl-journey.test.ts packages/cli/tests/repl-agent-journey.test.ts +deno task test packages/cli/tests/repl-lifecycle.test.ts packages/cli/tests/repl-agent-execution.test.ts +git diff --check c7d54769..82a915ae +``` + +All exit 0: **Core 53 tests / 414 steps; CLI 94 / 314; supplemental 14 / 52**. +Full outputs are core.log, cli.log and lifecycle.log in the new evidence folder. +The read-only contract probe also exits 0, closing R1–R3. Its source and output +are retained there. It ran from the repository root against the implementation +worktree's config: + +```sh +deno run --allow-all --config .claude/worktrees/issue-881-pr2/deno.json --node-modules-dir=manual --cached-only --frozen /private/tmp/issue881-planner-82a915ae/contract-probe.ts +``` These passing tests do not discriminate R4. + +This is an independent review by the Planner, who did not implement PR 2. It +checks the seven frozen requirements, without adopting the Implementor's +self-assessment as a verdict. + +| Frozen structural check | Result | +| --- | --- | +| 1. Canonical execution, exact delegation, outcome authority | Supported after R1/R3 corrections: exact identity precedes work; canonical failure and binding acceptance remain Core-owned. | +| 2. Existing owners, ordered cleanup, consumer lifetime | Held body/cleanup/middleware cleanup, failure/cancellation and session release tests pass. This live run completes Plan approval and teardown without the former storage collision. | +| 3. Narrow generated capabilities; presentation grants no authority | Generated execution and lifecycle regressions pass; CurrentOccurrence remains presentation lineage, not authorization or durable identity. | +| 4. Pure canonical inspection and retained replacement ownership | Supported after R2: shared canonical scanner, lexical-only envelope and exact retained-range replacement. | +| 5. No persistence extension; observed/unobserved equivalence | Focused canonical comparisons pass for output, bindings, failure and serialized Journal bytes. No retained lifecycle field/record is introduced. | +| 6. Prefix isolation, cold reads, actual output owner | Offscreen and cold checks pass below. TL10's compile/source-read counters stay zero; actual output/report belongs to the entry. | +| 7. Immutable root view, measured preparation/admission, mounted targets | Root/action/main-reading ownership remains intact. **Preview preparation is incomplete (R4)**: question-message content is not represented by the lossless visual rows the frozen presentation requires. | + +## Planner-owned journey and visual evidence + +The Planner drove one real execution through the accepted story, visiting all +three profiles at each recorded stage, with additional narrow traversal. Inputs, +provider records, raw captures and selected images are retained. No view state +was injected. + +| Accepted step | Independent result | +| --- | --- | +| 1. Original nested Plan and ACTIVE statuses | Passed at 160×36, 120×30 and 72×20; nested-running captures. | +| 2. Plan review, decisions, close/reopen | Pending question and source preservation pass at all profiles: plan-review-controls, plan-dismissed, plan-reopened. Full source-preview readability fails R4. | +| 3. Generated source inside Evaluate | Passed: original producer is replaced after admission; enclosure remains. generated-inline and the 52 narrow source-traversal windows reach the schema tail and closing Evaluate. | +| 4. Empty validation and populated form | Passed through existing interaction: invalid-details, completed-details, populated refusal/recovery. The known focus behavior required the established wide focus workaround; narrow field entry and submission are recorded. Fields were refilled after an additional driver close/reopen discarded unsubmitted values. | +| 5. Whole README preview, approval and result | **Fails R4.** Approval succeeds, the real file contains the complete values, Output starts with the document, and its actual final report is reachable. The preview loses text. File existence alone is not presented as an independent write-count measurement; canonical once-only evidence remains in the focused Core suites. | +| 6. Earlier prefix, offscreen advance and return live | Passed at all profiles: provider completes and a question arrives offscreen while selected source stays unchanged; return live shows the current question. | +| 7. Resize and reachable content | Supported profiles and populated 60×15 refusal/recovery pass. Explicit narrow source traversal and cold output/report/source-end reads pass. Preview wrapping remains R4. | +| 8. Cold head and earlier-prefix reopen | Passed at all profiles. Original producer returns in the early prefix with no future output or live badges. Journal/provider hashes remain identical. | + +The exact cold head is: +`xmd://repl/bbc58804e58e43a8e2f8b802e8fa59c8/entries/entry-1`. +The earlier prefix is that URI plus `?at=yield:root:0&inspect`. +Across head/prefix reopens and the additional narrow tail read, the Journal +stays **47,323 bytes / 35 lines**, SHA-256 +`847ee05b07d9e1305d545fdc7093e2bbc99df04ed2fb03215101316a59d9ef9e`. +The provider log stays **8,521 bytes / 11 lines**, SHA-256 +`eba0a2f670904a31a521728050fd1935e90912931d0c0e43c34773729094821c`. +Source-load/compile assertions come from the frozen cold regressions; these +hashes alone do not measure source loads. + +All **44 frozen comparison pairs** were opened through **16 supplied contact +sheets**, using the older reference archive +`86be64318121546f3208342edaf17f0a3aed35f3fde2766b523423e6c708c77b`. +The complete image inventory is image-review.md. Supplementary Planner captures +do not enlarge the frozen gallery. The gallery is reviewed, but not accepted +because of R4. + +Driver failures and corrections are preserved in driver-notes.md and their +first logs/captures. In particular, planner-journey-finish.log's generic +“whole preview”/“passed” messages are withdrawn: its checks established controls +and traversal, not retention of every preview character. The visual review and +preview-clipping-probe.json establish the failed requirement. This document is +the authoritative verdict. No flaky product rerun is claimed. + +## Ready-to-send revision prompt + +> Revise PR 2 from 82a915ae70cb96bc03d61d84c501d96430a86c08 for R4 only. +> Preserve the closed R1–R3 corrections. Prepare the actual question-message +> preview as lossless engine-measured visual rows, at the drawer's measured +> inset width, and use those rows for rendering, admission and scrolling. +> The original Plan schema and the README confirmation must remain entirely +> readable with their token roles, including the missing summary tail and +> closing quote. Keep current fields, focus and answer semantics; add no public +> API, persistence or Journal change. +> +> Extend the existing S2/journey regression through committed drawer cells and +> normalized scrolling so it fails on this revision, rather than merely proving +> that Approve is reachable. Run the frozen focused commands and base-to-head +> diff check, commit promptly once they pass, and return the exact SHA/parent/base. +> Refresh the unchanged 44-pair gallery from that SHA and the affected clipping +> control, retaining first failure and byte restoration. Preserve unaffected +> control evidence with clear provenance. Do not expand the gallery or rewrite +> PR 1's accepted record; do not push or open a PR. +> +> Return implementation evidence. The Planner retains visual re-review and the +> accept-or-request-changes verdict. PR 3 remains at its frozen handoff, waiting +> for PR 2 acceptance. + +Continuity: reviewed SHA and integrated base are above. Produced artifacts are +this review and pr2-planner-rereview-evidence/. R1–R3 and the previous packet/ +handback corrections are closed. R4 is the sole remaining blocking finding; +it restores the already accepted preview-wrapping contract. Next Implementor +action is that focused revision. No complete #881 or delivery acceptance is issued. diff --git a/.reviewer/issue-881/pr2-planner-review.md b/.reviewer/issue-881/pr2-planner-review.md new file mode 100644 index 000000000..096e5b2e1 --- /dev/null +++ b/.reviewer/issue-881/pr2-planner-review.md @@ -0,0 +1,159 @@ +# PR 2 Planner review + +**REQUEST CHANGES** at `9d8bc463297c39edd8893c8404c1dd674700cb23`. + +Three reproduced defects violate the settled contract: a foreign invocation +request can execute the current body before refusal; the lexical envelope +rejects an existing BOM-prefixed document; and published phase objects and +aggregate cause arrays are mutable. The independent review and corrections are +in [pr2-independent-architecture-review.md](pr2-independent-architecture-review.md). +No Journal or persistence change is needed. PR 1 remains accepted; PR 3 remains +outside this implementation verdict. + +## Reviewed revision and focused evidence + +Branch `agent/issue-881-pr2`; integrated base `c7d54769`, consisting of accepted +PR 1 `080b6ec80ca74e614789e8d2252857ac281df7e5` and main +`4c0414be1010f69f11bff0d1d634623a5b08f886`. The implementation worktree was +clean and stayed at the full reviewed SHA. The Planner changed only review +artifacts and ran isolated review fixtures. No production code, commit, push, +PR, GitHub mutation, CI inspection or subagent was used. + +These commands ran from `.claude/worktrees/issue-881-pr2`: + +```sh +deno task test packages/core/tests/component-expansion.test.ts packages/core/tests/source-inspection.test.ts packages/core/tests/component-api.test.ts packages/core/tests/invocation-scope.test.ts packages/core/tests/invocation-failures.test.ts packages/core/tests/invocation-identity.test.ts packages/core/tests/expansion-metadata.test.ts packages/core/tests/scanner.test.ts packages/core/tests/document-targets.test.ts packages/core/tests/document-target-execution.test.ts packages/core/tests/evaluate-component.test.ts +deno task test packages/cli/tests/repl-source-reading.test.ts packages/cli/tests/repl-execution.test.ts packages/cli/tests/repl-entries.test.ts packages/cli/tests/repl-layout-admission.test.ts packages/cli/tests/repl-presentation-style.test.ts packages/cli/tests/repl-forms.test.ts packages/cli/tests/repl-journey.test.ts packages/cli/tests/repl-agent-journey.test.ts +deno task test packages/cli/tests/repl-lifecycle.test.ts packages/cli/tests/repl-agent-execution.test.ts +``` + +All three exited 0: respectively **53 tests / 411 steps**, **94 / 313** and +**14 / 52**. Full outputs are retained as `pr2-planner-evidence/core.log`, +`cli.log` and `lifecycle.log`. These passing tests do not catch R1–R3; the +read-only contract probe reproduces them at this same revision. + +The ten supplied control records all report nonzero exits and identical +before/after production hashes. They were inspected, not rerun against the +reviewed worktree. K1 is described as “remove the rails,” but its saved mutation +changes EXIT's rail colour to pending; it does not remove a rail. Run the +original frozen rail-removal control with the affected frame evidence in the +revision. Preserve the complete first failure, rather than only the generic +`expect(received).toBe(expected)` line. + +## Independent structural checklist + +This table records the independent review of the seven existing checks; it +adds none. The overall verdict is REQUEST CHANGES. + +| Frozen check | Review result | +| --- | --- | +| 1. Canonical execution, exact delegation and outcome authority | **Fails R1.** Canonical failure capture and ignored middleware returns have passing focused evidence, but an authentic foreign request reaches the wrong continuation. R3 also contradicts the accepted immutable reporting contract. | +| 2. Existing owners, cleanup order and consumer lifetime | Held body/cleanup/middleware cleanup, cancellation, failed teardown and session retirement pass the focused CX/L3 suites. The live journey stopped on a missing Plan directory during cleanup; its cause is unresolved, so the journey supplies no additional acceptance of this requirement. | +| 3. Generated capabilities remain narrow; presentation grants no authority | Supported by the generated execution and lifecycle tests and the unchanged capability ownership boundary. Private CurrentOccurrence data selects presentation lineage, not permission or durable identity. | +| 4. Pure canonical inspection and exact replacement ownership | **Fails R2.** Scanner reuse and retained-range replacement have passing evidence, but document-envelope equivalence does not hold. | +| 5. No persistence change; observed/unobserved equivalence | Supported by the focused Core/session comparisons of output, bindings, failure and serialized Journal bytes. No new retained lifecycle record or field was introduced. | +| 6. Prefix isolation, cold reads and actual output ownership | Focused suites and the independent offscreen/cold checks below pass. Cold inspection of the supplied settled run and its earlier prefix leaves Journal/provider bytes unchanged. | +| 7. Root view data, measured admission, mounted targets and no hidden resources | Supported by the focused rendering/admission/source-reading suites and inspected fitting/description path. The complete 44-pair visual review is not accepted here because the supplied packet was changing. | + +## Planner journey: what was actually walked + +The Planner drove the real Deno entrypoint at the reviewed SHA through a private +tmux socket, with a local provider and temporary working directory. No +presentation state was injected. Scripts, normalized actions, raw ANSI/text +captures and selected rasterizations are in `pr2-planner-evidence/`. + +| Accepted step | Independent evidence and result | +| --- | --- | +| 1. Submit original Plan; nested ACTIVE reading | **Passed at all three profiles.** `captures/nested-running-*` shows Evaluate/Plan, nested rails and independent ACTIVE badges inside the pane. | +| 2. Preview/decisions; close and reopen unanswered | **Passed at all three profiles.** `plan-review-controls-*`, `plan-dismissed-*` and `plan-reopened-*`; source rows compare unchanged, and the pending question remains available. WAITING belongs to the actual nested Elicit; its active ancestors need not inherit that badge. | +| 3. Approve and inspect admitted source | **Not completed live.** Approval ends this attempt with a missing Plan session-directory diagnostic, before generated admission. The first failure is preserved. | +| 4. Invalid and populated project form | **Not reached in this live walk.** Passing focused tests and Implementor captures are not described as a Planner walk. | +| 5. Preview, write once, Output before Source | **Not reached live.** Independent cold reading confirms retained Output begins with the rendered document and includes the real final report. It does not prove the live approval/write path. | +| 6. Earlier prefix, offscreen advance, return live | **Passed at all three profiles.** While the provider was held, select Entry 1 admitted. Release it offscreen; the provider completes and the question arrives. `offscreen-before-*` / `offscreen-after-*` preserve the selected source; `offscreen-return-*` shows the current pending question after returning live. | +| 7. Resize and populated recovery | Supported sizes were exercised in the ACTIVE, question and historical states. **Populated-question refusal/recovery was not reached live.** No complete-step claim is made. | +| 8. Cold head and earlier-prefix reopen | **Passed at all three profiles.** `planner-cold-final.log`, `independent-cold-settled-*`, `independent-cold-historical-*` and `independent-cold-prefix-reopened-*`. No live badges reappear. | + +The decisive live log is `planner-journey-pty-4.log`. At approval, the diagnostic +names `/Users/tarasmankovski/.xmd/plan/sessions/3b1a41e4f5c8bc727bb15aa945f5f7023733b1dd76801c23260f2b42ae2f75ba` +and says the directory was already gone. Another evidence journey was actively +running against the same host storage during review. Concurrent interference is +a possible explanation, not an established cause or an additional #881 code +finding. Preserve this failure and complete the remaining live steps in a +non-overlapping review run after the revision; do not assign that Planner work +to the Implementor. + +For cold verification, the Planner reopened the supplied settled execution +`77890cfe1f8dbaefdf2c69b3b2cbd586`, selected Entry 1 and then its first admitted +prefix, exited and reopened the actual printed prefix URI: + +```text +xmd://repl/77890cfe1f8dbaefdf2c69b3b2cbd586/entries/entry-1?at=yield:root:0&inspect +``` + +Across these cold reads the Journal stays **49,022 bytes / 38 lines**, SHA-256 +`a7fd1d0e3105a003474f07242dcc1404f63d4a7193f98c582c9572889deb4f5a`. +The independent provider log stays **31,149 bytes / 42 lines**, SHA-256 +`e69738b96e17f52c1a392a9e9070b01588b8246bee9bcef6def82793f674aa9d`. +`repl-journey.test.ts` TL10 supplies the source-load counters (zero compiles, +zero Markdown reads and zero questions); file/provider hash +comparisons alone are not claimed to measure source loads. + +Early review-harness failures are preserved separately. They concern tmux socket +access in the sandbox, the absent Transcript heading in narrow mode, requiring +a parent's badge/guidance instead of checking the pending question, and reading +a wrapped exit URI at 72 columns. These are corrected review helpers, not +product defects or unexplained green reruns. The cold-prefix URI is read at +160 columns before reopening; its captures then exercise every profile. + +## Evidence packet and handback corrections + +The handed-back packet was being rebuilt during review. Its captures, actions, +provider log and journey script changed after the checksum list was written; +the gallery manifest and contact sheets were absent. The saved integrity +snapshot found only 37 of 319 listed files matching. This records the packet at +that time, not a claim about who changed it or its final state. The Planner has +not accepted or claimed to open all 44 visual pairs. Keep the frozen gallery +separate from supplementary journey evidence and return a complete stable +packet for the revised SHA. + +The reviewed commit also tracks an approximately 79,900-line scratch test log, +`.cliall.log`, and `.controls.json` at the repository root. The branch comparison +`git diff --check c7d54769..9d8bc463` exits 2 because that log has trailing +whitespace and a blank final line; output is retained in +`pr2-planner-evidence/branch-diff-check.log`. An empty working-tree diff does +not check the committed change. Remove scratch outputs from the product commit +and retain useful evidence under the review directory. + +Correct the self-assessment's measurement note: `ReplRenderer.measure` already +returns copied bounds at this revision. No renderer architecture decision is +opened by that inaccurate note. + +## Ready-to-send revision prompt + +> Revise PR 2 from `9d8bc463297c39edd8893c8404c1dd674700cb23` under the accepted +> contracts. Fix R1–R3 in `pr2-independent-architecture-review.md`: correlate +> each terminal with its exact request before claiming or running work; make +> pure lexical envelope extraction match existing execution, including a BOM +> without a header; and freeze published phases and explanatory aggregate +> member arrays. Extend the existing C1, C3/C4 and C5 tests with the supplied +> discriminating reproductions. These restore frozen requirements and require +> no new API, persistence or Journal design. +> +> Remove the committed scratch log/control outputs from the product diff, +> retain their evidence separately, and correct the copied-bounds statement. +> Run the frozen Core and CLI commands, the supplemental lifecycle command, +> and a base-to-feedback `git diff --check`. Commit promptly once the focused +> evidence passes. Return the exact SHA, parent and base, complete first +> failures and byte restoration for the relevant controls, including the +> frozen rail-removal control, and a stable 44-pair gallery/checksum packet +> from that revision. Supplementary journey captures do not enlarge the +> frozen gallery. Do not push or open a PR. +> +> Return implementation feedback only. The Planner retains the remaining +> live journey, independent review of the corrections, and accept-or-request- +> changes verdict. Keep PR 1's accepted evidence and PR 3's scope unchanged. + +Continuity: this review returns REQUEST CHANGES against the full SHA above. +The three contract corrections are settled, not questions for the Implementor. +The live journey and full gallery remain incomplete as explicitly recorded; +they are not represented as an approval or handed to the Implementor to judge. diff --git a/.reviewer/issue-881/pr2-product-verification.md b/.reviewer/issue-881/pr2-product-verification.md new file mode 100644 index 000000000..0155a806f --- /dev/null +++ b/.reviewer/issue-881/pr2-product-verification.md @@ -0,0 +1,97 @@ +# PR 2: product verification review + +Status: the main journey is accepted by the Product Owner. Companion checks +derive from accepted contracts; exact implementation evidence belongs to the Planner. +The invocation and presentation +contracts are accepted in [pr2-invocation-contract.md](pr2-invocation-contract.md) +and [pr2-source-presentation.md](pr2-source-presentation.md). This record describes +what a person must see working before the Planner freezes the implementation +evidence. It does not report tests or captures already run. + +## Main journey: follow Plan into generated source and read its result + +Run the original [plan-entry.md](plan-entry.md) through its real Plan review, +project-details question and README confirmation. The local provider fixture +supplies the original [generated-readme.md](generated-readme.md). Run this +journey at 160×36, 120×30 and 72×20, using the existing explicit drawer activation +and normalized controls. No presentation hook injects a fabricated state. + +1. Submit the entry. Its source reading shows Evaluate containing Plan and the + original prompt. Nested source rails establish their relationship. Actual + executing calls have independently coloured, full-word statuses aligned at + the right edge; an import returning alone does not mean SETTLED. +2. Open the announced Plan review. Reach its source preview and decisions using + `[↑ earlier]` / `[↓ later]`. Close the drawer without answering and reopen it: + the actual question remains WAITING, with the original source unchanged. +3. Approve the plan. In the source reading, the admitted generated heading and + first Elicit replace Evaluate's inner producer content. Evaluate's opening + and closing tags remain. This source is distinct from rendered output. +4. Open project details, submit empty values, and observe the existing validation + behavior. Enter Northstar and its description. At 72×20, reach the generated + schema's closing delimiters and all decision controls. Soft wrapping retains + text and token colours; continuation rows add no invocation or badge. +5. Reach and read the whole README preview, then approve. Read the settled entry + from its first window: Output precedes Source and begins with the rendered + document, without unrelated effect summaries before it. Reach the actual + `README.md was created.` report and inspect the generated source afterward. + The real file write happens once; the UI invents no receipt. +6. Inspect a retained prefix from before generated admission. The source shows + Plan again, without future generated text, later bindings, entry output or + live badges. Let the session advance offscreen, then return live: its reading + uses the latest snapshot. Existing History navigation performs the selection; + this journey does not accept PR 3's unreviewed rail geometry. +7. Resize through the supported profiles while reading wrapped content. The + whole status column stays within the source pane, and its reservation remains + stable across phase changes. Selection, focus, draft and question semantics + survive the existing admission rules. The fixed seven-row footer and narrow + route remain intact; every source and output row is reachable. +8. Cold-open the settled entry and the earlier retained prefix. Read the same + retained source and output, with no reconstructed live component badges, + provider activity, component-source load or Journal mutation. Process-local + window positions begin at their established initial position. + +This journey fails if source is merely appended after admission metadata, the +schema's tail or last preview line cannot be reached, statuses overwrite source +or shift its width, hiding a drawer answers a wait, output is attributed to the +wrong owner, or inspection borrows live/future content. + +**Decision: accepted.** The Product Owner accepts this original Plan-to-README +journey, including all three profiles, access to wrapped content, earlier-prefix +inspection, return live and cold reconstruction. This approves the verification +coverage; it does not report an implementation verdict or freeze capture counts. + +## Companion coverage derived from accepted contracts + +These checks give the already accepted boundary behavior concrete evidence. +They do not introduce another product decision or public API. The Planner names +the focused fixtures and commands in its handoff. + +| Accepted behavior | Concrete evidence | Incomplete result caught | +| --- | --- | --- | +| Self-closing Evaluate keeps its authored row and owns the admitted source beneath it | Read a program containing a File read, then inspect before admission. The file contents are Output; the File tag is Source. | Fabricated paired syntax or source presented as output. | +| Unselected source branches have structure without a fabricated execution state | Decline the README confirmation. The actual no-file report renders, no write happens, and the unselected File branch has no invocation badge. | Treating every source element as executed. | +| Concurrent/repeated calls remain distinct; waits have independent owners | Run real siblings and repeated source occurrences, with overlapping question/permission waits. Resolve one without erasing the other. | A shared current badge or session-wide waiting boolean. | +| EXIT lasts through owned cleanup and final acceptance | Hold cleanup after body return, then let it finish; separately exercise refused preparation, printed failure, result rejection and cleanup failure. Recover one child failure through the existing Core boundary. | SETTLED at body return, a caught failure reported as success or automatic parent failure. | +| Cancellation finishes its unwind once and preserves failure precedence | Cancel while a question waits; verify clean cancellation and a separate cleanup-failure case. Session shutdown clears waits and prevents late revival. | Invented success, hidden cleanup failure or leaked subscriptions. | +| Observation is independent and carries no execution authority | Observe with independent and late readers, with a slow/absent UI consumer; compare conforming observed and unobserved runs. | Competing readers, execution waiting for a frame, exposed canonical results or Journal changes. | +| Output follows its known owner and actual rendering behavior | Read a narrower recorded block output, a bound value emitting nothing, an empty rendered result, and successful text containing "failed". | Fabricated entry output, implicit bound-value output or status inferred from prose. | + +## Planner evidence boundary + +Use the older corrected archive with SHA-256 +`86be64318121546f3208342edaf17f0a3aed35f3fde2766b523423e6c708c77b`. +Map PR 2's M2/M4/M6 scenes to actual older source/reference frames; the accepted +terminal adaptations govern layout, not a newer archive or fabricated clock. +Independent colour expectations include the lifecycle literals. Assertions +inspect committed cells, mounted targets and real operation ownership. + +Freeze the exact scene list, visual pairs, focused commands and negative controls +in the Planner's PR 2 handoff. Do not claim the complete-story gallery or PR 3 +History acceptance from this slice. Keep PR 1's accepted SHA and its evidence +unchanged as a record of that slice. Feedback and delivery remain separate. + +The canonical static source-range boundary is accepted in pr2-source-inspection.md. +The ready pr2-planner-handoff.md carries every accepted contract. The plan explains +the private engine measurement used for wrapped row windows before implementation. +No second source parser, persistence extension, provider during +inspection or new terminal reader is part of the accepted behavior. diff --git a/.reviewer/issue-881/pr2-published-architecture-rereview.md b/.reviewer/issue-881/pr2-published-architecture-rereview.md new file mode 100644 index 000000000..4fc101704 --- /dev/null +++ b/.reviewer/issue-881/pr2-published-architecture-rereview.md @@ -0,0 +1,112 @@ +# PR 2 architecture re-review — #886 + +**REQUEST CHANGES** on `a85c36cb2edc184055b9aa3e270ba1d70b20670f`. +The previously reported fatal-precedence blocker remains and reproduces on this +exact head. The published revision changes lifecycle tests only; it contains no +production correction. + +## Reviewed boundary + +Reviewed [PR #886](https://github.com/taras/executable.md/pull/886) on 2026-10-10 +against main `160e354e47f6fbeb1c792e6799c1fe26b2f155fc`. The head's parent is +the previously reviewed `3815aef4eb72000c2c59f8b06a8e01ed8c9070b5`. +The PR head and base were read again after the checks and remain unchanged. + +The complete delta from the previous review is +`packages/cli/tests/repl-lifecycle.test.ts`: it removes redundant scoped wrappers +from individual tests while preserving the assertions and the comparison's +separate run scopes. All production code, specifications and architecture are +unchanged. The [previous architecture review](pr2-published-architecture-review.md) +records the full seven-item structural trace; this review checks the new delta +and reproduces its remaining blocker rather than relabelling earlier evidence. + +#885 remains merged. #887 depends on #886; the new #889 performance slice +depends on #887 and changes private REPL fitting/application code. Neither +descendant is a dependency of this review or covered by its verdict. The older +corrected reference and accepted #881 contracts remain authoritative. + +## R1 remains: a body failure suppresses a fatal middleware failure + +Frozen checklist item 1 in [pr2-planner-handoff.md](pr2-planner-handoff.md), the +[invocation contract](pr2-invocation-contract.md), and the implementation handoff +require authoritative failure selection to preserve existing durability/Files +fatal precedence across canonical work and middleware cleanup. + +At this exact head, `packages/core/src/component-expansion.ts:369` retains the +middleware failure in `chainFailure`, but lines 377–380 unconditionally throw +`settlement.raised` when canonical work failed. This bypasses fatal causes in +the middleware failure and reports the ordinary canonical error as terminal. +The established `Execution.document` reconciliation at +`packages/core/src/execute.ts:3244` instead examines both outcomes for durability +failure, then Files fatal failure, before ordinary canonical-failure precedence. +The component boundary discards the fatal cause before enclosing reconciliation +can recover it. + +The [exact-head reproducer](evidence/pr886-a85c36cb-fatal-precedence.test.ts) +uses public `Component.around({ expand })` middleware around real +`expandSegments` execution. It delegates the exact request once. The component +raises an ordinary error and the middleware raises a genuine +`DurablePersistenceError` from its synchronous `finally` during unwind. + +Expected: the persistence failure wins. Actual: the ordinary body failure wins +and `durabilityFailure(caught)` is `undefined`. The successful-body control +preserves the persistence failure. The [fresh output](evidence/pr886-a85c36cb-fatal-precedence.log) +records one passing control step and one failing regression step. + +This uses an in-scope supported middleware surface and changes which +authoritative outcome wins after a fatal failure. The correction belongs in +this PR's new expansion boundary. It requires no new product decision, +persistence change or architecture amendment. + +## Fresh verification + +Prepared `/private/tmp/xmd-pr886-r1-architecture-review` at the exact head with +`deno task setup`. The initial sandboxed preparation could not download packages; +it was stopped before rerunning setup with network access, which completed. + +```sh +# In the prepared exact-head worktree: +deno task test packages/cli/tests/repl-lifecycle.test.ts +# exit 0 — 1 test / 8 steps +git diff --check 160e354e a85c36cb +# exit 0 + +# From the repository containing this record: +deno test --allow-all --node-modules-dir=manual --cached-only --frozen --config /private/tmp/xmd-pr886-r1-architecture-review/deno.json .reviewer/issue-881/evidence/pr886-a85c36cb-fatal-precedence.test.ts +# exit 1 — control passes; ordinary-body/fatal-cleanup competition fails +``` + +The [changed lifecycle suite output](evidence/pr886-a85c36cb-lifecycle.log) +is saved separately. The prior 161 tests / 782 steps belong to `3815aef4`; +they were not rerun or attributed to this head. The isolated checkout remains +clean. No production code was changed, CI status inspected or GitHub review posted. + +## Implementor handoff + +Correct PR #886 from exact head +`a85c36cb2edc184055b9aa3e270ba1d70b20670f`, based on main +`160e354e47f6fbeb1c792e6799c1fe26b2f155fc`. + +The accepted `Component.expand` contract preserves fatal-failure precedence +across canonical work and middleware unwind. The attached exact-head regression +shows an ordinary body failure suppressing a persistence failure raised by +delegating middleware's `finally`. The current revision changes tests only; +the required production correction remains absent. + +Restore established selection across both failures: durability first, Files +fatal second, then canonical ordinary failure before later ordinary policy +failure. Preserve the existing earlier-failure preference within each fatal +kind. Middleware must still neither rescue canonical failure nor replace it +with a later ordinary error. The authoritative throw and detached terminal +report must describe the same selected outcome after full unwind. + +Add focused boundary regressions for the reproduced persistence competition, +its Files fatal counterpart, and preserved ordinary-failure ordering. Keep the +successful-body fatal control. Check the authoritative fatal outcome and the +corresponding detached terminal report, retaining one terminal observation after +cleanup. Preserve public APIs, persistence and existing resource owners. + +Run affected Core expansion/invocation regressions, commit once focused checks +pass, and return the exact feedback SHA, parent and every focused command and +result. Return the corrected boundary for architecture review. The dependent +History and performance slices retain their separate contracts and reviews. diff --git a/.reviewer/issue-881/pr2-published-architecture-review.md b/.reviewer/issue-881/pr2-published-architecture-review.md new file mode 100644 index 000000000..8d9246ed9 --- /dev/null +++ b/.reviewer/issue-881/pr2-published-architecture-review.md @@ -0,0 +1,158 @@ +# PR 2 architecture review — #886 + +**REQUEST CHANGES** on `3815aef4eb72000c2c59f8b06a8e01ed8c9070b5`. +One blocker remains: the new component expansion boundary discards a fatal +middleware failure when canonical component work already failed ordinarily. +The accepted contract requires fatal precedence across both outcomes. + +## Reviewed boundary + +Reviewed [PR #886](https://github.com/taras/executable.md/pull/886) against main +`160e354e47f6fbeb1c792e6799c1fe26b2f155fc` on 2026-10-09. The exact PR head and +base were checked again before recording this verdict. + +#885 has merged. #887 depends on #886 and owns the subsequent History slice; +this review does not cover it. The concurrent #805 session-rendering proof +changes test infrastructure rather than the private REPL production boundary. +The original corrected reference remains the #881 reference; newer features +remain outside this slice. + +The reviewed tree is byte-identical to accepted feedback revision +`acadbbdb4fa7d8c8c86fa85f6657d29c5d95bc3e`. Its main base is byte-identical to +the previous integrated base `c7d54769d56661bef38cee8549b148f3bf87a904`. +Both comparisons pass `git diff --exit-code`. This review independently checks +the published head against the seven frozen requirements in +[pr2-planner-handoff.md](pr2-planner-handoff.md). + +## R1: preserve fatal precedence when middleware unwinds + +The [accepted invocation contract](pr2-invocation-contract.md) requires the +existing policy-failure pattern: canonical failure cannot be rescued, while +durability and Files fatal precedence remains authoritative. The +[implementation handoff](pr2-implementation-handoff.md) repeats this requirement +under “Surround the complete canonical invocation.” This finding belongs to +frozen checklist item 1; it introduces no new architecture criterion. + +At the reviewed head, `packages/core/src/component-expansion.ts:369` captures +the middleware chain's failure. Lines 377–380 then select a previously raised +canonical failure unconditionally, without inspecting the chain failure for a +fatal cause. The terminal reporting Result is also built from that ordinary +canonical failure. + +The established `Execution.document` reconciliation in +`packages/core/src/execute.ts:3244` first examines both canonical and policy +failures for durability failure, then Files fatal failure, and only then applies +canonical ordinary-failure precedence. `rankBoundFailure` in +`packages/core/src/expand.ts:1590` follows the same ordering. The new boundary +loses the later fatal failure before either enclosing boundary can recognize it. + +The [reproducer](evidence/pr886-architecture-fatal-precedence.test.ts) uses the +supported public `Component.around({ expand })` middleware and real +`expandSegments` execution. It delegates the exact request once. A function +component raises an ordinary body error; the middleware's synchronous `finally` +raises a genuine `DurablePersistenceError` during unwind. No counterfeit +request, mutable context authority or hostile reporting object is involved. + +Expected: the persistence failure remains the authoritative fatal outcome. +Actual: expansion throws `Error: ordinary body failure`, and +`durabilityFailure(caught)` is `undefined`. The same middleware after a +successful body preserves the persistence failure, establishing the control. +The [first valid regression output](evidence/pr886-architecture-fatal-precedence.log) +contains one passing control step and one failing competition step. + +This changes which authoritative outcome wins after a fatal failure. It is an +execution-boundary defect, not diagnostic wording or ordinary Error identity. +Correcting reconciliation belongs within this PR because the PR introduces +the boundary that suppresses the fatal outcome. No persistence change or +product decision is needed. + +## Other structural checks + +No additional blockers were found in the remaining frozen boundaries: + +- Exact request identity is checked before the terminal claims work; private + settlement retains once-only execution authority. The previous foreign-request + correction remains present. +- Invocation cleanup retains its existing owner and ordering. Session-owned + phase readers do not join dispatch while awaiting its terminal phase. Entry + release clears live observations after owned work and consumers unwind. +- Generated execution retains the existing capability boundary. Private + occurrence context supplies presentation attribution without becoming + execution or durable authority. +- Static inspection uses the canonical scanner, evaluates no header or body, + and preserves the installed document envelope. Replacement uses retained + owner and exact source ranges. Published observations and explanatory + aggregate members retain the earlier immutability correction. +- No Journal schema or persistence mechanism changes. Historical views suppress + live overlays, use selected-prefix facts and retain the actual output owner. +- Immutable readings and semantic actions remain inside the measured admission, + mounted-tree, focus and frame-target path. Width probes create no mounted + nodes or targets; source and preview wrapping use engine measurements. + +Ordinary visual acceptance remains with the Planner. The existing 44-pair +gallery and control record are not relabelled as new captures from this review. + +## Focused evidence + +Prepared an isolated detached worktree at the exact reviewed head with +`deno task setup`, then independently ran: + +```sh +deno task test packages/core/tests/component-expansion.test.ts packages/core/tests/source-inspection.test.ts packages/core/tests/component-api.test.ts packages/core/tests/invocation-scope.test.ts packages/core/tests/invocation-failures.test.ts packages/core/tests/invocation-identity.test.ts packages/core/tests/expansion-metadata.test.ts packages/core/tests/scanner.test.ts packages/core/tests/document-targets.test.ts packages/core/tests/document-target-execution.test.ts packages/core/tests/evaluate-component.test.ts +# exit 0 — 53 tests / 414 steps +deno task test packages/cli/tests/repl-source-reading.test.ts packages/cli/tests/repl-execution.test.ts packages/cli/tests/repl-entries.test.ts packages/cli/tests/repl-layout-admission.test.ts packages/cli/tests/repl-presentation-style.test.ts packages/cli/tests/repl-forms.test.ts packages/cli/tests/repl-journey.test.ts packages/cli/tests/repl-agent-journey.test.ts +# exit 0 — 94 tests / 316 steps +deno task test packages/cli/tests/repl-lifecycle.test.ts packages/cli/tests/repl-agent-execution.test.ts +# exit 0 — 14 tests / 52 steps +git diff --check 160e354e 3815aef4 +# exit 0 +``` + +Saved outputs: [Core](evidence/pr886-architecture-core.log), +[CLI](evidence/pr886-architecture-cli.log) and +[lifecycle](evidence/pr886-architecture-lifecycle.log). Total: 161 passing tests +and 782 steps. These passing checks do not exercise the reproduced competition. + +The reproducer imports the reviewed source in the retained isolated worktree +`/private/tmp/xmd-pr886-architecture-review`. Run it from the repository: + +```sh +deno test --allow-all --node-modules-dir=manual --cached-only --frozen --config /private/tmp/xmd-pr886-architecture-review/deno.json .reviewer/issue-881/evidence/pr886-architecture-fatal-precedence.test.ts +# exit 1 — successful-body control passes; ordinary-body/fatal-cleanup case fails +``` + +The isolated checkout remains clean. No production changes, CI inspection or +GitHub review publication were performed. + +## Implementor handoff + +Review and correct PR #886 from exact head +`3815aef4eb72000c2c59f8b06a8e01ed8c9070b5`, based on main +`160e354e47f6fbeb1c792e6799c1fe26b2f155fc`. + +The accepted `Component.expand` contract requires the existing fatal-failure +precedence across canonical work and middleware, including middleware unwind. +The attached regression shows an ordinary body error suppressing a genuine +`DurablePersistenceError` raised by a delegating middleware's `finally`. +`observeExpansion` currently chooses `settlement.raised` before considering +fatal causes in `chainFailure`. + +Restore the established ordering across both failures: durability first, Files +fatal second, then canonical ordinary failure before a later ordinary policy +failure. Preserve the existing earlier-failure preference within each fatal +kind. A middleware must still neither rescue canonical failure nor replace it +with a later ordinary error. The authoritative throw and the detached terminal +report must describe the same selected outcome after full unwind. + +Add focused regressions at this boundary for the reproduced ordinary-body / +fatal-middleware competition, the Files fatal counterpart, and the preserved +ordinary-failure ordering. Keep the successful-body fatal control. Assert the +authoritative fatal outcome and corresponding detached terminal report; use +the existing publication checks for one terminal observation after cleanup. +Reuse established reconciliation semantics without widening public APIs, +changing persistence, or creating new resource owners. + +Run the affected Core expansion/invocation regressions first. Once focused +checks pass, commit promptly and return the exact feedback SHA, parent and +every focused command and result. Return the changed architecture boundary +for review. #887 remains dependent work; its History contract is unchanged. diff --git a/.reviewer/issue-881/pr2-source-inspection.md b/.reviewer/issue-881/pr2-source-inspection.md new file mode 100644 index 000000000..b004523d0 --- /dev/null +++ b/.reviewer/issue-881/pr2-source-inspection.md @@ -0,0 +1,310 @@ +# PR 2: canonical source inspection interview + +Status: all four items are accepted by the Product Owner. +The invocation boundary, five presentation decisions and main +verification journey are accepted. Static source inspection completes the +cross-package contract in the Planner handoff. This does not reopen the +middleware request or add persistence. + +## Purpose and current gap + +After admission, the REPL displays generated XMD in place of Evaluate's inner +producer content. It must preserve Evaluate's opening and closing tags. Core's +current Expansion position identifies the opening character; it does not supply +the end of the opening tag or beginning of the closing tag. + +The canonical scanner already decides those boundaries while reading component +attributes, nested content, fences and inline code. Its private parse result +contains the end position, and its private top-level ComponentSpan collection +supports heading discovery. Public ComponentElement exposes only an opening +position. Reconstructing the missing boundaries with a CLI parser would create +another account of XMD syntax. + +The REPL also needs this map on a cold read, when no component is executing. +Adding ranges to live middleware would leave that case unanswered. The existing +parseMarkdownDefinition operation compiles declarations and builds an executable +definition; static presentation needs only lexical source ranges. In particular, +inspection must not invoke a frontmatter language evaluator, compile schemas, +evaluate prop expressions or execute code blocks. + +## System-boundary interview + +Trigger: a new public Core function and multi-member returned description crosses +the Core/CLI boundary. Review **four items** before freezing the contract: + +1. `inspectSource(text, kind)`: the static reading operation and its input form. +2. `SourceElement.name`: the authored element's name. +3. `SourceElement.opening`: the complete opening or self-closing tag range. +4. `SourceElement.closing`: the closing-tag range for a paired element. + +Reuse the existing Core SourceRange shape, `readonly start` and `readonly end`, +instead of introducing another interval type. Existing document-target ranges +remain body-relative; inspection ranges are relative to the exact string handed +to this function. Every range is a half-open UTF-16 string slice, matching the +scanner's existing offset arithmetic. Source-range offsets are not terminal +cell measurements. + +The names and returned shape below are accepted. Local collector mechanics +remain delegated. No contextual runtime +API, new namespace or public parent/process key is proposed. + +## Item 1 of 4: inspectSource + +**Feature.** Let the REPL locate executable element tags in retained source, +including while inspecting an earlier checkpoint or opening a completed run. + +**Example.** For the packet's paired Evaluate, opening and closing ranges let the +display preserve both tags and replace only the string between them. A literal +`` inside a code fence must not become a replacement target. + +**Current.** Core's scanner records complete top-level component spans privately. +It knows nested elements and exact delimiter positions during parsing. The +public definition parser returns ComponentElement positions and executable +definitions rather than this detached range reading. + +**Accepted interface.** + +```ts +/** + * Read executable element boundaries from source without executing it. + * Document input excludes frontmatter from executable scanning; fragment input + * follows generated expansion's whole-string scanning behavior. + * Ranges index the exact input string, including any document header prefix. + */ +function inspectSource( + text: string, + kind: "document" | "fragment", +): Result; +``` + +`document` follows Core's authored Markdown source envelope. `fragment` follows +the generated expansion path, which scans the complete produced string. The +caller selects from the retained source region's known kind, not from filename +guessing or header-looking content. The parameter is required because these +parsing paths have different frontmatter semantics. + +The function is synchronous and pure: no filesystem, provider, context lookup, +import, frontmatter evaluator, schema compiler or executable-definition factory. +It reuses Core's scanner boundary decisions and returns a detached, recursively +frozen list. Entries include every recognized nested executable element in +opening-source order. Parent relationships follow interval containment; the +REPL supplies its own private view composition. This is syntax, not a claim +that an element resolved, ran or received permission. + +Ordinary passive text yields no element entry. An incomplete tag follows the +canonical scanner's passive-text behavior; a scanner refusal returns Err rather +than a guessed boundary. Core's scanning exceptions become Error failures. +An empty list is successful absence of recognized executable tags, not a failed +inspection. The REPL separately refuses replacement when a retained admission +cannot be matched to one canonical paired Evaluate at its recorded position. + +Keep original bytes, source positions and existing execution decisions unchanged. +Document-envelope extraction preserves the same body boundary as execution while +reading no frontmatter value; it must not call a user language evaluator even +if that language was used when the document originally ran. No persistent +metadata or Journal change is necessary. + +Export this pure engine helper and its types from Core's existing root entrypoint, +alongside its parsing helpers. Consumer-facing contextual Component operations +remain on /api under architecture rule 7. No new subpath or dependency is needed. + +**Decision for item 1: accepted.** The Product Owner accepts the pure Core +inspectSource function with explicit document/fragment input, Result reporting +and a detached readonly source-element list. The returned members remain under +review. Static inspection does not execute the source or evaluate expressions. + +## Item 2 of 4: name + +**Feature.** Identify the authored element at each range, so the REPL can match +a generated admission to Evaluate and label source without resolving a component. + +**Example.** The inspected outer tag in the packet carries `name: "Evaluate"`; +its producer carries `name: "Plan"`. Two Evaluate tags have the same name but +different opening positions. A dotted tag such as `` retains +`"File.Delete"` exactly. The name alone identifies neither a unique occurrence +nor a permitted definition. + +**Current.** Core's scanner reads the authored spelling into ComponentElement.name. +The existing Expansion description also reports the authored name for an actual +invocation. Source inspection reuses that spelling without requiring an invocation. + +**Proposed member.** + +```ts +interface SourceElement { + /** The authored tag name, exactly as Core's scanner reads it. */ + readonly name: string; +} +``` + +This member is required because every recognized executable element has a name. +Preserve its case and dotted spelling; do not substitute a resolved definition +name, package origin, registry identity or user-facing label. The value is a +detached immutable string with the inspected source description's lifetime. +Reading it performs no import or permission check. An unresolved authored name +can still have a source range, without being reported as having executed. + +The REPL uses the name together with the retained source owner and exact opening +position when matching Evaluate. It does not merge repeated names, assign a +process identity from them or infer a lifecycle phase. Retained source kind and +canonical position, not the name, establish which source string owns the range. + +**Assessment.** `name` and `string` match Core's existing parsed and live +description vocabulary. No enum of currently installed components can represent +all custom authored tags. No additional display-name field is needed. + +**Decision for item 2: accepted.** The Product Owner accepts required readonly +name as the exact authored tag spelling, independent of resolution and execution. + +## Item 3 of 4: opening + +**Feature.** Preserve an element's exact opening tag when the display replaces +its content or draws a source rail. + +**Example.** In `body`, opening is `{ start: 0, end: 10 }`: +`text.slice(opening.start, opening.end)` returns ``. For +``, the range covers that entire self-closing tag. +Attributes and their authored whitespace remain in the slice. + +**Current.** ComponentElement.position marks the opening character. The canonical +scanner knows the point immediately after `>` or `/>`, having read attributes +with its existing quote/expression handling. That point is not currently part +of the public source description. + +**Proposed member.** + +```ts +interface SourceElement { + /** Complete opening or self-closing tag, as a half-open slice of input text. */ + readonly opening: SourceRange; +} +``` + +The member is required for every recognized element. Its start includes `<`; +its end excludes the character after `>` and therefore includes the entire tag. +Both bounds are zero-based UTF-16 string offsets in the exact inspectSource input. +For a document, they include the original header prefix; for a fragment, they +index the complete produced string. This follows SourcePosition.offset arithmetic +and the existing SourceRange start/end vocabulary. Existing document-target +range coordinates remain unchanged. + +Core returns a frozen range with integer bounds satisfying +`0 <= start < end <= text.length`. The range has no file, admission id, live +occurrence key, line/column duplication or terminal-cell coordinate. The caller +already owns the retained source string and its provenance. Applying a range +to a different string would describe different source; display wrapping never +changes the string these bounds index. + +Read the boundary from the canonical parse decision, including a tag containing +`>` inside a quoted attribute or expression. Do not search for the first `>` +after a recorded position. A multiline opening tag remains one range and one +element, regardless of how many visual rows it occupies. + +**Assessment.** `opening` distinguishes the tag from the whole element and its +inner content. Required SourceRange preserves exact spelling without exposing +parsed props or executable definitions. The closing boundary is the next item. + +**Decision for item 3: accepted.** The Product Owner accepts required opening as +the exact half-open range of the opening or complete self-closing tag. Attributes +remain in the slice and visual wrapping changes none of its offsets. + +## Item 4 of 4: closing + +**Feature.** Preserve a paired element's exact closing tag and identify the end +of the content replaced in the source reading. + +**Example.** In `body`, closing is `{ start: 14, end: 25 }`. +The closing slice is `` and the inner slice, from opening.end to +closing.start, is `body`. In ``, that inner slice is empty +but closing is still present. A self-closing `` +has no closing range. + +**Current.** Core's parseChildren identifies the matching closing tag after +reading nested children and returns the position after it. The boundary is +currently private; an opening SourcePosition alone cannot identify it safely. + +**Proposed member.** + +```ts +interface SourceElement { + /** Complete closing tag for a paired element; absent for a self-closing tag. */ + readonly closing?: SourceRange; +} +``` + +The optional member is absent exactly when the recognized element is self-closing. +It is present for every recognized paired element, including one with empty +content. Absence never means that a close is still expected, execution is running, +inspection failed or the data is unknown. An incomplete paired tag follows the +canonical scanner's passive-text behavior, not a guessed paired SourceElement. + +Like opening, closing is a detached frozen range indexing the exact input string. +Its start includes the closing tag's `<` and its end is immediately after `>`. +For a paired element, Core guarantees +`opening.end <= closing.start < closing.end <= text.length`. The spelling and +whitespace belong to the actual tag recognized by Core. This is source syntax; +it says nothing about runtime cleanup or the invocation's terminal outcome. + +The REPL derives the inner content with +`text.slice(opening.end, closing.start)` and the whole paired element with +`text.slice(opening.start, closing.end)`. The whole self-closing element is its +opening slice. Interval containment supplies static nesting without public +children, parent keys or another stored content range. + +Read the matching close from the successful canonical parse, including nested +same-name elements and inert tag-like strings. A text search for the next +`` is not equivalent. Freeze both ranges before returning the description; +neither carries a live handle or gets updated by execution phases. + +**Assessment.** `closing?: SourceRange` expresses the two existing authored +forms without duplicating a selfClosing flag. Its absence has one precise +meaning, and opening/closing use parallel names and interval semantics. + +**Decision for item 4: accepted.** The Product Owner accepts optional closing, +present for every paired element and absent exactly for self-closing elements. +It is a source boundary with no lifecycle meaning. All four items are settled. + +## Accepted boundary shape + +```ts +interface SourceElement { + /** The authored tag name, exactly as Core's scanner reads it. */ + readonly name: string; + /** Complete opening or self-closing tag, as a half-open slice of input text. */ + readonly opening: SourceRange; + /** Complete closing tag for a paired element; absent for a self-closing tag. */ + readonly closing?: SourceRange; +} + +// Existing Core interval shape, exported for this consumer. +interface SourceRange { + readonly start: number; + readonly end: number; +} +``` + +The accepted opening range covers `` or the entire ``. +The accepted closing range covers `` and is absent exactly for a +self-closing element. For a paired element, its inner content is the slice from +opening.end to closing.start. No content range, whole-element range, parsed +props, definitions, children array or parent key duplicates these boundaries. + +## Derived evidence for the Planner + +Compare static boundaries with actual execution scanning for documents and +generated fragments. Include nested same-name tags, tag-like strings inside +attributes, code fences and inline code, CRLF, non-ASCII offsets and empty paired +content. Document headers containing tag-like text are excluded from document +scanning without running their parser; generated fragments retain their existing +whole-string behavior. Existing heading target discovery and execution parsing +remain unchanged. Cold inspection has no provider call, source load or Journal +mutation. Malformed/ambiguous admission positions still refuse replacement. + +The implementation collects ranges where the canonical parser recognizes them; +it does not reconstruct closing delimiters by text search after parsing. Keep +the scanner's existing top-level spans for heading masking equivalent. The exact +private metadata collector and focused tests belong to the conforming plan. + +The accepted boundary is consolidated with the invocation and presentation +contracts in [pr2-planner-handoff.md](pr2-planner-handoff.md). PR 2 is ready for +planning; the Planner freezes the implementation plan and its focused evidence. diff --git a/.reviewer/issue-881/pr2-source-presentation.md b/.reviewer/issue-881/pr2-source-presentation.md new file mode 100644 index 000000000..1fa5d70ff --- /dev/null +++ b/.reviewer/issue-881/pr2-source-presentation.md @@ -0,0 +1,331 @@ +# PR 2: source presentation interview + +Status: all five presentation items are accepted by the Product Owner. +The main product verification journey is accepted in +[pr2-product-verification.md](pr2-product-verification.md). +The middleware boundary is accepted separately in +[pr2-invocation-contract.md](pr2-invocation-contract.md). + +## Item 1: show admitted XMD inside its Evaluate enclosure + +The execution reading lets a person follow the generated program where its +producer ran. The older corrected reference keeps Evaluate's opening and closing +tags visible and replaces the inner Plan content with the admitted program. + +Today, the REPL's entry-wide transcript describes admission as an event and +appends generated source. Core already retains the admitted program and the +producing Evaluate position. That position identifies the enclosing Evaluate; +it does not identify a particular producer child as the sole source of the text. + +**Accepted behavior.** For a paired Evaluate, show its original content before admission. +Once the selected retained prefix contains a successful admission, replace its +inner producer content in the display with the exact admitted source. Keep the +Evaluate opening/closing tags and enclosing source rail. Generated executable +children belong beneath that enclosure. This is a display projection of retained +facts, with live badges supplied separately by session middleware. + +For the packet's [plan-entry.md](plan-entry.md), the reading initially shows +Evaluate containing Plan and its prompt. After admission it shows Evaluate +containing the program beginning `# Create a project README` from +[generated-readme.md](generated-readme.md). The program is XMD source; its rendered +result has a separate output role. + +Preserve the original submitted source and Journal bytes. An earlier inspected +prefix still shows the producer content and contains no future generated source +or live badges. Returning live shows the latest admitted reading. Inspection +does not run the producer or fragment. + +Admit replacement only when the retained owner and producing position identify +the enclosing source span unambiguously. Do not guess a Plan by name, attach a +fragment to a sibling, replace several separate producer children independently, +or fabricate syntax that was not submitted. A refusal is not a successful +replacement. Missing/ambiguous source ownership follows the existing refusal +contract. + +**Proposed product verification.** Run the original Plan journey to admission, +then inspect a prefix from before admission and return live. After admission, +the generated heading and first Elicit occupy the producer content's place +inside Evaluate. Before admission, Plan and its original prompt remain there. +Generated source and rendered output remain visually distinct. The source and +Journal remain byte-identical during inspection, with no provider activity. +Appending the program below an unchanged producer as an unrelated transcript +event does not satisfy this behavior. + +**Decision: accepted.** The Product Owner accepts preserving Evaluate's enclosure +and replacing its inner producer content with the admitted program. Original +source remains unchanged; an earlier checkpoint shows the producer again; +rendered output remains separate. This is a feature decision, not a reusable rule. + +## Item 2: show the program owned by a self-closing Evaluate + +The existing self-closing form takes a program from a value: + +```md + +``` + +It has no inner producer content to replace. Keeping its authored row visible +preserves both that input form and the expression supplying the program. The +older reference's paired example does not settle this display adaptation. + +**Accepted behavior.** After successful admission, preserve the self-closing row and +display its exact admitted program directly beneath it as a generated child +source region. Connect that child to Evaluate's source rail. Do not manufacture +an opening/closing pair or place the generated source in the rendered-output +role. For a program reading notes.md, the source reading is: + +```text + + │ +``` + +This example illustrates ownership and reading order; measured placement and +rail styling are reviewed separately. The generated bytes retain their own +identity and source offsets. Visual indentation and rails are decorations, +not changes to the submitted or admitted source. + +Before admission, or when inspecting an earlier prefix, show the authored row +without a future generated child. A refused admission does not acquire a +successful generated child. Use the same unambiguous retained-owner requirement +as item 1. Inspection reads retained facts without executing the program. + +**Proposed product verification.** Submit a self-closing Evaluate whose program +reads notes.md. After admission, its authored `text={program}` row remains and +the admitted File source appears directly beneath it. The note's contents occupy +the separate rendered-output role. Inspect before admission and return live: +the child appears only in prefixes containing that admission. Fabricated paired +syntax, unrelated appended source, and displaying the note as generated XMD +each fail this behavior. + +**Decision: accepted.** The Product Owner accepts keeping the self-closing +Evaluate row and attaching its admitted program directly beneath it as generated +source. Rendered output stays separate; earlier prefixes omit the future child. + +## Item 3: reach all source and rendered text at every supported width + +The long schema in [generated-readme.md](generated-readme.md) must remain +readable at 72×20, as must a long README preview. Existing drawer and list +windows already reach content through measured capacity and earlier/later +controls. The main transcript currently splits explicit newlines into rows; +it has no equivalent source-reading window. PR 1 bounds visible text runs and +preserves their colours, but deliberately leaves this reading policy unchanged. + +**Accepted behavior.** Soft-wrap authored/generated source and rendered output to the +available measured content width. Preserve every source character, token role, +explicit newline and blank line in the logical reading. A visual wrap inserts no +newline into source, bindings or Journal data. Ordinary word boundaries are +preferred; a token longer than the row still continues across rows so its tail +remains reachable. Continuations stay attached to the same source owner and +rail, and acquire no extra lifecycle badge or executable occurrence. + +Use the established vertical window pattern for the main source/output reading: +`[↑ earlier]` and `[↓ later]` remain outside the moving content. Every wrapped +row is reachable. Decoration and controls consume measured capacity before +admission; nothing spills into another pane or the fixed seven-row footer. +Source previews use the same text policy inside their existing drawer window. +This proposal adds no horizontal scrolling interaction. Editable fields and the +persistent single-row draft retain their existing behavior. + +Keep window positions private to the process and the selected reading, following +the existing scope/prefix ownership pattern. Scrolling changes no selection, +answer, permission, location or Journal. A resize remeasures wrapping and window +capacity, clamps the position, and preserves selection/focus through the existing +admission rules. Rows outside the window contribute no nodes or targets. + +The engine supplies text fit and geometry; do not infer cell width from string +length or create another screen-coordinate calculator. The installed text +operations expose wrapping, while the current REPL measurement adapter returns +box bounds rather than a public line-break map. The Planner derives the smallest +private measurement adaptation needed for row windows, preserving the existing +renderer ownership and measured-frame boundary. No dependency change is implied. + +Metadata labels keep their established shortening rules. Source and rendered +content use continuation rows rather than an ellipsis that hides their tail. +Output owner and section placement remain item 5; this item settles text access. + +**Proposed product verification.** Read the original generated schema and README +preview at 160×36, 120×30 and 72×20. Use earlier/later to reach the schema's closing +delimiters and the preview's last line. Include an unbroken value wider than the +pane and a line with non-ASCII text, so character counting cannot stand in for +measured fit. Resize while reading, then inspect an earlier prefix and return +live. All selected content remains reachable, decorations and controls stay in +their measured regions, and source/Journal bytes and execution remain unchanged. +Preserving colour only on a clipped prefix, overflowing a neighboring pane, +or making the last row unreachable each fails this behavior. + +**Decision: accepted with revised labels.** The Product Owner accepts soft +wrapping and vertical window controls, and replaces the confusing `^`/`v` +characters with `↑`/`↓`. Use `[↑ earlier]` and `[↓ later]` consistently for the +new reading and existing Sessions, Entries and drawer window controls. Retain +their semantic actions and normal activation behavior; the arrows are labels, +not new keyboard bindings. Measure the complete Unicode labels and verify their +rendering and hit targets. This presentation change belongs to PR 2; PR 1's +accepted commit and evidence remain historical records of its frozen slice. + +## Item 4: connect nested source with rails and readable lifecycle badges + +The older reference places lifecycle glyphs beside source and joins paired +elements with nested vertical rails. Its phase labels sit in a separate fixed +screen column. The terminal must preserve those relationships when that column +has no room, especially after source begins wrapping. + +Keep one source rail per displayed enclosing element, connecting +its opening and closing source positions. Nested source receives nested rails; +continuation rows carry the same enclosure. Generated source inherits its +Evaluate enclosure under items 1 and 2. Rails describe source structure even +when that source has no live invocation observation. + +**Accepted placement:** reserve one measured status +column at the right edge of the source pane. Put the current glyph and full +state word there on the first visual row of its element. Align statuses across +nesting levels. The left side carries source rails and token-coloured source. + +Measure the column for the longest supported status reading, including a cleanup +wait, and keep that reservation stable as phases change. Measure the separation +from source as part of the row. Long source wraps within the remaining content +width; its badge stays on the first visual row. Continuations keep their source +rails and leave the status column blank. No separate status-only row is needed +at the supported profiles. Paired closing EXIT/terminal markers, when actually +observed, use the same right-hand column. No phase glyph remains in the left +source gutter. A wrapped line does not acquire a second invocation or badge. + +For example, with source attributes abbreviated only in this illustration: + +```text +│ ● ACTIVE +│ │ ● ACTIVE +│ │ │ ● WAITING +``` + +The column ends at the pane's measured inner edge, not the terminal's edge or +another pane. A word remains complete at 72×20; source gains continuation rows +instead of losing characters. Do not shorten WAITING to an unexplained glyph, +elide source to retain the badge, or paint a label over another region. + +Use the older reference's lifecycle colours with their glyphs and state words: + +| Reading | Glyph | Colour | +| --- | --- | --- | +| ENTER | ▶ | `#5aa87c` | +| ACTIVE | ● | `#7fd3e8` | +| WAITING | ● | `#c99a3f` | +| EXIT | ◀ | `#c2766e` | +| SETTLED | ✓ | `#4f8468` | +| FAILED | × | `#d24b3f` | + +Cancellation keeps the accepted textual cancelled reading. A wait during cleanup +keeps EXIT visible alongside WAITING, rather than implying the body resumed. +Repeated or concurrent calls receive separate private occurrence readings within +their owned source group; a source id alone cannot combine their badges. +Unselected source has rails without a fabricated execution state. Historical +inspection has source rails but no live badges; return live restores the latest +session reading. No minimum frame duration or execution delay is introduced. + +**Proposed product verification.** In the original nested journey, identify +Evaluate, Plan and the actual pending Elicit from their own rails and badges. +Hold cleanup and observe EXIT until final acceptance. At all supported profiles, +the full state words align at the source pane's right edge. At 72×20, reach +wrapped source through the window without losing characters; the first visual +row carries the badge and continuation rows leave its column blank. Transition +from ACTIVE to WAITING to terminal state without changing the reserved column +or rewrapping source solely because the state word changed. +Inspect an earlier prefix while execution advances: its source rails remain, +its live badges disappear, and returning live restores the latest state. +Include two real calls sharing a logical source id so one cannot overwrite the +other. A single entry-level progress badge, colour without a state word, +duplicated continuation badges or historical live-state leakage fails. + +**Decision: accepted.** The Product Owner confirms a shared right-aligned status +column at the end of the line. All phase glyphs and words use it; nesting rails +stay on the left. Long source wraps in the remaining width, with the badge on +its first visual row and a stable reservation across state changes. + +## Item 5: read rendered output before the entry's source + +The original reference gives the settled entry's rendered document visual +priority. Its generated source is a separate execution reading. The current +flat transcript interleaves source/admission/effect summaries before the entry's +final result, so the useful result can be buried below machinery. + +The session already receives an entry-owned output stream. The selected entry's +retained root close supplies its final rendered output and outcome. Evaluated +blocks can also retain output with their actual source-region owner. These are +different facts: a retained block output does not prove that its parent emitted +the same text to the entry, and lifecycle `Result` carries no rendered +value. No general per-component rendered-output record exists in this contract. + +**Accepted behavior.** When reading an entry, put an `Output` section before its `Source` +section within the existing transcript pane. The Output section contains the +actual entry-rendered text. The Source section contains the accepted authored/ +generated projection and rails. Both belong to the selected entry and share its +measured vertical reading window. These sections create no additional pane or +route. Source remains reachable through `[↑ earlier]` / `[↓ later]`. + +The output starts at the entry's first reading position; do not automatically +move a window already being read when output arrives. For the original packet +journey, the Output section begins with the rendered `Create a project README` +heading and includes the actual preview and `README.md was created.` text. +The Source section shows the admitted Evaluate program separately. Do not +synthesize a write receipt, interpret a bound value as output, or print the +generated program itself in the Output section. + +While an entry runs, show the session's emitted text with the label +`Output · live`. Once the retained final result exists, its text replaces the +live reading exactly once and the heading becomes `Output`. The retained result +wins even if it differs from a partial live stream. A retained empty result +shows `No rendered output.` alongside the actual entry outcome. If an inspected +prefix has no entry-rendered output record, say +`No entry output recorded at this checkpoint.` rather than borrowing live or +later output. Keep existing failure/cancellation diagnostics and truthful entry +outcomes visible; text containing the word "failed" does not decide an outcome. + +Reading a nested source scope remains a source reading. Display a retained +block's output at its recorded owner as `Recorded block output` when available; +do not label the entry's entire final result as that component's output or +assemble local block outputs into a fabricated entry result. Agent response +text remains in its Agent reading, and a binding remains in its binding reading. +If the existing records cannot establish a narrower owner, display the output +only at its known entry owner. No middleware payload or persistence extension +is required for these section relationships. + +**Proposed product verification.** Run the original Plan journey and open the +settled entry. Its rendered heading, preview and final report appear in the +Output section before Source, without an intervening list of effect summaries. +At each supported profile, the first reading window begins with rendered text +and earlier/later reaches the final report and source. Read a nested generated +scope: source remains that scope's, and entry output is not attributed to its +Elicit or File. Include a bound value that renders nothing and a printed word +"failed" in a successful entry. Inspect before the root close and cold reopen +afterward: no future output, live overlay, duplicate result or provider call +appears. An entry-wide dump below unrelated events or synthesized output fails. + +**Decision: accepted.** The Product Owner accepts Output before Source for the +entry reading. Live output is explicitly labelled and replaced by the retained +final result; earlier checkpoints contain only their retained facts. Nested +source readings receive output only where its narrower owner is known. + +## Remaining items + +All presentation decisions, the main verification journey and all four static +inspection items are accepted. Use the canonical read-only boundaries in +[pr2-source-inspection.md](pr2-source-inspection.md), not a second CLI parser or +unrelated additions to Expansion. The ready +[PR 2 Planner handoff](pr2-planner-handoff.md) consolidates these contracts. +Private wrapping measurement stays within the existing renderer boundary; +the Planner specifies its concrete method and freezes implementation evidence. + +History geometry and full-story reference scene mapping remain PR 3 architecture +work. This record settles presentation behavior; it is not a complete PR 2 handoff. + +## Evidence + +- Older archive SHA-256: + `86be64318121546f3208342edaf17f0a3aed35f3fde2766b523423e6c708c77b`. + `xmd-repl-timetravel.jsx`, root document reading at lines 745–793, preserves + Evaluate around the generated program after its inline transition. +- `packages/core/src/components/Evaluate.ts` obtains the produced string, then + passes the current Evaluate expansion position with the generated admission. + The paired and self-closing forms are distinct existing language forms. +- `packages/cli/src/repl/model.ts` projects retained generated admissions into + source regions. These regions establish retained source ownership and do not + prove component lifetime or per-component rendered-output ownership. diff --git a/.reviewer/issue-881/pr3-history-contract.md b/.reviewer/issue-881/pr3-history-contract.md new file mode 100644 index 000000000..4a10297ac --- /dev/null +++ b/.reviewer/issue-881/pr3-history-contract.md @@ -0,0 +1,525 @@ +# PR 3: History rail interview + +Status: recorded-order spacing and major/minor hierarchy are accepted by the +Product Owner. Both navigation members, checkpoints and head, are accepted. +Head display wording, five-row rail placement and collision grouping are +accepted, including rail colour treatment and generic History drawer wording. +All interface, presentation and +[verification journey](pr3-product-verification.md) decisions are accepted. +The [PR 3 Planner handoff](pr3-planner-handoff.md) is ready for planning. +PR 2 is ready for planning under +[pr2-planner-handoff.md](pr2-planner-handoff.md). + +## Purpose + +Show how the selected checkpoint relates to the recorded head. The older +reference distinguishes entry boundaries from smaller marks and shows the +selected position separately from the head. The terminal keeps the existing +History drawer for choosing an exact checkpoint. + +The authority is the older corrected archive, SHA-256 +86be64318121546f3208342edaf17f0a3aed35f3fde2766b523423e6c708c77b. +Its xmd-repl-timetravel.jsx Band draws tall entry boundaries above the rail, +short scope marks below it, an amber selection and a separate head indicator. +Its elapsed-time labels and compressed wait use mock timing cues. The current +ReplCheckpoint has marker, kind and label, with no timestamp. + +## Item 1: spacing by recorded order + +**Current.** The terminal spreads checkpoint labels through the five History +rows. It has no rail or major/minor tick geometry. The reference spaces marks +by elapsed time, which cannot be reconstructed from the current Journal. + +**Intent.** Give the reader the reference's visual relationship between entries, +checkpoints, selection and head using facts the application actually retains. + +**Assessment.** Adding timing records conflicts with the accepted persistence +boundary. Recorded-order spacing is a material adaptation of the reference and +needs Product Owner approval. It represents sequence, not duration. + +**Accepted.** Label the band `History · recorded order`. Space positions by +their retained checkpoint order. Use tall entry ticks and short minor marks; +draw selection and head as separately identifiable indicators. Do not show +elapsed seconds or compressed-wait duration. Keep all five History rows and +the seven-row footer. The rail is read-only; the existing drawer chooses exact +positions. No new scrubbing, arrow-key navigation or fork control is introduced. + +This decision settles the spacing basis and visual hierarchy. The accepted +labels and collision placement follow below. It does not grant permission for +future execution facts to appear in inspected content. + +**Decision.** The Product Owner accepts recorded-order spacing, tall entry +ticks, short minor marks and distinct selected/head indicators. Subsequent +decisions settle head wording and collision placement. + +## Navigation boundary interview: two members + +Trigger: the History band needs later navigation facts while inspected content +remains a selected-prefix reading. This materially changes reachability during +inspection. Pause the main presentation interview and review the proposed +private summary's two members: + +1. `checkpoints`: full retained marker order and checkpoint kind. +2. `head`: truthful overall head state, with no work details or capability. + +The existing route owns the selected marker; do not duplicate it in this +summary. This is private CLI view data, not a Core API or durable record. +Both member types and their ownership contracts are accepted. Exact display +labels follow the completed boundary interview. + +### Member 1 of 2: checkpoints + +**Feature.** Keep the entire recorded rail and exact-selection drawer available +when a reader selects an earlier checkpoint. + +**Example.** Selecting an early Plan checkpoint leaves later recorded marks +visible in History. The reader can choose a later mark directly. Source and +Output still describe only the selected Plan checkpoint. + +**Current.** ReplCheckpoint carries marker, kind and label. Both historyBand +and the History drawer receive view.model.checkpoints, which belongs to the +selected prefix. Some labels contain binding names or recorded Agent outcomes. +Passing these whole checkpoints from the head would expose more than navigation +identity and category. + +**Accepted member and documentation.** + +```ts +/** All retained checkpoint identities and kinds, in append order. */ +readonly checkpoints: readonly Pick[]; +``` + +Reuse the existing marker identity and kind union. Freeze a detached list and +each element. Carry no existing label, binding name/value, source, output, +question, permission, Agent turn or lifecycle observation. Entry numbering and +generic checkpoint-category labels are derived from this list; their exact +wording is a later presentation decision. The drawer retains one semantic +selection action for every exact marker, including grouped rail marks. + +An empty list means no retained selectable checkpoint. It does not mean the +projection failed or that a process is paused. A corrupt full Journal remains a +projection refusal under the existing contract; History cannot fall back to a +stale summary that appears complete. + +The root program drive owns the reading. Derive the full navigation list and +selected-prefix model from one validated retained-event snapshot. Rebuild on +the existing session wake path, including while inspecting an earlier marker. +Keep inspected content fixed at its selected marker as the full list grows. +Do not introduce another durable store, polling loop, host reader or stream API. + +The parent-child path is root program composition to the immutable application +view, then to the footer History band and the History drawer through their +existing parent composition. Neither child projects the Journal or reads the +session. Other panes and the contextual action row receive the prefix reading +and the already restricted live view. Later review of the head member determines +the additional state the band alone may show. + +This is an explicit History navigation exception to the current specification's +whole-view prefix wording. The content restrictions remain intact. Record that +exception in the implemented REPL specification when this behavior exists. +Root ownership and immutable parent-child flow follow architecture rules 9 and +11; those conforming mechanics need no separate approval. + +**Decision.** The Product Owner accepts the full marker identities and kinds in +History during inspection. Other content remains selected-prefix-only. The +accepted shape excludes the existing labels and their future binding names or +Agent outcomes. + +### Member 2 of 2: head + +**Feature.** Distinguish the current overall execution state from the earlier +checkpoint being read. + +**Example.** While Source shows an earlier Plan checkpoint, the head indicator +can change from live to settling to settled as the actual entry finishes. Its +Output and lifecycle statuses do not appear in the inspected content. + +**Current.** There is no History head-state member. The root has a session's +process facts, its expansion controller state and a retained model. Existing +readiness distinguishes a recorded result from an entry still releasing +resources. The expansion controller has playing, pausing and paused states; +paused holds the expansion walk, while already-started work can still finish +and advance the Journal. + +**Accepted member and documentation.** + +```ts +/** Overall head state for the History band, independent of inspected content. */ +readonly head: + | "empty" + | "live" + | "pausing" + | "paused" + | "settling" + | "settled" + | "unfinished"; +``` + +This required value is a state, not a control, marker identity or success result. +Use these meanings and precedence: + +| State | Required fact | +| --- | --- | +| settling | The latest entry has a retained root outcome, but its owned task still releases resources. | +| paused | An entry task is active without a retained root outcome, and its real expansion controller reports paused. | +| pausing | An entry task is active without a retained root outcome, and its real controller reports pausing. | +| live | An entry task is active and none of the preceding states applies. | +| empty | No entry has been retained and no entry task is active. | +| settled | No entry task is active and the latest entry has a retained root outcome. | +| unfinished | The latest retained entry has no root outcome and no entry task is active. | + +Settled includes successful, failed and cancelled retained outcomes. It does not +claim success. The indicator carries no outcome payload or diagnostics. Display +wording and colour must preserve this neutral meaning; the detailed outcome is +read at its own checkpoint. Unfinished does not mean paused. A cold reader uses +retained empty/settled/unfinished facts unless this process actually owns work; +it never infers live state from an absent terminal record. + +The root builds the head value alongside the accepted navigation list, from the +full retained snapshot and authoritative session-owned task/controller facts. +It does not infer it from live component badges, selected-prefix outcomes, +pending drawers or whether a frame has changed. Owned work remains active until +its teardown completes. A body's return or recorded root close is insufficient +evidence that resources are released. The concrete plan must show which owner +proves that boundary and how its changes wake the existing root rebuild; do not +assume the current session.live flag proves every outer attachment has unwound. +No new resource owner or observer stream is required by this contract. + +Pass this state down only to the History band. The drawer needs the accepted +checkpoint list, not live state. Inspected Source, Output, Sessions, Bindings, +questions, permissions and the frozen contextual action row keep their existing +prefix restrictions. The summary never provides Pause, Continue or Submit +authority. Returning live resolves the actual current view and capabilities. + +**Decision.** The Product Owner accepts the seven head states and their meanings, +including History-band-only visibility during inspection. Settling lasts +through owned teardown; settled does not claim success. Head-state display +wording is a separate presentation item. + +### Complete accepted navigation interface + +```ts +interface ReplHistoryNavigation { + /** All retained checkpoint identities and kinds, in append order. */ + readonly checkpoints: readonly Pick[]; + /** Overall head state for the History band, independent of inspected content. */ + readonly head: + | "empty" + | "live" + | "pausing" + | "paused" + | "settling" + | "settled" + | "unfinished"; +} +``` + +The summary name is a private implementation name. Both members are required; +an empty list and the empty state have explicit meanings, so absence need not +carry a second meaning. The route already owns selection. Neither member +duplicates source, output, outcome details, controls or lifecycle observations. +The accepted exception is specific to History navigation and head presentation, +not a reusable permission for future content to enter inspected panes. + +## Item 2: head display wording + +**Current.** The reference uses LIVE, PAUSED HEAD and COMPLETED. The terminal's +existing action row says running, settling or unfinished. Its frozen action row +says History. The accepted head type adds the distinctions needed to keep the +reference's indicator truthful without importing detailed live work. + +**Intent.** Let a reader distinguish what the head is doing from the selected +checkpoint, including during cleanup and cold inspection. + +**Assessment.** PAUSED HEAD can imply all work has stopped even though pausing +holds only expansion. COMPLETED with a success checkmark would misrepresent a +settled failure or cancellation. Name expansion explicitly and use neutral +settled wording. Keep these labels in the History band, under its accepted +navigation exception; the frozen action row remains History. + +**Accepted wording.** + +| Head state | Exact label | +| --- | --- | +| empty | HEAD · EMPTY | +| live | HEAD · LIVE | +| pausing | HEAD · PAUSING EXPANSION | +| paused | HEAD · EXPANSION PAUSED | +| settling | HEAD · SETTLING | +| settled | HEAD · SETTLED | +| unfinished | HEAD · UNFINISHED | + +Use the same wording at all three profiles. Reserve engine-measured room for +the largest head label before placing the rail. A head state change must not +move or obscure the selected indicator or consume another footer row. Exact +glyphs and row placement follow below; no success glyph or colour is implied +by SETTLED. Colour treatment is a separate presentation item. + +**Decision.** The Product Owner accepts all seven labels, with the same wording +at each supported profile. Reserve the largest engine-measured head-label width; +state changes do not obscure selection or add a footer row. + +## Item 3: five-row rail placement + +**Current.** The terminal uses the five History rows for checkpoint label lists. +The older reference has entry ticks above the rail, scope marks below it, a +selection diamond above and a separate head bar. Five terminal rows cannot +reproduce its pixel heights, but can preserve the visual hierarchy and keep +selection and head readable at the same horizontal position. + +**Intent.** Show entry boundaries, minor checkpoints, selection and head within +the existing footer, with no competing control or extra row. + +**Accepted placement.** + +| History row | Reading | +| --- | --- | +| 1 | History · recorded order at left; accepted head-state label at right. | +| 2 | Entry-number captions over the rail; selection caption at right. | +| 3 | Tall entry ticks and the selected diamond above the rail. | +| 4 | Horizontal rail, with entry and minor checkpoint junctions. | +| 5 | Short minor stems below the rail and the head marker. | + +Reserve one engine-measured right-hand caption region before placing marks. +Its stable width covers the largest accepted head label and the current +selection caption. The rail and its markers occupy the remaining measured +region; captions never overwrite marks. No extra separator row is introduced. + +Use `┃` for entry uprisers, `─` for the rail and `┬`/`│` for short minor marks. +The selected position is an amber `◆` above the rail. The head is a `▼` below +the rail, aligned with the rail's end. These symbols are readings, not arrow-key +bindings or controls. Exact junction characters and engine-operation assembly +are conforming local mechanics; preserve the stated hierarchy. + +Schematic only, showing selection at checkpoint 3 and a paused head. Spacing +here is illustrative, not a measured frame or a final narrow-profile artifact: + +```text +History · recorded order HEAD · EXPANSION PAUSED +Entry 1 Entry 2 ◆ SELECTED · 3 +┃ ◆ ┃ +╂──┬────╪──┬─────────╂──┬───────────────────┤ + │ │ │ ▼ +``` + +The selection caption is `◆ SELECTED · N`, where N is the selected marker's +one-based ordinal in the accepted full checkpoint list. This is checkpoint +order, not an entry number or elapsed time. At the live route it reads +`SELECTED · HEAD`, with no earlier-selection diamond. Entry captions are +`Entry N`, derived from retained entry checkpoints in admission order. + +When a selected checkpoint and head share a column, keep `◆` in row 3 and `▼` +in row 5. Never replace them with a combined symbol or hide one. If an entry +tick or minor stem shares that column, the distinctive selection/head symbols +take their respective rows; the boundary remains represented on the rail and +in the exact-selection drawer. Detailed collision grouping is the next item. + +With no retained checkpoints, show `No recorded checkpoints` in row 2 and draw +no fabricated ticks or selectable position. The accepted head label can still +describe actual work before its first retained checkpoint. There is no selected +ordinal in this case. Empty visual rows remain inside the same five-row band. + +All three profiles keep this row organization. The contextual action row and +draft retain their existing positions, making seven footer rows in total. +No horizontal input, scrolling rail, scrubbing or new target is introduced. +Colours and detailed grouping follow in subsequent presentation decisions. + +**Decision.** The Product Owner accepts the five-row placement, selected diamond +above the rail and head marker below it. Their separate rows preserve both when +they share a column. Selection captions use the full-list checkpoint ordinal; +live selection reads SELECTED · HEAD. + +## Item 4: collisions and grouping + +**Current.** Existing History grouping combines labels across a five-row text +budget. The accepted rail instead places recorded-order marks in one measured +horizontal region. Many checkpoints can share a terminal column, and entry +captions can collide even before the marks do. + +**Intent.** Preserve the recorded sequence and exact selection at narrow width +without forcing every checkpoint to have its own visible column. + +**Accepted.** Place checkpoint ordinals evenly across the available +engine-measured rail columns, with the first at the start and last at the head. +With one checkpoint, place it at the head. Checkpoints assigned the same column +form one visual group, containing consecutive ordinals in retained order. +Grouping changes presentation only: retain every exact marker and its kind. +Do not group by component name, outcome, elapsed duration or source location. + +Use a short minor notch for a single minor checkpoint and a heavier notch for +multiple checkpoints in that column: `┬`/`│` versus `┳`/`┃`. A group containing +an entry keeps the tall entry boundary and uses a heavier rail junction for the +group. Exact junction assembly stays local, but a populated group must be +visibly distinguishable from one ordinary minor mark. An entry/minor collision +preserves the tall entry boundary and a below-rail minor stem where the head +marker does not occupy that row. + +Entry captions retain Entry N. Merge overlapping adjacent entry captions into +one range, such as `Entry 1–3`, until the measured captions fit their rail +region. A range names actual consecutive entry ordinals, not checkpoint +ordinals. Do not clip a caption into a different number or cover the fixed +right-hand head/selection captions. The Planner supplies the concrete +deterministic placement and grouping method against engine measurements. + +Selection keeps its exact ordinal in `◆ SELECTED · N` even when its rail column +contains several checkpoints. Keep its diamond above the rail, with precedence +over the entry upriser in that cell. Keep the head marker below the rail, with +precedence over a minor stem. A shared column never combines head and selection +into one symbol. The group's retained identities and entry caption preserve +the boundary when a distinctive indicator occupies its upriser or stem. + +For example, checkpoints 41, 42 and 43 may share a grouped notch. Selecting 42 +shows its diamond at that column and the caption ◆ SELECTED · 42. The History +drawer still has three separate rows and actions for those three exact markers. +The rail group itself acquires no input target or selection action. + +The History drawer uses the complete accepted marker list, in retained order, +with one independently selectable row per marker. Ordinals distinguish repeated +checkpoint kinds. Its existing measured window and PR 2's ↑ earlier / ↓ later +controls make all rows reachable. Generic category wording is a subsequent +presentation item; future binding names, values and Agent outcomes stay excluded. + +Resize rebuilds placement from the same identities and the new measured region. +It preserves the selected marker, drawer focus under established window rules, +draft and route. New recorded checkpoints may change proportional placement; +a head-state-only change does not. Returning to a former size and the same +snapshot reproduces the same groups. No horizontal scrolling or new navigation +mode is introduced. + +**Decision.** The Product Owner accepts visual grouping, heavier crowded +notches, tall entry boundaries, merged entry captions and exact selection +ordinals. Every marker remains separately selectable in the History drawer. +Resize recalculates groups while preserving selected marker identity. + +## Item 5: rail colour treatment + +**Current.** The older reference uses a near-black History surface, bright entry +ticks, cyan minor marks, amber selection and muted later marks. Its live head +is cyan; its settled head is green with a success checkmark. The accepted +terminal head state settled includes failure and cancellation, so its colour +must remain neutral. + +**Intent.** Preserve the reference's colour hierarchy and show the selected +prefix against later recorded navigation marks, independently of focus. + +**Accepted literal colours.** + +| Reading | RGB hex | +| --- | --- | +| History surface | #08090b | +| Horizontal rail | #141a1f | +| History title | #8b959c | +| Entry caption at or before selection, or at live head | #b8c4cc | +| Entry tick at or before selection, or at live head | #e6ecf1 | +| Minor mark at or before selection, or at live head | #7fd3e8 | +| Later entry tick and caption during inspection | #5d666e | +| Later minor mark during inspection | #4e565d | +| Selected diamond, selected rail junction and ordinal caption | #c9a86a | +| Live head marker and HEAD · LIVE label | #7fd3e8 | +| Empty, pausing, paused, settling, settled or unfinished head marker/label | #7b858d | +| SELECTED · HEAD and No recorded checkpoints | #7b858d | + +These literals come from the older Band's surface, rail, labels, ticks, +selection and dimmed marks. The neutral settled head is the consequential +adaptation: it carries no green success cue and no checkmark. Pausing and +paused remain muted like the reference's paused head; their accepted wording +states the real expansion behavior. Head state does not recolour the whole +recorded rail or animate progress. + +During inspection, later means a checkpoint ordinal after the selected marker, +not an unrecorded future event. Those marks remain navigation only. In a visual +group, colour the entry tick/caption as earlier if any represented entry is at +or before selection; otherwise use the later-entry colour. Apply the equivalent +rule separately to minor marks. A group spanning the boundary does not imply +every represented checkpoint belongs to the prefix. Exact ordinal selection +and the drawer retain that distinction. + +Selection takes precedence at its diamond, rail junction and caption. Head +takes its own state colour below the rail; sharing a column never turns its +marker amber or hides it. Entry captions merged across the selected boundary +use the earlier-caption colour, with the exact selected ordinal still stated +at right. Keep existing drawer focus and selected-row cues from PR 1, with no +global focus colour replacing History semantics. + +Keep the literal colour expectations independent of production constants in +the Planner's derived evidence. The palette does not create new checkpoints, +timestamps, outcomes, animation state or input targets. + +**Decision.** The Product Owner accepts the colour treatment after viewing the +[colour study](visuals/history-colours.html), which shows the exact literals +on the History surface, with illustrative marks and head-state samples. It is +an interview aid, not engine-measured terminal evidence. The accepted colours +include neutral non-live head states, distinct amber selection and dimmed later +recorded marks during inspection. + +## Item 6: exact-selection drawer wording + +**Current.** History rows use the retained checkpoint label. Those labels can +include component names, binding names or Agent outcomes. The accepted full +navigation list carries only marker and kind, including after the selected +prefix. It cannot supply those original labels. + +**Intent.** Let a reader choose an exact checkpoint, including a later one or a +member of a crowded rail group, using its number and recorded category. + +**Accepted wording.** Prefix every row with its one-based ordinal in the full +checkpoint list, followed by the category below. The ordinal is the same N as +the rail's SELECTED caption. Entry E counts admitted entries separately. + +| Existing checkpoint kind | Exact row wording | +| --- | --- | +| entry | N · Entry E admitted | +| scope | N · Component admitted | +| binding | N · Bindings recorded | +| generated | N · Generated XMD admitted | +| elicit | N · Answer recorded | +| agent | N · Agent turn recorded | +| terminal | N · Entry outcome recorded | + +For example, `42 · Bindings recorded` and `43 · Bindings recorded` are separate +rows with separate marker actions, even if they share a grouped rail notch. +Selecting one projects exactly that marker; the root adopts the prefix or +reports the existing navigation refusal. A row names no binding, component, +question, prompt, answer value, rendered output or outcome detail. + +Entry outcome recorded names the retained root close. It does not claim the +session-owned task has completed cleanup; the accepted History head remains +SETTLING until that boundary completes. Component admitted likewise describes +the retained admission, not a full invocation finishing. Answer recorded follows +the projector's successful answered-question checkpoint, not a pending live wait. + +Use these same category labels at live and historical routes. Do not substitute +the original richer labels at the live route and then change a focused row's +reading during inspection. Preserve marker-based keys, existing selection/focus +cues and the drawer title History. No additional hint or legend row consumes +its measured content window. Earlier/later controls retain the accepted arrow +labels and semantic actions. Exact rows outside the admitted window remain +absent from mounted nodes, frame targets and Tab stops. + +**Decision.** The Product Owner accepts all seven numbered, category-only +labels. Checkpoint numbering matches the rail; entry numbering is separate. +Each row retains its own exact marker action, including grouped checkpoints. +Entry outcome recorded describes the retained root close without claiming +that owned cleanup has finished. + +## Verification and handoff + +The navigation boundary is complete. Resume the main presentation interview. +The REPL specification excludes live status from the frozen action row; the +accepted head member has separate History-band reachability. +Source, bindings, rendered output, questions, permissions, Agent content and +lifecycle overlays stay selected-prefix readings under the accepted PR 2 +contract. + +Head labels, rail placement, grouping, colour and drawer wording are settled. +Every grouped marker +remains individually selectable in the History drawer. Engine measurements +own terminal placement; a character-count layout must not bypass admission. + +The accepted [PR 3 verification journey](pr3-product-verification.md) carries +these contracts into observable behavior. The ready +[Planner handoff](pr3-planner-handoff.md) consolidates the contracts and freezes +the structural review checklist. The Planner owns the finite +gallery, focused tests and controls, including the complete-story comparison. +No production changes, persistence changes, implementation verdict or GitHub +mutation is issued by this record. diff --git a/.reviewer/issue-881/pr3-implementation-handback-r2.md b/.reviewer/issue-881/pr3-implementation-handback-r2.md new file mode 100644 index 000000000..dbf00c497 --- /dev/null +++ b/.reviewer/issue-881/pr3-implementation-handback-r2.md @@ -0,0 +1,330 @@ +# PR 3 revision handback: R1–R4 + +Revised from `f509197bd1998b376b09986b79fce2740568e76f` against the four +findings in [the Planner review](pr3-planner-review.md), and against +[the R2 evidence correction](pr3-r2-evidence-correction.md). Branch +`agent/issue-881-pr3`, base `acadbbdb4fa7d8c8c86fa85f6657d29c5d95bc3e`. + +**Revision: `05ba70d567cb80be4bfdea67e7ae0267376e2376`**, amending +`3fa241dccd1ca3128d7026dbdd529efc7b401ef0` with the R4 and R5 corrections from +[the second review](pr3-planner-review-r2.md). One signed commit, worktree +clean, nothing pushed and no PR open. + +Three of the four are closed as asked. The fourth, R2, is closed in substance +and differs from the frozen wording in one ordering step, for a reason the +product forced and which is recorded with its own probe evidence. + +## R1 — one root snapshot, and full refusal after admission + +**The root change is in.** `ReplSession` now hands both halves over together: + +```ts +reading(at: string | undefined): Result // { model, navigation } +``` + +built from one slice of the acknowledged array, memoized on that array's +length and the position asked for, with the head derived on read because +pausing, resuming and the last of an entry's resources being released all move +it while the file stands still. + +`program.ts` keeps one `reading` value where it kept a `model`. Every branch +assigns both halves or neither; `build()` takes the prepared reading instead of +asking `session.navigation` again; and the per-frame composer recomposes *that* +reading at a new size. The shortcut that returned without reading when the +route and model selections matched is gone, and with it the window the review +described: the terminal size read between resolution and composition suspends, +and a record retained during it used to move navigation under content that had +already been projected. + +A reading that cannot be built at all now draws the **refused view** — the same +screen a cold open of that file shows — rather than a route notice over a stale +prefix. That is kept distinct from a route that does not resolve at its +position, which still keeps its reading and says the reason beside it. + +The head is now derived in exactly one place (`headNow`). It had to be: the +first cut of this change created a second derivation, and KC5's mutation then +hit only one of them and reported UNBROKEN. That is in the control record. + +New regressions, in `repl-history.test.ts`: + +- *refuses the whole reading once an admitted session can no longer read its + file* — an **admitted** session, not a cold one: a duplicate of the entry's + own last record is appended to the live stream, both `reading(early)` and + `reading(undefined)` refuse, and `session.model` is still the model it was, + not quietly refreshed. This is the shape of the Planner's own probe. +- *answers both halves of one position from one acknowledged array* — the same + position read either side of an append: content does not move, navigation + does, and the pair agrees with itself. + +The root-level half of this is the corrected offscreen journey under R2: a real +append arriving while a prefix is inspected, with the drawn frame's content and +order read from the same screen. + +## R2 — advancement with the head held + +**The captures now show a held head.** All three `offscreen-advance` frames say +`HEAD · EXPANSION PAUSED`; the audit requires that string and forbids +`HEAD · LIVE` for this state, so the green result can no longer be had with the +superseded frames. + +**The frozen ordering is not performable for these shapes, and this is why.** +R2 asked to establish the controller hold and *then* release work that already +started. The controller reports paused only when every active expansion walk +is satisfied, and a walk suspended inside an already-started provider +operation has not necessarily reached such a gate — so Pause requested there +can correctly stay PAUSING until that operation returns. Four shapes of +outstanding work were tried in the real command — +a `` held at its provider gate inside ``; a spawned component body +polling for a latch; an Agent permission request held at its gate; and a +spawned body suspended on a single `fs.watch` event, which is the frozen +`HistoryGate` fixture shape — and in every one the head stayed at +`PAUSING EXPANSION` for as long as it was watched, with `[continue]` never +offered. The probes and their timings are in +[pause-boundary-probe.md](pr3-evidence/pause-boundary-probe.md); `HistoryGate.ts` +is kept beside the other fixtures so the fourth probe can be re-run. + +This is about expansion walks, not about all Effection work or resource +lifetime: the probes below say what these four shapes do, and nothing broader. +The order the journey performs, which the Planner has since recorded as the +correct one, is: start the work, request the pause against it (`PAUSING`, +which is what says the request is real and the work outstanding), inspect an +early prefix, then release the started work — its records append with nothing +typed and nothing activated in the frozen view, and the hold establishes as it +finishes. Every assertion the row names is then made: a real retained append +(journal records), growth of the whole navigation list (the last ordinal the +drawer lists, walked to the end before and after, and **compared**), unchanged +exact selected content and selection caption, and `HEAD · EXPANSION PAUSED`. +Opening and closing History while still inspecting leaves the head held, the +prefix and the selection standing, and offers no Continue there — the action +row at a frozen position is read only. Only after returning live is the real +Continue required and activated through the controller, after which the entry +reaches an outcome and the head reads `SETTLED`. + +That the pause is requested against work that is genuinely in hand is checked +rather than assumed — the stage reads the provider's own log and refuses to +proceed until a Plan turn has been taken and not answered. Two earlier runs of +this stage recorded a head that had already settled, which is exactly what that +check now prevents. + +## R5 — the repository's rules on the newly committed files + +Three changes, all in the direction the review named. + +**No production casts.** `session.ts`'s memo held optional `whole`, `prefix` +and `failed` fields and then asserted two of them with `as ReplModel`. It now +holds one `Result` — a pair that either exists or a failure — +built by a single `project()` helper. Nothing asserts a payload the shape +could lack, and no public interface changed. The repository's own +`prefer-effection-result` rule then caught two places where I rebuilt an +already-narrowed failure with `Err()`; both now return the failure itself. + +**The probe is out of shipped source.** `HistoryGate.ts` took its `fs.watch` +before registering the release, which Code Rule 16 forbids, and it used +`node:fs/promises` where the repository requires Effection operations. The +corrected journey does not use it — the pause is requested against the Plan +provider — so it is removed from `packages/` rather than rewritten, which is +the alternative the review offered. Its exact bytes are retained at +`pr3-evidence/probes/HistoryGate.ts` +(sha256 `ea46a4d6add24b286d6158a24405413ebbae2f9963cc902d4f4d759b016e18d2`) +and the probe record points at them, so the fourth probe can still be +repeated. No executable repository source now takes a watcher before +registering its cleanup. + +**The controlled host follows the same rules.** Both latch paths are narrowed +once, at the edge, by a `latches()` function that exits if either is absent — +so everything below holds two strings rather than asserting them. Its +filesystem work is `writeTextFile` and `exists` from `@effectionx/fs` instead +of direct `node:fs/promises`. The host's architecture is unchanged: one real +installation holding its own teardown, no fabricated head state, and the +accepted gallery's `settling-head` still comes from it. + +## R3 — KC3 against a real held invocation + +`repl-presentation-style.test.ts` gains **P1-T4**: a session opened with +`submitReplEntry`, an `` that actually suspends, and the frame composed +from that session's own overlay — `lifecycle: session.lifecycle`, not an +`observing(...)` fixture. Nothing in the test names a phase. The assertion is a +committed cell: the row carrying `● WAITING` is the one holding `.log` and a +first-failure block that runs to the end of the failure including its stack +locations, rather than an excerpt cut at 1,400 characters. + +## R4 — what grouped actions actually select + +**The first submission's oracle was false, and the review is right about why.** +`diamond_column()` scanned all five band rows and returned the first `◆`. +Row 1 carries the right-hand `◆ SELECTED · N` caption and comes before +row 2's actual rail mark, so the helper reported the caption's column — 145 — +for every selection, and the equality it checked agreed with itself. Positions +18 and 19 were chosen because they were the first consecutive +`Component admitted` rows, with nothing establishing that their marks shared a +column. They do not: the handback's 18/19 "one mark" claim was wrong and is +withdrawn. + +**What the repaired journey reads.** `rail_diamond_column()` reads band row 2 — +the marks above the rule — and nothing else. The pair is no longer the first +consecutive one: candidates are tried in recorded order, each member is +actually selected, its rail column read, and the walk stops at the first pair +whose two columns are equal. Which pair that is, is the layout's answer. + +Measured at **160×36**, zero-based rail columns, from the rebuilt packet's +`grouped-candidates` and `grouped-selection` records: + +| Candidate | Rail columns | Verdict | +| --- | --- | --- | +| 18 · Component admitted / 19 · Component admitted | 10, 11 | not one mark — rejected | +| 19 · Component admitted / 20 · Component admitted | 11, 12 | not one mark — rejected | +| **20 · Component admitted / 21 · Component admitted** | **12, 12** | one mark — chosen | + +The 18/19 columns reproduce the review's independent reading exactly. The +chosen pair is 20 and 21 rather than the review's 23 and 24 — both are +genuinely shared; 20/21 is simply the first in recorded order, and the walk +takes the first it can prove. + +What each selects, with the catalog scrolled rather than read from one frame: + +| Position | Caption the band draws | Component scopes the prefix admits | +| --- | --- | --- | +| 20 · Component admitted | `SELECTED · 20` | 3 | +| 21 · Component admitted | `SELECTED · 21` | 4 | + +One mark on the rail, two positions behind it, two different exact markers, and +content differing by exactly the component admitted between them. The +later-marker action is unchanged: position 218, the end of the order, selected +directly while inspecting, with the band named to it. + +**Correction, after the acceptance review.** This section previously said the +counts above were recovered by walking the catalog one row at a time with a +one-row movement check. They were not. `journey.py` carried **two** +definitions of `admitted_components()` — the scrolling one and an older +single-frame one later in the file — and Python used the later one, so the +scrolling walk never ran. The acceptance review caught this and the annotation +is right. + +What that does and does not affect: the 3 and 4 above are counts of the +complete visible prefixes at 160×36, where both fit in one frame, and the +review independently verified them. So the frozen H1 criterion stands on +evidence that is correct. What was wrong was my account of how it was +produced, and a single-frame count must not be relied on at a narrower +profile, where admitted scopes can fall outside the window and read as none. + +The duplicate is now removed: `journey.py` holds one `admitted_components()`, +the scrolling one, and its module docstring is a docstring again — both copies +came from the same bad edit, which inserted a definition ahead of the file's +opening string. The counts in this packet were **not** re-derived with the +corrected helper: the acceptance review requested no further gallery run, and +re-running one to restate a number the review has already established +independently would be work nobody asked for. Any later run of this journey +will use the scrolling count. + +`repl-history.test.ts`'s focused regression is unchanged and still passes: two +hundred real component admissions, groups measured by the real layout engine at +160, 120 and 72 columns, sharing pairs intersected across all three widths, and +the later prefix admitting exactly one more scope than the earlier. + +## The two corrections the R2 decision named + +Both were real and both are fixed. + +**The counts are now compared.** The stage recorded `checkpoints_before` and +`checkpoints_after` and never compared them. It does now, and the comparison +is what fails the stage rather than a number in a log: + +``` +offscreen-advance records 294 → 296 checkpoints 225 → 226 HEAD · EXPANSION PAUSED +``` + +Both counts are read the way the correction asks: records from the retained +file, checkpoints by walking the History drawer to the end of the order with +its own control, before the release and again after it. + +**Continue is no longer looked for during inspection.** Step 6 now opens and +closes History while still inspecting and requires the *paused head*, the +selected prefix and the selection to survive — and asserts that the frozen +view offers **no** Continue, which is the read-only action row the correction +describes. Only after returning live does step 7 require the real Continue, +activate it through the controller and carry the entry to an outcome: + +``` +hold-survived-history HEAD · EXPANSION PAUSED (no Continue offered) +offscreen-continued HEAD · SETTLED (after [live] → [continue]) +``` + +A third thing the rebuild needed, which is worth recording because it twice +produced a false green: the stage now proves the provider actually has a Plan +turn in hand before requesting the pause. "The entry is running" stays true +after a turn has come back, and a pause requested then is a pause against +nothing. The check reads the provider's own log positionally — request ids are +per session and are reused, so every turn in this journey is request 2. + +## The frozen commands, the controls and the packet + +Both unchanged frozen commands, on `05ba70d5`: + +``` +deno task test packages/cli/tests/repl-history.test.ts packages/cli/tests/repl-model.test.ts \ + packages/cli/tests/repl-execution.test.ts packages/cli/tests/repl-entries.test.ts \ + packages/cli/tests/repl-layout-admission.test.ts packages/cli/tests/repl-composition.test.ts \ + packages/cli/tests/repl-presentation-style.test.ts packages/cli/tests/repl-journey.test.ts +→ ok | 99 passed (312 steps) | 0 failed + +deno task test packages/cli/tests/repl-source-reading.test.ts packages/cli/tests/repl-forms.test.ts \ + packages/cli/tests/repl-agent-journey.test.ts +→ ok | 19 passed (111 steps) | 0 failed + +git diff --check → exit 0 +git diff --cached --check → exit 0 +deno task check → clean +``` + +The five controls, run from the packet against the amended worktree, each +restored and SHA-verified, with complete captured output per control in +`.controls-output/.log`: + +| Control | Outcome | What it breaks | +| --- | --- | --- | +| `KC1-token-drift` | BROKEN | named XMD and JSON cells against the archive literal | +| `KC2-no-rails` | BROKEN | `draws a rail on every row, in the colour of the region it is in` | +| `KC3-no-lifecycle` | BROKEN | **P1-T4**, the frame of a real held invocation, plus the waiting/EXIT unit rows | +| `KC4-label-list` | BROKEN | H4's placement, collisions and hierarchy, and H1's grouped-pair prefix case | +| `KC5-unowned-head` | BROKEN | H3's SETTLING case, through the single head derivation | + +The packet is `pr3-evidence/`: **all 77 pairs rebuilt end to end** on this +revision rather than patched — the retained location had drifted off the +gallery execution during the repair, and a self-consistent packet is worth +more than three re-taken frames. `comparison.html`, 27 contact sheets, +`capture-runbook.md`, `gallery-manifest.json`, `actions.jsonl`, +`pause-boundary-probe.md`, `probes/HistoryGate.ts`, +`revision-provenance.json` and `sha256sums.txt` over all 557 files. The audit +requires the held head for `offscreen-advance` and rejects `HEAD · LIVE`: + +``` +77 captures checked, 0 failed; 76 draw the band, 70 draw a mark on its rail +``` + +This run's R2 figures, from `actions.jsonl`: + +``` +offscreen-advance records 262 → 264 checkpoints 220 → 221 HEAD · EXPANSION PAUSED +hold-survived-history HEAD · EXPANSION PAUSED (no Continue offered while inspecting) +offscreen-continued HEAD · SETTLED (after [live] → [continue]) +settling-released HEAD · SETTLED (after the held teardown was let go) +``` + +Cold hashes are identical across the reopen in journal bytes, journal lines, +journal SHA-256 and provider-log SHA-256. + +The provenance note stands and is recorded in `revision-provenance.json`: the +captures were taken from this worktree shortly before the amended commit +object existed, against product source byte-identical to `05ba70d5` — the tree +was clean when it was amended, nothing under `packages/` changed between the +last journey stage and the amend, and the controls restore every file they +mutate. The committed files are hashed there, with the retired probe's bytes +and hash beside them. + +Nothing is pushed. No PR is open. No public artifact links are claimed, and no +acceptance is asserted. diff --git a/.reviewer/issue-881/pr3-implementation-handback.md b/.reviewer/issue-881/pr3-implementation-handback.md new file mode 100644 index 000000000..047334219 --- /dev/null +++ b/.reviewer/issue-881/pr3-implementation-handback.md @@ -0,0 +1,149 @@ +# PR 3 implementation handback: navigate the recorded History rail + +Base: accepted PR 2 `acadbbdb4fa7d8c8c86fa85f6657d29c5d95bc3e`. +Branch: `agent/issue-881-pr3`, worktree `.claude/worktrees/issue-881-pr3`. +Head at the time of writing: `f509197bd1998b376b09986b79fce2740568e76f`. +Nothing is pushed and no PR is open. + +## What is there + +| Commit | | +| --- | --- | +| `ca246a97` | Layers 1 and 3a: `navigation.ts` (the thin immutable summary and the head's precedence) and `history-rail.ts` (the measured five-row rail). | +| `2b148f07` | The band drawn as that rail, and the drawer given the whole recorded order. | +| `05bc510b` | Layer 2's evidence: the head against a real session. | +| `ac802025` | `specs/repl-spec.md` and `architecture.md`. | +| `d1e04771` | H1/H2. | +| `f509197b` | H5/H6. | + +Seventeen files, +2194 / −193. `historyBand`, `groupedMarkers`, `bandRows`, +`ReplSurfaceMarker`, `ReplPlacedMarker` and `HISTORY_LABEL` are gone from +`layout.ts`; the band is `ReplPreparedRail` now. + +## Frozen focused evidence + +Both commands, run on this head: + +``` +deno task test packages/cli/tests/repl-history.test.ts packages/cli/tests/repl-model.test.ts \ + packages/cli/tests/repl-execution.test.ts packages/cli/tests/repl-entries.test.ts \ + packages/cli/tests/repl-layout-admission.test.ts packages/cli/tests/repl-composition.test.ts \ + packages/cli/tests/repl-presentation-style.test.ts packages/cli/tests/repl-journey.test.ts +→ ok | 97 passed (308 steps) | 0 failed + +deno task test packages/cli/tests/repl-source-reading.test.ts packages/cli/tests/repl-forms.test.ts \ + packages/cli/tests/repl-agent-journey.test.ts +→ ok | 19 passed (111 steps) | 0 failed + +git diff --check → exit 0 +``` + +Those are the actual counts, not a required number. + +| Row | Where | What it holds | +| --- | --- | --- | +| H1/H2 | `repl-history.test.ts` | A prefix's content beside the whole file's navigation, with neither channel carrying the other's payload; and a malformed later segment refusing the whole reading rather than leaving stale navigation. Both have in-place controls: the content channel is shown to carry the prefix's own payload, so "navigation carries none" is not a claim about an empty string; and the same stream rebuilt *without* the bad record is shown to open at the same marker, so the refusal is the record's. | +| H3 | `repl-history.test.ts` | The seven-state precedence over `headOf`, and the head a real session publishes: empty, live, SETTLING read from inside the installation's own `ensure`, settled, and no payload in the summary. | +| H4 | `repl-history.test.ts` | The five rows allocated by one real layout engine at three measured widths: first and last positions, deterministic collisions, the entry/minor hierarchy, caption-range merging, the longest head's reservation, the shared ◆/▼ column, the empty band, and the refusal where the title will not fit. | +| H5 | `repl-journey.test.ts` | Every recorded position reached in the drawer with its own `[↓ later]`, visible/focus/pointer agreement row by row inside the drawer's rectangle, and 160×36 → 120×30 → 72×20 → 60×15 → 160×36 keeping marker, route, draft and focus. The scrolling claim is made at the narrow size, where one window really does hold less than the whole set. | +| H6 | `repl-journey.test.ts` | A cold process at an early prefix: settled head, the prefix's catalog, the retained draft, the same rail mark-for-mark at the same three sizes, category-only drawer rows, no live badges, byte-identical journal, no compile, no `.md` read, nobody asked, and a drawer window that opens at its first row although the process that recorded it left its own at the end. | + +Changed premises in existing suites, itemized: `repl-journey.test.ts` UI1/UI5 +asserted the band's *labels* and now asserts the band's title and rule, because +the band draws a measured rail rather than a list — the case is about the +footer's order and that is unchanged; `repl-presentation-style.ts` and +`repl-forms.ts` reading helpers now pass a navigation, because the drawer lists +nothing without one; `surface.ts` and `presentation.ts` fixtures gained +`rail: undefined` / `EMPTY_BAND`. Exact action, prefix, focus and teardown +behaviour are unchanged. + +## The five controls + +`pr3-evidence/.controls.py`, run one at a time on `f509197b`, each restored +from the bytes read before the mutation and verified by SHA-256. +Full records in `pr3-evidence/.controls.json`. + +| Control | Outcome | First failing step | +| --- | --- | --- | +| `KC1-token-drift` — one palette role moved by one bit | BROKEN | `P1-T1: a source row's delimiters, names, values and references are each their own`, and `P1-T1: a binding's JSON is read as JSON` — named XMD and JSON cells, against the independently sampled archive literal, not fixture equality | +| `KC2-no-rails` — the nesting rail removed from every row | BROKEN | `draws a rail on every row, in the colour of the region it is in` | +| `KC3-no-lifecycle` — the lifecycle words and glyphs removed | BROKEN | `says WAITING on the element that is waiting, with the waiting rail`, and `keeps EXIT's rail during a cleanup wait` — real held-call frames | +| `KC4-label-list` — every mark placed at its own index | BROKEN | `puts the first position at the start and the last at the end`, `groups collisions deterministically`, `keeps the entry's tall mark and the minor's stem when they share a column` | +| `KC5-unowned-head` — the head's owned-work fact cleared | BROKEN | `is SETTLING while the outcome is retained and the entry is still coming down` | + +All five restored; the runner exits non-zero if any control passes or any file +comes back different. + +## The gallery + +`pr3-evidence/` — seventy-seven pairs, twenty-five states at 160×36, 120×30 and +72×20 plus the two History resize endpoints, matching +`final-gallery-plan.json` exactly: nothing missing, nothing extra. Captured +from the real command in a private tmux PTY against this head, with its own +`$HOME`. `comparison.html` is the gallery, `sheets/` the per-state contact +sheets, `capture-runbook.md` how each was produced, `gallery-manifest.json` +the machine-readable list, `actions.jsonl` every keystroke, pointer press, +paste, resize and gate with its timestamp, `sha256sums.txt` all 545 files. + +`image-review-log.md` holds both readings: `audit.py` checking all seventy-seven +captures against their own rows of the frozen matrix — + +``` +77 captures checked, 0 failed; 76 draw the band, 70 draw a mark on its rail +``` + +— with a break-it control showing it fails when one capture's head word is +changed, and my own review by eye of five named pairs across all three +profiles. + +Cold hashes: `cold-before.json`, `cold-after.json` and +`cold-after-historical.json` are identical in journal bytes, journal lines, +journal SHA-256 and provider-log SHA-256. + +## Four things the Planner should know + +**The crowd fixture does not use `Json`, and the plan's premise for it is +wrong.** `stack-and-evidence.md` asks for two hundred `` invocations to +produce enough checkpoints to collide. Measured against the real projector that +is *one* position: a publication record carries every binding it publishes and +the projector records one `binding` checkpoint per record, so thirteen `` +elements in one entry drew one mark. A component scope is what is one position +each. `history-crowd.md` therefore invokes a Markdown component two hundred +times, each carrying a `secret` of its own so a frozen earlier reading can +still be checked for a later payload. The result is the crowding the criterion +wants: 218 positions over a 134-cell rail at 160 columns, so marks share columns +at every measured width. + +**The controlled host is needed for one state, not three.** The matrix sends +"pause/cleanup scenes" to it. Both paused states turned out to be reachable +through `xmd repl` itself — its own `[pause]`, against a provider holding at +the fixture's gate, gives `PAUSING EXPANSION` and then `EXPANSION PAUSED` — so +they were captured with the ordinary command and the controlled host is used +only by `settling-head`, where no public grammar holds the window open. That +host adds exactly one installation to the production assembly and assembles no +Agent stack, because the entry it holds is a `` publication. + +**One observation I am not claiming as a defect.** In one run, Escape left a +History drawer scrolled to the end of 218 positions still standing. Two +targeted reproductions — scrolled to the end with no selection, and scrolled to +the end with the last position selected — both closed on Escape, as did the +unscrolled and three-row-scrolled cases. So it did not reproduce and I am not +reporting it as a finding. The journey now presses Escape, falls back to the +drawer's own `[close]`, and records in `actions.jsonl` which one dismissed it. + +**`historical-before-admission` is PR 2's row, not PR 3's.** It is the one +state in the matrix with `yes` under PR 2 and `—` under PR 3, so it is not +among the twenty-five and is not captured here. + +## What is not done + +The three capture fixtures — +`packages/cli/tests/fixtures/repl/issue-881/{HistoryRecord.md,history-crowd.md,controlled-host.ts}` +— are **staged but uncommitted**: every signing attempt fails with +`fatal: failed to write commit object`, which is 1Password's SSH agent rather +than git. They are formatted, lint-clean and typecheck, and the product source +at `f509197b` is what every capture and every control ran against, so no +evidence depends on them landing. They need one `git commit` once the agent is +unlocked. + +Nothing is pushed. No PR is open. No public artifact links are claimed. diff --git a/.reviewer/issue-881/pr3-implementation-handoff.md b/.reviewer/issue-881/pr3-implementation-handoff.md new file mode 100644 index 000000000..6efb2ec28 --- /dev/null +++ b/.reviewer/issue-881/pr3-implementation-handoff.md @@ -0,0 +1,300 @@ +# PR 3 implementation handoff: navigate the recorded History rail + +**Frozen; ready for implementation from accepted PR 2.** History shows all retained +checkpoint positions while content reads one selected prefix. Tall entry marks +and shorter semantic marks share a five-row rail. Selection stays amber above +the rail; the truthful head stays below it, including at the same column. +The drawer selects every exact checkpoint, even when rail marks are grouped. + +The accepted [architecture handoff](pr3-planner-handoff.md) owns these product +and structural decisions. This plan freezes the concrete algorithm, focused +evidence and [77-pair assembled gallery](final-gallery-matrix.md). The shared +[stack and evidence record](stack-and-evidence.md) supplies exact revisions, +real fixtures and feedback rules. This is planning, not production acceptance. + +## Base and boundaries + +Implement on accepted PR 2 **acadbbdb4fa7d8c8c86fa85f6657d29c5d95bc3e**, parent +9163a16b9f5b83e9c042f47e90ac307f4679d239. The [Planner acceptance](pr2-planner-acceptance.md) +records independent structural, visual and live feedback. Its integrated base is +c7d54769d56661bef38cee8549b148f3bf87a904: accepted PR 1 +080b6ec80ca74e614789e8d2252857ac281df7e5 plus recorded main +4c0414be1010f69f11bff0d1d634623a5b08f886. Branch from the accepted PR 2 SHA and +refresh overlaps before production edits. PR 3 preserves PR 2's public observation +and static inspection APIs, source/output/wrapping, arrows and live/prefix rules. + +No persistence, timing, sidecar, new Core API, dependency/vendor update, provider +during settled inspection, new terminal reader, observer stream, polling, +scrubbing, horizontal scrolling, fork, editor, auto-drawer or newer reference +feature belongs here. The draft and contextual action row retain their product +behavior. This slice supplies complete original visual evidence for #881; its +feedback remains separate from delivery and publication. + +## 1. Give navigation and content one retained snapshot + +Use this exact private view shape, reusing existing ReplCheckpoint kinds: + +```ts +interface ReplHistoryNavigation { + readonly checkpoints: readonly Pick[]; + readonly head: "empty" | "live" | "pausing" | "paused" | + "settling" | "settled" | "unfinished"; +} +``` + +Detach/freeze the list and each item. Both members are required. Carry no +checkpoint label, source, component/binding name, value, output, question, +permission, Agent detail, outcome detail or lifecycle observation. Selection +already belongs to the root route and is not copied into this summary. + +In program.ts, replace the selected-only reproject shortcut with a rebuild from +one readAll result per retained/session wake. Snapshot the acknowledged event +array before projection. Project its full head and requested marker using that +same array and projectRepl's existing full-file validation. Two projections of +one immutable input are sufficient; do not add a second reader or redesign the +projector. Derive the thin list from the full validated model, derive the +inspected model from the requested prefix, and discard the full model from child +reachability. Never derive full navigation by appending to a selected model. + +A later malformed segment refuses the whole reading even for an earlier marker. +Use the existing refused view, not stale navigation beside a plausible prefix. +An invalid requested marker retains the existing route refusal semantics; it +never rounds to a grouped mark or head. Initial/cold validation uses this same +flow before a resolved screen is composed. During paint/resize preparation, +reuse that one immutable reading; a new retained append wakes another rebuild. +Do not read the Journal from a description, drawer or renderer. + +Pass navigation root → application view → footer band and History drawer through +the direct parent composition. Only the band receives head; the drawer receives +the thin list. Other panes receive the selected model and suppressed historical +live overlay. This is the explicit navigation exception to whole-view prefix +wording, not an exception for content or capabilities. The inspected action row +still reads History and offers only its existing historical controls; it does +not acquire Pause, Continue or Submit from navigation. Returning live resolves +the latest actual session view and capabilities. H1/H2 prove this separation. + +## 2. Derive the head from retained facts and owned work + +Use the full snapshot's latest entry/root outcome and the session's actual +entry-wide liveness from PR 2. That signal remains true until all entry resources, +including its outer Agent attachment and consumers, release. The first-registered +last-running entry finalizer publishes the existing session wake. Do not set +settled from body return, root Close, component badges, drawers or selected +content. Preserve submission readiness and cancellation/failure ownership. + +| Precedence | Required facts | Exact label | +| --- | --- | --- | +| 1 settling | Latest root outcome retained; owned entry task still active. | HEAD · SETTLING | +| 2 paused | Active task, no root outcome; controller actually paused. | HEAD · EXPANSION PAUSED | +| 3 pausing | Active task, no root outcome; controller actually pausing. | HEAD · PAUSING EXPANSION | +| 4 live | Active task; none of the preceding cases. | HEAD · LIVE | +| 5 empty | No retained entry and no owned task. | HEAD · EMPTY | +| 6 settled | No active task; latest entry has a retained root outcome. | HEAD · SETTLED | +| 7 unfinished | Latest entry lacks root outcome; no active task. | HEAD · UNFINISHED | + +Paused stops expansion, not already-started background work. A retained success, +failure or cancellation all become neutral SETTLED after owned unwind. Missing +outcome without owned work is UNFINISHED, never an inferred paused state. +Settled cold inspection starts no work. Existing unfinished-run resumption +remains unchanged; if it starts actual work the head describes that work. + +Head-only changes publish through the current session/controller wake path, +including while inspecting. Add no stream, timer or competing frame clock for +static History. H3 uses real start, controller holds, retained Close and held +installation cleanup, then checks the completion repaint without input. + +## 3. Allocate the five rows with engine measurements + +Replace layout.ts's historyBand/groupedMarkers/bandRows label-list presentation. +Application.ts prepares immutable rail data from navigation, route selection and +engine measurements; presentation-style.ts maps its explicit roles to literal +colours. Layout receives inert placement/text data. It receives no Journal, +session, capability, mounted focus or authoritative outcome. + +Keep footer rows action, five History rows, draft at every profile: + +| History row | Left region | Stable right caption region | +| --- | --- | --- | +| 1 | History · recorded order | Head label | +| 2 | Entry captions, or No recorded checkpoints | Selection caption | +| 3 | Tall entry uprisers and historical selection diamond | Blank | +| 4 | Horizontal rail, entry/minor junctions | Blank | +| 5 | Short minor stems and head marker | Blank | + +Use prepareFrame's measurement pass and the private fit probes described in +[planning-measurement.md](planning-measurement.md). Measure the band's inner +width, title, all seven head labels, `SELECTED · HEAD`, current +`◆ SELECTED · N`, and the actual entry captions. Reserve the maximum of head +and selection caption widths at the right, plus an engine-measured separating +space. Use the same reserved width for all head states. The remaining measured +left region owns the rail, and must hold the title and admitted entry captions. +No head-state-only update changes those reservations or source rail placement. +Changing count/selection or size may remeasure. Paint empty areas with the band +surface so a shorter caption cannot leave old cells behind. + +These deterministic mechanics are frozen: + +1. Let W be the engine-measured available rail columns, K the complete checkpoint + count and i its zero-based ordinal. For K>1 place i at + round(i × (W−1)/(K−1)); for K=1 place it at W−1. Empty has no checkpoint marks. + This is proportional spacing inside measured bounds, not elapsed time. +2. Consecutive ordinals assigned to one column form one visual group. Keep + every marker/kind in the group's private presentation membership. K and the + same measured size produce identical groups, independent of head state. + The head marker is below the rail end; an active empty reading has a head + label but no invented checkpoint tick or target. +3. Entry marks use `┃` above the rail. Minor marks use `┬` at the rail and `│` + below; crowded groups use heavier `┳`/`┃`. Groups with entries preserve their + tall boundary and heavier junction. Assemble entry/minor collisions without + dropping either category. Junction shape details remain private. +4. An inspected selection uses an amber `◆` in row 3 and amber junction in row 4 + at its group's column. Its right caption is `◆ SELECTED · N` using the exact + full-list one-based ordinal, never the group ordinal. Live has + `SELECTED · HEAD` and no earlier-selection diamond. Head uses `▼` in row 5. + If both share a column, preserve ◆ above and ▼ below with separate colours. + Those distinctive markers win their cells; other category information remains + in junctions/captions and exact drawer rows. The rail is not interactive. +5. Number entries by admitted entry order. Start one caption `Entry E` per entry + at its column, centred on that mark and clamped to the left measured region. + Its width is the engine's actual fit result. Require one separating cell + between adjacent captions. For the first overlapping pair from left to right, + merge its actual consecutive entry span into `Entry A–B`; centre that caption + between its first/last entry columns, clamp, remeasure, and repeat left to + right until all captions fit without overlap. Merged captions never include + a nonexistent entry, clip a number or invade the right region. A measurement + refusal follows the existing frame refusal, not an ellipsis or overwrite. +6. Express columns/spaces as constrained engine boxes or measured text runs. + The engine owns final bounds; no parallel screen/pointer coordinate map is + built. History's static marks/captions mount no controls or targets. Exactly + one prepared reading feeds placement, descriptions and committed cells. + +At 72×20 the title and longest head still fit, with rail columns remaining. +Use the crowded real fixture for caption merges rather than assuming caption +length in characters. Resize remeasures and regroups while preserving exact +marker, route and draft; focus follows existing mounted-window rules. Drawers +remain above seven footer rows, and absent narrow surfaces have no nodes/targets. +H4/H5 verify measured placement and navigation separately. + +## Colours and exact drawer rows + +These accepted literals are independent expectations, copied with original +source provenance to the test fixture: + +| Role | Colour | +| --- | --- | +| Band surface / horizontal rail / title | #08090b / #141a1f / #8b959c | +| Entry caption / tick at or before selection, or live | #b8c4cc / #e6ecf1 | +| Minor mark at or before selection, or live | #7fd3e8 | +| Later entry tick and caption / minor mark | #5d666e / #4e565d | +| Selected diamond, junction and ordinal caption | #c9a86a | +| Live head marker and label | #7fd3e8 | +| All other head states, SELECTED · HEAD, empty message | #7b858d | + +Later means ordinal after selection. For each group, entry and minor categories +independently use their earlier colour when any corresponding member is at/before +selection; otherwise later. Merged entry captions spanning selection use the +earlier caption colour. Selected junction/diamond/caption win their cells; head +keeps its own state colour below. No global focus recolouring, green settled +success, checkmark or animation is implied. Preserve PR 1's drawer focus/selection. + +Replace drawerRows's use of checkpoint.label with one row per full marker: + +| Kind | Exact wording; N is full ordinal, E is entry order | +| --- | --- | +| entry | N · Entry E admitted | +| scope | N · Component admitted | +| binding | N · Bindings recorded | +| generated | N · Generated XMD admitted | +| elicit | N · Answer recorded | +| agent | N · Agent turn recorded | +| terminal | N · Entry outcome recorded | + +Count E from entry kinds in the thin list, without looking up future payloads. +Use identical category wording at live and historical routes. A recorded answer +is not a wait; admission is not invocation completion; entry outcome is not +finished cleanup. Keep History title, marker-based key and typed marker action, +selected cue, existing window and `[↑ earlier]`/`[↓ later]` controls. Every group +member keeps a separate drawer action. Off-window rows have no node, pointer +target or Tab stop. Add no legend/hint row that costs capacity. Empty has no +drawer marker action and no fabricated selected ordinal. H1/H5 cover the drawer. + +## Frozen focused evidence + +Add packages/cli/tests/repl-history.test.ts. Extend the existing projector, +execution, entry, composition, layout and journey regressions using their real +stream/profile/renderer fixtures. Do not fabricate a head state for an acceptance +journey; derived unit tests may take an actual retained unfinished snapshot +without opening/resuming it. + +| ID | Concrete inputs and required evidence | Defect discriminated | +| --- | --- | --- | +| H1 | Complete Plan then the corrected HistoryRecord crowd fixture. Pick two same-category component-admission markers sharing one measured column; exact root drawer actions reveal each corresponding prefix, including its distinct admitted component set. Full category rows include all seven kinds and correct N/E. | Group substituted for marker; prefix-only navigation loses later positions. | +| H2 | Select before generated source, bindings, answer and Agent admission. Inspect panes and drawer; only full identity/kind and band head exception cross. Corrupt a later segment and ask for earlier marker: full refused view, no stale navigation. | Future payload/richer label leaks or partial validation. | +| H3 | Actual empty, pre-first-record active task, live, pausing, paused; request Pause against already-started work, inspect during PAUSING, then release it: retained records and full navigation grow, selected content stays fixed, and the controller establishes PAUSED. Held root-outcome teardown reads SETTLING then neutral SETTLED without input. Separate retained success/failure/cancel and unowned unfinished. Readiness/controls remain with real owner. | Root Close proves completion, background work declared stopped, historical execution authority. | +| H4 | Empty, singleton and the crowd fixture's complete checkpoint list at all three engine-measured sizes. First/last positions, deterministic collisions, entry/minor hierarchy, entry caption range merge, longest head fit, independent shared-column ◆/▼; head-only transition leaves groups/caption reservation unchanged. | Character-count admission, overlap, list substitute or hidden marker. | +| H5 | Populated exact History drawer, all rows reached with Unicode controls; visible/focus/pointer target agreement. Resize 160×36→120×30→72×20→60×15→160×36 preserves marker, route, draft and focus under existing admission rules. | Invisible actions, changed identity or extra narrow mounts. | +| H6 | Settled cold head and early prefix, retained draft, same markers/order/grouping at same sizes, category-only labels, no live badges. Journal/provider hashes and component-source-load counters unchanged; process-local offsets initial. | Reconstruction by execution or persistence of presentation. | + +Planner fixture correction after review at f509197b: one binding publication can +hold many Json results, so Json count does not establish checkpoint count. Use +200 actual HistoryRecord Markdown invocations for crowding. H1 keeps its exact +prefix requirement and uses two scope checkpoints of the same category. See +[the PR 3 review](pr3-planner-review.md); the frozen gallery remains 77 pairs. + +Planner R2 evidence-order correction: establish provider work, request Pause, +inspect while PAUSING, then release the work and observe the retained advance +and actual PAUSED head. Closing History preserves the hold; Continue is checked +after returning live. [The correction](pr3-r2-evidence-correction.md) supersedes +the earlier establish-before-release fixture recipe. The controller is unchanged. + +Run these exact focused commands on the actual PR 3 implementation base: + +```bash +deno task test packages/cli/tests/repl-history.test.ts packages/cli/tests/repl-model.test.ts packages/cli/tests/repl-execution.test.ts packages/cli/tests/repl-entries.test.ts packages/cli/tests/repl-layout-admission.test.ts packages/cli/tests/repl-composition.test.ts packages/cli/tests/repl-presentation-style.test.ts packages/cli/tests/repl-journey.test.ts +deno task test packages/cli/tests/repl-source-reading.test.ts packages/cli/tests/repl-forms.test.ts packages/cli/tests/repl-agent-journey.test.ts +git diff --check +``` + +The second command holds the preceding source, drawer and Agent slice through +assembly. Existing tests may update their list/label premise; retain exact action, +prefix, focus and teardown behavior and itemize each changed assertion. +Report actual counts, not an invented required count. Commit promptly after +focused evidence passes; do not wait for exhaustive CI or whole runtime suites. + +Run five controls independently on the assembled feedback revision: collapse +token roles (a named XMD/JSON cell fails); remove nesting rails (source geometry +fails); remove lifecycle words/glyphs (real held-call frame fails); replace +History with a label list (H4 shape/shared markers fails); clear the head's +owned-work fact at root Close (H3 fails while held teardown is entered). +The full/selected snapshot and future-payload refusal cases in H1/H2 are direct +negative regressions; they require no additional control mutation. Keep all +patches, first failures and SHA-verified restorations. A one-bit palette drift +is the token control when applied to an independently sampled original role; +it must fail the named committed-cell assertion rather than fixture equality. + +## Documentation, gallery and handback + +Update architecture.md and specs/repl-spec.md together with implementation. +Describe the explicit full-navigation/head exception, root-owned thin immutable +summary, one validated snapshot, prefix-only other panes, exact checkpoint +actions, entry-wide cleanup truth, category wording, measured five-row rail and +grouping in present tense. Keep the action row's historical restrictions and +fixed seven-row footer. No new executable-MDX or persistence contract is added. +Architecture review uses the seven frozen checks in pr3-planner-handoff.md. + +Capture and open all 77 pairs on the exact assembled feedback SHA, using the +frozen matrix and accepted terminal adaptations. Do not substitute the accepted +35 PR 1 pairs or PR 2 captures for fresh assembled captures. Return gallery, +runbook, manifest, image review, cell/target evidence, controls, actual focused +commands and cold hashes under pr3-evidence/ and pr3-implementation-handback.md. +Public artifact links belong to separately authorized delivery work. A local +Planner feedback verdict alone neither publishes a PR nor closes #881. + +Continuity: required predecessor is accepted PR 2 +acadbbdb4fa7d8c8c86fa85f6657d29c5d95bc3e on the exact stack recorded above. +Artifacts are this handoff and the shared stack, measurement and final-gallery +records. All original-scope architecture and presentation decisions are settled. +**Planning blockers: none; PR 2 acceptance dependency satisfied.** Next Implementor +action: branch from that exact feedback SHA, prepare the worktree under AGENTS.md, +and implement the snapshot, head and rail layers above. Return the frozen focused +evidence and fresh 77-pair assembled gallery; stop before push or PR creation. diff --git a/.reviewer/issue-881/pr3-planner-acceptance.md b/.reviewer/issue-881/pr3-planner-acceptance.md new file mode 100644 index 000000000..d6e23e374 --- /dev/null +++ b/.reviewer/issue-881/pr3-planner-acceptance.md @@ -0,0 +1,50 @@ +# PR 3 Planner acceptance at 05ba70d5 + +**PASS.** Reviewed **05ba70d567cb80be4bfdea67e7ae0267376e2376**, parent f509197bd1998b376b09986b79fce2740568e76f, on `agent/issue-881-pr3`, against accepted PR 2 base acadbbdb4fa7d8c8c86fa85f6657d29c5d95bc3e. This supersedes the REQUEST CHANGES verdict at 3fa241dc. The worktree is clean. This is implementation feedback against the frozen original-parity contract; delivery verification remains a separate boundary. + +R4 and R5 satisfy the remaining acceptance requirements. R1–R3 remain accepted. No persistence, lifecycle API, History ordering or presentation contract is reopened. + +## R4: actual shared mark and different prefix content + +The corrected rail helper reads band row 2, above the rule, instead of the right-hand selection caption. The candidate record rejects 18/19 at columns 10/11 and 19/20 at 11/12, then selects 20/21 at 12/12. These measurements are explicitly **160×36, zero-based**. The handback withdraws the earlier false 18/19 claim. + +The Planner independently selected those positions through the amended command's actual History drawer. At wide, 20 and 21 both draw their selected rail mark at column 12, retain their exact ordinal captions, and show three versus four HistoryRecord scopes. The complete entry-5 component lists fit: neither catalog has a later-window control hiding another scope. The later marker 218 is selected directly while inspecting, and returning live reaches SETTLED. The copied retained file remains byte-identical through these reads. + +The same pair need not share at every width: it draws at 8/9 at 120×30 and 4/4 at 72×20. This review accepts the explicitly wide root-journey proof, together with the unchanged focused regression that intersects genuine sharing pairs across all three profiles. The earlier independent 23/24 walk at all three profiles remains recorded in the preceding review. No new profile permutation is required. + +**Evidence annotation:** the supplied journey defines a scrolling `admitted_components()` at line 1, then replaces it with the older single-frame definition at line 336. Python therefore does not execute the claimed scrolling count. This review does not accept the handback's claim that the new one-row movement check supplied these counts. The actual wide three/four count still discriminates the two complete visible prefixes, as independently verified above, so the shadowed helper does not leave the frozen H1 criterion unproven. It is not used to claim complete narrow counts. No additional gallery run or product commit is requested for this annotation. + +## R5: narrowed projections and owned teardown + +The memo now holds one `Result`, built from one acknowledged-array slice by the private `project()` helper. Both successful projections narrow together; failed results return unchanged. The new production casts and reconstructed failures are gone. Head derivation remains outside the memo and in its single existing function. + +HistoryGate is absent from committed executable test source. Its original bytes remain in `probes/HistoryGate.ts`, with the recorded ea46a4d6… hash, as historical probe evidence. Removing the unused probe is the permitted correction; no new executable watcher remains to require a cancellation regression. + +The controlled host narrows its latch paths at the edge and uses `writeTextFile` and `exists` from `@effectionx/fs`. Its installation still registers its teardown through `ensure`. The Planner's updated-host check verifies the actual latch entry, SETTLING, refusal of another submission, and SETTLED after latch release with no terminal input. + +## Frozen evidence + +Both unchanged frozen commands passed independently from this commit: + +```sh +deno task test packages/cli/tests/repl-history.test.ts packages/cli/tests/repl-model.test.ts packages/cli/tests/repl-execution.test.ts packages/cli/tests/repl-entries.test.ts packages/cli/tests/repl-layout-admission.test.ts packages/cli/tests/repl-composition.test.ts packages/cli/tests/repl-presentation-style.test.ts packages/cli/tests/repl-journey.test.ts +deno task test packages/cli/tests/repl-source-reading.test.ts packages/cli/tests/repl-forms.test.ts packages/cli/tests/repl-agent-journey.test.ts +git diff --check +git diff --cached --check +``` + +Results: **99 passed / 312 steps** and **19 passed / 111 steps**, both exit 0. Both whitespace gates exit 0. The five supplied mutation controls are BROKEN; each full failure log is present, each recorded restoration hash matches its initial hash and the reviewed source, and the named failures reach the intended boundary, including P1-T4's real suspended invocation and H3's owned teardown. The Planner inspected these records without mutating product files during its live check. + +All **77 production/reference pairs** were opened through their **27 contact sheets**. The original reference direction remains satisfied under the frozen terminal adaptations: pane hierarchy, source/output roles, lifecycle reading, drawer treatment, recorded-order rail, selection and head. The independent copied audit reports 77 checked, 0 failed, 76 bands and 70 marked rails. The supplied offscreen record compares 262→264 retained records and 220→221 checkpoints, keeps EXPANSION PAUSED and the selected prefix, preserves the hold through History, then reaches SETTLED after returning live and continuing. + +All **557 supplied checksum entries** match. The nine provenance hashes match both committed blobs and current files. The supplied cold-counter triplet is identical; its byte/line hashes also match the corresponding prefixes of the retained Journal and provider log after the later offscreen append. Captures precede creation of the amended commit object; their documented source equivalence is accepted under the previous review's sufficiency ruling. They are not described as post-commit captures. + +The prior independent eight-step live/cold journey at three profiles remains applicable: the production delta from 3fa241dc is the narrowed memo representation, removal of the unused probe and the controlled host's filesystem adaptation. The memo behavior is also covered by both rerun commands, and the changed host is checked live here. The full journey is not claimed to have been rerun at this SHA. + +## Continuity and next action + +The seven original architecture checks remain satisfied under the accepted PR 2/PR 3 contracts and the preceding structural review. Session-owned live observations remain separate from retained prefix facts. No new persistence or replay execution is introduced. + +Original-scope Planner implementation review is complete for PR 1 at 080b6ec80ca74e614789e8d2252857ac281df7e5, PR 2 at acadbbdb4fa7d8c8c86fa85f6657d29c5d95bc3e, and PR 3 at **05ba70d567cb80be4bfdea67e7ae0267376e2376**. No required Implementor repair remains against this frozen matrix. The next boundary is delivery under the repository's delivery gates. This review performs no push, PR, merge or CI action. + +Evidence is retained in [pr3-planner-acceptance-evidence/sha256sums.txt](pr3-planner-acceptance-evidence/sha256sums.txt), including the stable supplied packet copy, hash/source verification, focused logs, all opened sheets, helper-definition annotation, independent live drivers and actual terminal captures. The teardown driver’s initial helper-name failure and corrected completion are disclosed in driver-notes.md; no product failure is hidden. diff --git a/.reviewer/issue-881/pr3-planner-handoff.md b/.reviewer/issue-881/pr3-planner-handoff.md new file mode 100644 index 000000000..c43dc5e1a --- /dev/null +++ b/.reviewer/issue-881/pr3-planner-handoff.md @@ -0,0 +1,343 @@ +# PR 3 Planner handoff: recorded History rail and exact checkpoint selection + +**Ready for planning.** The Product Owner accepts the complete History +navigation boundary, six presentation decisions and main verification journey. +Prepare a self-contained implementation handoff for the final slice of +[Story #881](https://github.com/taras/executable.md/issues/881). Product behavior, +member types, labels, colours, grouping and prefix isolation are settled. + +This is an architecture/design handoff. It reports no PR 2 or PR 3 implementation +verdict, production test run, feedback commit, completed visual parity or +delivery approval. The Planner freezes concrete sites, fixtures, focused commands, +finite visual evidence and negative controls before implementation. + +## Outcome and smallest example + +History shows the complete recorded sequence while a person reads an earlier +checkpoint. Tall entry ticks and short minor marks establish hierarchy. An +amber diamond above the rail identifies selection; a separate head marker +below the rail describes the current overall state. Both stay visible at the +same column. The History drawer selects every exact marker, including those +sharing a crowded rail mark. Inspected content remains the selected prefix. + +For example, checkpoints 41–43 can share a grouped notch. Selecting drawer row +`42 · Bindings recorded` keeps `◆ SELECTED · 42` at right and reads exactly that +prefix. It does not reveal checkpoint 43's bindings. Later recorded marks stay +available in navigation with dimmer colours. + +## Stack and authority + +- PR 1 Planner feedback is PASS at + **080b6ec80ca74e614789e8d2252857ac281df7e5**, parent + f0b8eb1f323c1ad5826eafba978ef9c2e9f5fffa, recorded base + e68f128121cd802623ab7797a016b0c66ce91176. Preserve its + [acceptance record](pr1-planner-acceptance.md) and 35-pair evidence unchanged. +- PR 2's [architecture handoff](pr2-planner-handoff.md) is ready for planning. + Its middleware, source inspection, source/output reading, wrapping and arrow + labels are accepted contracts. No accepted PR 2 implementation SHA is supplied + here. PR 3 plans against those contracts and implements on the actual accepted + preceding slice. Record the exact stack base and refresh overlaps before + implementation; do not infer production acceptance from design approval. +- Architecture workspace HEAD is + 2d719f78025059158a35023701fdff52b855a65b. This is not a current remote-head or + CI claim. Merged #876/#877/#878 supply measured layout, reveal retention and + semantic styling. Reuse installed dependencies and the patched Freedom tree. +- The older corrected reference archive owns visual intent. Its SHA-256 is + **86be64318121546f3208342edaf17f0a3aed35f3fde2766b523423e6c708c77b**; + retained bytes are [evidence/reference.zip](evidence/reference.zip). + The newer Downloads archive adds a feature and supplies no requirement. +- Detailed accepted contracts are + [pr3-history-contract.md](pr3-history-contract.md) and + [pr3-product-verification.md](pr3-product-verification.md). This handoff + consolidates their consequential decisions. The + [colour study](visuals/history-colours.html) is an interview aid, not a measured + terminal capture. The full-story matrix is a source for the Planner's evidence + plan, not another frozen oracle. + +Read repository AGENTS.md, required Effection instructions, architecture.md, +the affected REPL specification and the accepted PR 2 boundary records. Setup +owns dependency preparation; builds/checks do not reinstall or mutate that state. + +## Accepted private navigation interface + +```ts +interface ReplHistoryNavigation { + /** All retained checkpoint identities and kinds, in append order. */ + readonly checkpoints: readonly Pick[]; + /** Overall head state for the History band, independent of inspected content. */ + readonly head: + | "empty" + | "live" + | "pausing" + | "paused" + | "settling" + | "settled" + | "unfinished"; +} +``` + +Reuse ReplCheckpoint's existing marker identity and kind union: entry, scope, +binding, generated, elicit, agent and terminal. The summary name is private +implementation vocabulary, not a Core API or a new package export. Both members +are required. Freeze a detached list and each element. The route already owns +selection; do not duplicate it in the summary. + +Carry no original label, component or binding name, source, value, rendered +output, question, permission, Agent turn, outcome detail or lifecycle observation. +An empty list means no retained selectable checkpoint. Grouping never changes +marker identity or creates a durable checkpoint. + +The root program drive owns the reading. Derive full navigation and the selected +model from one validated retained-event snapshot; rebuild on the existing session +wake path, including during inspection. A damaged later segment remains a +projection refusal even when the requested marker is earlier. Do not present a +stale or partial navigation summary beside a plausible prefix. + +Pass immutable data through the direct parent-child path: root program +composition to application view, then to footer History and the History drawer +through existing parent composition. The band receives both members; the drawer +receives the marker list. Children do not project the Journal or read the +session. Renderer input remains engine operations and the renderer stays +model-blind. No additional host reader, polling loop, observer stream or durable +store is introduced. + +This is the accepted History navigation exception to whole-view prefix wording. +Source, Output, Sessions, Bindings, questions, permissions, Agent details and +live lifecycle overlays remain prefix-only during inspection. The frozen action +row still reads History and offers only its existing historical controls. +Navigation does not grant Pause, Continue or Submit authority. Returning live +resolves the actual current view and capabilities. + +## Head states, precedence and exact labels + +Use this precedence and these facts, from the full retained reading and actual +session-owned entry task/controller state: + +| State | Required fact | Exact label | +| --- | --- | --- | +| settling | Latest root outcome is retained; its owned task still releases resources. | HEAD · SETTLING | +| paused | Task is active without a root outcome; real controller reports paused. | HEAD · EXPANSION PAUSED | +| pausing | Task is active without a root outcome; real controller reports pausing. | HEAD · PAUSING EXPANSION | +| live | Task is active and none of the preceding states applies. | HEAD · LIVE | +| empty | No entry is retained and no entry task is active. | HEAD · EMPTY | +| settled | No entry task is active; latest entry has a retained root outcome. | HEAD · SETTLED | +| unfinished | Latest entry has no root outcome and no entry task is active. | HEAD · UNFINISHED | + +Paused holds expansion, not already-started background work; that work may still +advance the Journal. Settled includes successful, failed and cancelled outcomes +and carries no success cue or payload. Unfinished does not mean paused. Do not +derive state from a drawer, a component badge, the selected prefix, missing +frames or an absent terminal record alone. + +Owned work remains active through its complete teardown. A body return or root +close does not prove release. The plan names the session-owned boundary that +proves cleanup is complete and wakes the existing rebuild; do not assume the +current session.live flag covers every outer attachment. Preserve ownership, +cancellation, failure precedence and submission readiness. No new resource +owner is proposed. + +Cold readings use retained facts unless this process actually owns work. This +does not add a mode that disables existing unfinished-run resumption. The +accepted cold-immutability journey opens a settled execution. + +## Five rows, marks and grouping + +Keep the same layout at 160×36, 120×30 and 72×20: + +| History row | Reading | +| --- | --- | +| 1 | History · recorded order at left; head label at right. | +| 2 | Entry captions over the rail; selection caption at right. | +| 3 | Tall entry uprisers and selected diamond above the rail. | +| 4 | Horizontal rail with entry and minor junctions. | +| 5 | Short minor stems and head marker below the rail. | + +The contextual action row precedes these rows and the draft follows, for seven +footer rows. Drawers remain above the footer. Narrow shows only its routed +surface and admitted drawer; absent surfaces have no nodes or targets. + +Reserve one stable engine-measured right-hand caption region covering the +largest head label and current selection caption. Marks occupy the remaining +measured rail region. A head-state-only change neither moves the selected mark +nor reflows the rail. No extra separator or legend consumes a row. + +Use `┃` entry uprisers, `─` rail, `┬`/`│` minor marks, an amber `◆` selection +above and a `▼` head below, aligned with the rail end. These are readings, not +key bindings or controls. Exact junction assembly remains local. + +Place checkpoint ordinals evenly across available measured columns: first at +the start, last at the head; a singleton at the head. Consecutive ordinals +sharing a column form one visual group. Use heavier `┳`/`┃` minor marks for +crowded groups. Groups containing entries retain tall entry boundaries and a +heavier rail junction. Entry/minor collisions retain both readings where the +distinctive head/selection markers do not occupy those rows. + +Entry captions use Entry N. Merge overlapping adjacent captions into actual +consecutive entry ranges, such as Entry 1–3, until they fit their measured region. +Do not clip into a different number or overwrite right-hand captions. The +Planner supplies the concrete deterministic algorithm against engine bounds; +character-count width estimates do not own admission. + +Historical selection reads `◆ SELECTED · N`, where N is the one-based ordinal +in the complete checkpoint list. Live selection reads `SELECTED · HEAD` with no +earlier-selection diamond. If selection and head share a column, retain ◆ in +row 3 and ▼ in row 5, with separate colours. These distinctive marks take +precedence over an entry upriser or minor stem in their own cells; rail/group +identity and entry captions still represent the boundary. + +With no checkpoints, show No recorded checkpoints in row 2, with no fabricated +tick, selected ordinal or target. Actual work before its first checkpoint may +still give a live head label. Keep the five-row band. + +Resize remeasures and regroups, preserving marker identity, draft and route; +focus follows established window/admission rules. The same snapshot and size +produce the same groups. Appended checkpoints may change proportional placement; +changing only head state does not. No rail input, scrubbing, horizontal scrolling +or new navigation mode is introduced. + +## Accepted literal colours + +| Reading | RGB hex | +| --- | --- | +| History surface | #08090b | +| Horizontal rail | #141a1f | +| History title | #8b959c | +| Entry caption at/before selection, or at live head | #b8c4cc | +| Entry tick at/before selection, or at live head | #e6ecf1 | +| Minor mark at/before selection, or at live head | #7fd3e8 | +| Later entry tick/caption during inspection | #5d666e | +| Later minor mark during inspection | #4e565d | +| Selected diamond/junction/ordinal caption | #c9a86a | +| Live head marker/label | #7fd3e8 | +| All other head states | #7b858d | +| SELECTED · HEAD and No recorded checkpoints | #7b858d | + +Later means recorded after the selected ordinal. For a group, use the earlier +entry colour if any represented entry is at/before selection, otherwise the +later-entry colour; apply the equivalent rule separately to minor marks. Merged +entry captions spanning the boundary use the earlier-caption colour. The exact +selected ordinal and drawer retain the distinction between group members. + +Selection wins its diamond, junction and caption colour. Head retains its own +state colour below, including at the same column. Keep PR 1's drawer focus and +selected-row cues. No global focus recolouring, green settled head, success +checkmark or animated progress is implied. + +## Exact-selection drawer wording + +One row per exact marker, in full retained order, including every grouped mark. +N is the full-list checkpoint ordinal; E is admitted entry order: + +| Kind | Exact row wording | +| --- | --- | +| entry | N · Entry E admitted | +| scope | N · Component admitted | +| binding | N · Bindings recorded | +| generated | N · Generated XMD admitted | +| elicit | N · Answer recorded | +| agent | N · Agent turn recorded | +| terminal | N · Entry outcome recorded | + +Use the same category-only labels at live and historical routes, not original +richer labels containing later names or outcomes. Component admitted is not a +completed invocation; Entry outcome recorded is not finished cleanup. The +successful answered-question checkpoint is Answer recorded, not a pending wait. + +Keep marker-based keys, existing semantic selection actions, title History, +focus/selection cues and measured window. PR 2's `[↑ earlier]` / `[↓ later]` +controls reach every exact row. Rows outside the admitted window have no node, +frame target or Tab stop. No hint/legend row consumes capacity. Selection +projects the exact marker or reports the existing refusal; a visual group never +becomes one combined marker action. + +## Frozen structural review checklist + +1. **Authoritative retained identity.** Full navigation and selected content come + from one validated snapshot; full-Journal refusal remains fail-closed. Groups + preserve exact marker identities and never invent durable positions. +2. **Inspection reachability.** Only full marker identity/kind reaches band and + drawer; overall head state reaches band alone. Future payloads, richer labels, + live content and execution capabilities do not enter inspected panes or the + frozen action row through this exception. +3. **Execution ownership.** The session's actual entry task/controller owns live + head facts through complete unwind. Body return/root close cannot release + readiness early; cancellation, failure precedence and actual capabilities + retain their existing owners. +4. **Persistence and reconstruction.** No Journal/sidecar protocol, timing record, + replay execution, provider or source load is introduced for settled cold + inspection. Existing unfinished-run resumption remains its separate policy. +5. **Root and child boundaries.** Rebuildable immutable view data flows down the + direct parent path; typed marker actions flow up. Only the root resolves + selection. Children/renderers hold no Journal, session or control authority. +6. **Mounted targets and measurement.** One prepared measured reading supplies + placement, descriptions and targets. Freedom retains focus; absent narrow + surfaces and off-window drawer rows have no nodes/targets. Grouping does not + redirect an exact checkpoint action. +7. **Resource and concurrency boundaries.** Reuse the existing owned wake/input + paths and rendering lifetimes. Static History introduces no extra host reader, + competing frame subscription, polling loop or resource owner, and no live + observation leaks or revives after session teardown. + +Architecture review uses this checklist on the exact feedback SHA. A distinct +later structural invariant needs an explicit architecture amendment. Product +appearance and ordinary evidence sufficiency remain Planner feedback; CI, +speculative permutations and incidental diagnostic polish do not expand this +architecture review. + +## Planner work, verification and complete-story evidence + +Use the accepted six-step journey in pr3-product-verification.md at all three +profiles: original Plan/README and populated entries; real pause and early +inspection; offscreen owned work; grouped exact selection and shared indicators; +resize/return live/held cleanup; settled cold reopen. Derive companion evidence +for empty/singleton states, success/failure/cancellation, unfinished readings, +navigation payload exclusion, damaged later history and mounted target agreement. + +The plan names concrete sites in program.ts, application.ts, layout.ts and +presentation-style.ts, and projector/session changes only where needed for the +accepted snapshot/ownership facts. Explain the single-snapshot projection flow, +full teardown signal, existing wake integration, engine-measured caption/rail +allocation, ordinal grouping and exact drawer rows. Do not defer these mechanics +to discovery during implementation. If the concrete plan requires a new public +boundary, return that specific choice to the Architect before adding it. + +Candidate focused files are repl-model, repl-execution, repl-journey, +repl-layout-admission, repl-presentation-style and relevant forms regressions. +Choose the smallest discriminating selection, adding known black-box boundaries +explicitly. Name concrete inputs and controlled real operations, not fabricated +head/lifecycle states. Preparation uses setup, never a check that reinstalls. + +Freeze PR 3's finite gallery and meaningful isolated break controls. Include +M9/M10 and the complete assembled original journey, mapping each pair to the +older archive source/scene, hash, profile and feedback SHA. Carry all accepted +terminal adaptations. Keep literal expectations independent of production +palette/role maps. A reviewer opens every final pair and classifies differences; +tests alone do not prove parity. Exact gallery counts, commands and control +sufficiency belong to the Planner. Do not automatically inherit PR 1's 35 count +or the provisional 71-pair baseline as a frozen final oracle. + +After focused evidence passes, create a stable feedback commit promptly and +return its exact SHA, stack base and every actual focused command. Preserve first +failure output and apply repository flake rules where relevant. Exhaustive CI +and delivery gates keep their authority and are separate from architecture +feedback; do not wait for them to supply the feedback revision. + +Update architecture.md and specs/repl-spec.md with implemented behavior in +present tense: the explicit History navigation exception to whole-view prefix +wording; root ownership and thin summary; truthful head/cleanup semantics; +five-row rail, grouping, category drawer and unchanged seven-row footer. Keep +the frozen action row's restrictions. No completed production claim is published +ahead of implementation. + +## Exclusions and next action + +No new persistence, clocks, elapsed/compressed-wait protocol, general tracing, +dependency/vendor change, Core API, extra reader, fork, scrubbing, multiline +editor, automatic drawer or newer reference feature belongs to this slice. +PR 3 preserves PR 2's session-owned middleware authority and cold/prefix rules. + +Next Planner action: freeze conforming PR 2 and PR 3 implementation/evidence +handoffs against their settled contracts, using the actual stack revisions. +The architecture interviews for the original parity slices are complete. +No production change, GitHub mutation, implementation verdict or delivery +approval is issued here. diff --git a/.reviewer/issue-881/pr3-planner-review-r2.md b/.reviewer/issue-881/pr3-planner-review-r2.md new file mode 100644 index 000000000..94661e002 --- /dev/null +++ b/.reviewer/issue-881/pr3-planner-review-r2.md @@ -0,0 +1,97 @@ +# PR 3 Planner re-review at 3fa241dc + +**REQUEST CHANGES.** Reviewed revision **3fa241dccd1ca3128d7026dbdd529efc7b401ef0**, parent f509197bd1998b376b09986b79fce2740568e76f, on `agent/issue-881-pr3`, against accepted PR 2 base acadbbdb4fa7d8c8c86fa85f6657d29c5d95bc3e. The working tree was clean. This is independent implementation feedback, not delivery or publication approval. + +The snapshot/refusal correction, corrected pause sequence and real held-call control satisfy R1–R3. The rendered original-parity gallery also passes visual review. R4's product behavior works in the Planner's live check, but the submitted journey still passes its grouping assertion against two ungrouped positions. Newly committed source and fixtures also need the repository's existing type and resource-ownership rules applied. No persistence, lifecycle API or presentation decision is reopened. + +## R4: compare the selection on the rail, not in its caption + +`pr3-evidence/journey.py:249–266` scans the five rows after `[history]` and returns the first `◆`. Row 2's right-hand `◆ SELECTED · N` caption comes before row 3's actual selected rail mark. The reported column 145 is therefore the caption's column. + +The submitted `grouped-selection` record chooses 18 and 19 because they are the first consecutive Component admitted rows, without first establishing that their marks share a column. In an independent real-command cold reading of the packet's checksummed settled prefix: + +| Profile | Position 18 rail column | Position 19 rail column | Submitted helper's answer | +| --- | ---: | ---: | --- | +| 160×36 | 10 | 11 | 145 for both | +| 120×30 | 7 | 8 | 105 for both | +| 72×20 | 4 | 4 | 57 for both | + +These are zero-based columns. The wide and medium pair is not grouped. The journey's successful equality therefore cannot establish its claim. + +The Planner also selected a real shared pair through the root drawer: 23 and 24, both Component admitted. Their rail columns are 14 at wide, 10 at medium and 5 at narrow. At wide, scrolling the Entries catalog to expose the admitted scopes shows six components for 23 and seven for 24. Both exact selected ordinals remain correct. Position 218 was then selected directly while inspecting; the shared selection/head indicators, History resize through 60×15 and recovery, and return live also passed. This demonstrates working product behavior and supplies a concrete fixture for the repair. + +**Required correction:** constrain the helper to the actual selected-mark row/rail region and choose a consecutive same-category pair that really shares a measured column. Keep the existing exact-prefix content discriminator and later-marker action. Correct the handback's 18/19 “one mark” claim. The new session/renderer regression is useful and can stay; it does not make the root journey's false grouping assertion valid. No sixth mutation control or additional gallery scene is requested. + +Evidence: [live grouped results](pr3-planner-review-r2-evidence/grouped-live/verified-shared-results.json), [original-pair observations](pr3-planner-review-r2-evidence/grouped-live/results.json), and the preserved drivers, logs and ANSI/text/PNG captures beside them. Counts in the initial observation log are only visible catalog rows; the corrected wide check scrolls the catalog before asserting six versus seven. Zero visible rows at smaller profiles are not a claim that their prefixes contain no scopes. + +## R5: apply existing code rules to the newly committed files + +This revision adds production casts at `packages/cli/src/repl/session.ts:577,580`: the memo stores optional whole/prefix/error fields, then asserts both successful payloads with `as ReplModel`. Repository Code Rule 6 requires inferred/narrowed types rather than casts. Represent successful and failed cached projections with types that narrow to their actual payloads; Effection's existing `Result` is available. Keep local names and helper structure as implementation decisions. No new public interface is needed. + +The newly committed `packages/cli/tests/fixtures/repl/issue-881/HistoryGate.ts:51–56` creates `fs.watch` and then yields `ensure()` to register its release. Code Rule 16 explicitly forbids that order: the registration itself suspends, so cancellation there can leave the watcher without cleanup. The same file also introduces an async filesystem helper at lines 31–37 and direct fs promise operations where the repository requires Effection operations and appropriate `@effectionx/fs` operations (Code Rules 1–3). + +`controlled-host.ts:67–68` likewise uses `as string` for validated latch paths and imports direct fs promise operations. Narrow the values into the host operation instead of asserting them, and use the existing filesystem operation boundary where it supplies the operation needed. The controlled-host architecture itself remains accepted: one real installation holds its own teardown, with no fabricated head state. + +**Required correction:** bring the newly committed code under these existing rules. Register cleanup before taking any watcher resource, with its actual release lifetime established. Alternatively, remove the unused HistoryGate probe from shipped test source and retain its historical bytes with the probe evidence. Preserve the controlled teardown fixture that the accepted gallery needs. A focused cancellation/resource check is appropriate if HistoryGate remains executable source; no new visual permutation is needed. + +This is an existing ownership requirement applied to a new resource, not an expansion of the History architecture or the frozen visual matrix. + +## Corrections accepted and evidence reviewed + +- **R1 satisfied:** `session.reading(at)` projects the full file and prefix from one acknowledged-array slice. The root carries the resulting model/navigation pair through resolution, measurement, paint and resize. It no longer takes fresh navigation after a suspending size read. An unreadable admitted history wakes the root and draws the refused view. The admitted duplicate-final-record regression and coherent-pair regression pass independently. +- **R2 satisfied under the Planner's recorded ordering correction:** actual provider work is established, Pause reports PAUSING, work is released while inspecting, both retained and navigation counts grow, and the controller reaches PAUSED with unchanged content/selection. Closing History preserves that hold and offers no historical Continue. Returning live exposes the actual Continue and the entry reaches an outcome. The submitted counts are explicitly compared, rather than merely logged. +- **R3 satisfied:** P1-T4 composes a frame from a genuinely suspended Elicit's session-owned observations. KC3 fails that committed-cell assertion. All five controls retain complete first output, stack locations and equal before/after source hashes. Their mutations and restorations were inspected; the Planner did not rerun the destructive controls concurrently with its live journey. +- **Visual review satisfied at this revision:** all 77 supplied comparison pairs were personally opened through 27 contact sheets. Pane hierarchy, token/source/output roles, lifecycle reading, drawer treatment and the five-row recorded-order rail follow the original reference under the frozen terminal adaptations. Narrow clipping remains the accepted vertical-window behavior. No additional visual defect was found. + +The original R2 section in the handback still says a complete pause means “nothing is outstanding,” says closing History leaves Continue offered while inspecting, and ends at LIVE. The later correction section and executable journey are correct. Update the earlier prose and the corresponding journey/probe explanations to the accepted expansion-walk boundary and the actual PAUSED → return live → Continue → SETTLED result. The four historical probes do not prove that all Effection work must finish before a pause can exist. This is documentation cleanup alongside the two corrections above. + +## Structural checklist + +The seven original-scope production checks were reviewed against the accepted architecture handoff: + +| Check | Assessment | +| --- | --- | +| Authoritative retained identity | One validated snapshot supplies full identities and exact prefix; malformed history refuses. | +| Inspection reachability | Only marker/kind and band head cross; prefix content and historical authority stay isolated. | +| Execution ownership | Actual session/controller state and complete entry unwind supply the head. | +| Persistence and reconstruction | No new protocol, store or replay execution; settled cold reads perform no work. | +| Root and child boundaries | The root resolves the reading; inert data travels down and typed exact-marker actions return. | +| Mounted targets and measurement | Existing engine/Freedom boundaries remain; grouped selection works. R4 repairs its repeatable evidence. | +| Resource and concurrency boundaries | Production History reuses the existing wake/render ownership. R5 repairs the separately committed probe resource's cancellation boundary. | + +No new architecture amendment is needed. R5 is application of the repository's existing code/resource rules, and R4 is the frozen H1 evidence requirement. + +## Independent live journey + +The Planner completed post-commit production-input checks at all three profiles: the original held Plan; Pause and offscreen advance with prefix/selection preserved; unanswered Plan close/reopen; complete original schema traversal; generated source and enclosure; required-field validation and entered values; full README confirmation summary and decisions; the actual written README; settled output/source traversal; warm and cold early-prefix inspection; retained draft; and cold head plus cold selected-location reopening. The populated form additionally survived 60×15 refusal and 160×36 recovery. The controlled production host showed SETTLING while its installation teardown was held, refused another submission, and repainted SETTLED after release without input. + +Cold checks retained the same 47,333-byte / 35-record Journal hash and 8,521-byte / 11-record provider-log hash through head and prefix reopening. The separate copied 218-position history supplied the true grouped selections, later-marker selection and History resize checks above. No source load or provider execution was introduced by the production change; the focused H6 regression covers the source-load counter boundary. + +The drivers used separate owned PTYs, working directories and provider logs, with the normal home and unchanged prepared dependencies. Their distinct first traceback outputs are preserved; the generic failure-image overwrite is disclosed in the driver notes. Reviewer helper corrections are documented in [driver-notes.md](pr3-planner-review-r2-evidence/driver-notes.md): a narrow heading lookup, footer contamination in source comparison, counting a clipped catalog, and a missing helper name inherited from the previous slice. Completed continuation scripts and final logs supply the actual proof; early helper failures are not presented as product failures or silently replaced with green logs. + +## Independent commands and provenance + +Both exact frozen commands were run from the reviewed worktree: + +```sh +deno task test packages/cli/tests/repl-history.test.ts packages/cli/tests/repl-model.test.ts packages/cli/tests/repl-execution.test.ts packages/cli/tests/repl-entries.test.ts packages/cli/tests/repl-layout-admission.test.ts packages/cli/tests/repl-composition.test.ts packages/cli/tests/repl-presentation-style.test.ts packages/cli/tests/repl-journey.test.ts +deno task test packages/cli/tests/repl-source-reading.test.ts packages/cli/tests/repl-forms.test.ts packages/cli/tests/repl-agent-journey.test.ts +git diff --check +git diff --cached --check +``` + +Results: **99 passed / 312 steps**, **19 passed / 111 steps**, no failures; both whitespace gates exit 0. No full-suite, dependency mutation, CI, push or PR work was performed. + +All **558 supplied checksum entries** match. All ten hashes in revision-provenance.json match both committed blobs at 3fa241dc and the working files. The independent copy of the gallery audit reports 77 checked, 0 failed, 76 bands and 70 marked rails. + +The captures preceded creation of the commit object. Their documented source-equivalence claim is accepted for this review together with verified current committed-file identity and the independent post-commit live checks. The hash list was written afterward and is not a contemporaneous capture-start fingerprint; this review does not pretend otherwise. A rerun solely to change capture timestamps is not requested. + +## Next Implementor action + +Correct the R4 evidence helper/claim and R5's newly committed code-rule violations, then return a stable feedback revision with the existing focused commands, five controls and honest packet provenance. Keep the original parity scope, 77-scene/profile pairs and architecture unchanged. Retain the current gallery as reviewed evidence for 3fa241dc; do not silently relabel inherited captures as a later capture run. The before-commit timing caveat alone does not require another journey. + +For this bounded repair, the Planner permits reuse of the 77 visually reviewed pairs at their actual 3fa241dc provenance if changes remain confined to memo typing, capture/probe fixtures, the grouping-evidence helper and explanatory text, without changing rendered behavior. Run the corrected grouped-selection journey against the new feedback commit and retain its actual rail/content captures. Do not recapture all 77 merely to replace a revision label. A change to rendered behavior instead needs its affected visual evidence refreshed. This is an explicit evidence-sufficiency ruling; it adds no gallery scene or mutation control. + +The Planner owns the next re-review and verdict. No delivery authorization is issued. Accepted predecessors remain PR 1 at 080b6ec80ca74e614789e8d2252857ac281df7e5 and PR 2 at acadbbdb4fa7d8c8c86fa85f6657d29c5d95bc3e. + +Review evidence: 853 checksummed files in [pr3-planner-review-r2-evidence/sha256sums.txt](pr3-planner-review-r2-evidence/sha256sums.txt). diff --git a/.reviewer/issue-881/pr3-planner-review.md b/.reviewer/issue-881/pr3-planner-review.md new file mode 100644 index 000000000..3b82f8b36 --- /dev/null +++ b/.reviewer/issue-881/pr3-planner-review.md @@ -0,0 +1,254 @@ +# PR 3 Planner review: request changes + +**REQUEST CHANGES at f509197bd1998b376b09986b79fce2740568e76f.** The measured +History rail and category drawer are substantially in place. Four existing +frozen requirements remain unmet: the root's coherent retained reading, paused +offscreen advancement, the real-invocation lifecycle control, and proof that +same-category grouped actions select different content prefixes. + +This is independent Planner feedback against +[the frozen implementation handoff](pr3-implementation-handoff.md), its H1–H6 +matrix, [the seven structural checks](pr3-planner-handoff.md#frozen-structural-review-checklist), +and [the accepted product journey](pr3-product-verification.md). It adds no +production scope, persistence, public API, gallery scene or CI gate. + +## Reviewed revision and evidence + +Branch `agent/issue-881-pr3`, worktree `.claude/worktrees/issue-881-pr3`, accepted +base **acadbbdb4fa7d8c8c86fa85f6657d29c5d95bc3e**. Product HEAD remained +**f509197bd1998b376b09986b79fce2740568e76f** throughout this review. Three capture +fixtures are staged additions, absent from that commit; their index/worktree +bytes and hashes are retained in +[capture-fixture-provenance.json](pr3-planner-review-evidence/capture-fixture-provenance.json). +The review distinguishes that product revision from its uncommitted capture +inputs. I did not attempt authentication, bypass signing, commit, push, open a +PR or inspect CI. Unlocking 1Password requires the user's local authentication. + +I independently ran both frozen commands, each with exit 0: + +```sh +deno task test packages/cli/tests/repl-history.test.ts packages/cli/tests/repl-model.test.ts packages/cli/tests/repl-execution.test.ts packages/cli/tests/repl-entries.test.ts packages/cli/tests/repl-layout-admission.test.ts packages/cli/tests/repl-composition.test.ts packages/cli/tests/repl-presentation-style.test.ts packages/cli/tests/repl-journey.test.ts +# 97 passed / 308 steps / 0 failed + +deno task test packages/cli/tests/repl-source-reading.test.ts packages/cli/tests/repl-forms.test.ts packages/cli/tests/repl-agent-journey.test.ts +# 19 passed / 111 steps / 0 failed + +git diff --check acadbbdb4fa7d8c8c86fa85f6657d29c5d95bc3e..f509197bd1998b376b09986b79fce2740568e76f +git diff --cached --check +# both exit 0 +``` + +Logs are [main](pr3-planner-review-evidence/focused-main.log) and +[companion](pr3-planner-review-evidence/focused-companion.log). All 545 supplied +checksums matched at the start and end. I opened all 27 contact sheets, covering +all 77 pairs; [the per-sheet record](pr3-planner-review-evidence/gallery-review.json) +names them. The rail hierarchy, separate shared-column indicators, category +rows, drawer bounds, resize recovery, source colours and cold prefix reading +are visually consistent with the accepted adaptations. The offscreen scene is +the exception described in R2. + +The supplied audit also exits 0 when replayed on copied capture text: 77 checked, +76 with the band, 70 with a rail mark. Its offscreen claim omits the required +held head, so that green result does not establish the frozen matrix. I inspected +the five control records and first-failure excerpts rather than rerunning mutations. +All five current production files match both recorded restoration hashes; +[restoration checks](pr3-planner-review-evidence/control-restorations.json) are +retained. KC3's claimed boundary is not the boundary its failing tests exercise. +The three supplied cold reports are byte-identical. H6's independently green +journey also exercises no source load or compilation during settled inspection. + +## R1 — Rebuild the root reading from one snapshot and propagate full refusal + +**Frozen basis:** implementation handoff section 1, H1/H2, structural checks 1 +and 5. The handoff explicitly requires replacing program.ts's selected-only +shortcut, projecting full navigation and requested content from one retained +array, and carrying that immutable reading through paint and resize. A malformed +later segment uses the existing refused view. + +That root change is absent. In `program.ts:774–787`, `reproject()` still returns +without reading when route and model selections match. Otherwise it independently +calls `execution.stream.readAll()` and projects only the requested content. +Navigation comes from `current.navigation` at `program.ts:667/682` and is read +again by `build()` at line 821. The intervening `screen.size()` and frame +preparation suspend. A retained append can therefore move navigation while the +selected model belongs to another snapshot. This is a structural finding from +the actual root path; I am not claiming to have captured that race in a PTY. + +The new session projection at `session.ts:510` does project two models from one +array, but its selection is the opening option, not the root's changing route. +It cannot make the independently projected root content and freshly read +navigation one prepared reading. Its failure path is also incomplete: +`refuse()` at line 451 only answers an unresolved opening. Once admission has +answered, a later projection failure leaves the old model and points in place +and publishes no refusal. Root reprojection errors retain the old model with a +route notice instead of showing the full refused view. + +A [focused probe](pr3-planner-review-evidence/admitted-malformed-probe.mjs) +executes a real Json entry, then appends a duplicate of its real final Close. +This is a malformed sequence of real event data. Both the full projector at the +early marker and a cold reopen refuse it. The admitted session still exposes +its identical old model, identical navigation and old prefix payload, with head +`settled`. [Output](pr3-planner-review-evidence/admitted-malformed-probe.log) +records those observations. The probe checks session data, not rendered cells. + +**Required revision:** implement the already-frozen root snapshot flow. Bind full +navigation, selected content and retained head facts to the same acknowledged +array and reuse that prepared reading during paint/resize. Preserve the existing +live observation/capability suppression while inspecting. Propagate later full +validation failure to the existing refused view; preserve invalid-route-marker +refusal semantics separately. Add discriminating root-drive regressions for a +retained/session wake during inspection and for a malformed later segment after +admission. The cold-only session test is useful but does not reach this boundary. +Keep the documentation's one-snapshot claim aligned with the implementation. + +## R2 — Prove advancement while expansion remains paused + +**Subsequent Planner evidence correction:** [R2 now uses the supported +PAUSING → advance → PAUSED order](pr3-r2-evidence-correction.md). This supersedes +the establish-before-release recipe below. The historical REQUEST CHANGES +verdict at f509197b and the finding against its LIVE offscreen scene remain. + +**Frozen basis:** H3, product journey steps 2–3, and the existing +`offscreen-advance` gallery row's “actual navigation append, same exact +selection/prefix and held head.” + +All three supplied offscreen captures show **HEAD · LIVE**. In `journey.py:639`, +`stage_offscreen()` opens or starts Plan work, selects Entry 1, releases the Plan +provider gate and compares the prefix and selection caption. It never requests +Pause or establishes an expansion hold. Journal line growth proves an append, +but not that navigation updates while a real pause remains established. The +audit's offscreen row checks `[live]` and the selected caption and permits LIVE. +The separate paused-historical captures establish a real pause, but do not +perform the subsequent background append under that hold. + +The focused H3 additions do not fill this gap: their pausing/paused cases feed +booleans to `headOf`; the real-session cases cover empty/live/settling/settled. +The neutral-ending loop also repeats the identical facts for three unused +strings instead of reading separate retained endings. + +**Required revision:** use the already-frozen sibling work/expansion boundary: +start background work, request real Pause, establish the controller hold, +inspect an early prefix, then release work that already started. Assert a real +new retained checkpoint, growth of the full navigation list, unchanged exact +selected content, and the still-paused head. Closing History must leave the +hold in place. Return live, Continue and finish through the actual controller. +Capture the corrected offscreen state at the same three profiles and make the +audit require its held head. Finish the existing H3 companion evidence with +separate retained success/failure/cancellation inputs and an unowned unfinished +reading; do not count the unused-string loop as that evidence. + +The controlled settling host is an acceptable implementation of the frozen +cleanup fixture. Its journey checks SETTLING, submission refusal and release to +SETTLED without input. There is no finding against that evidence, and no need +to replace ordinary CLI Pause scenes that already establish the required state. + +## R3 — Make KC3 fail a frame from a real held invocation + +**Frozen basis:** the five-control table explicitly requires removal of lifecycle +words/glyphs to fail a **real held-call frame**. + +KC3 reports BROKEN, but its named WAITING and EXIT assertions are presentation +unit cases. At `repl-source-reading.test.ts:660/676`, each calls `entryReading` +with `observing([...])` data containing an assigned phase and waiting reason. +No invocation starts or waits. Its other named presentation case likewise +supplies observation data before rendering. These tests discriminate badge +formatting; they do not establish that a held operation reaches the assembled +frame. Calling them real held-call frames overstates the evidence. + +The control runner also discards the captured process output and retains only +an excerpt, stopping before stack locations or after 1,400 characters. The +packet contains those JSON excerpts, not complete first-failure logs. The +from/to mutations identify the patches, but do not replace the prescribed +first-output records. + +**Required revision:** retain those unit tests, and run the existing KC3 mutation +against a committed-cell assertion driven by an actual session-owned held +invocation through production composition. Observe the real wait or cleanup +boundary and assert its glyph/word on that invocation's source row against the +independent reference literals. Record the command, complete first failure and +SHA-verified restoration. Retain complete first-failure output and the mutation +patch for each of the same five controls on the revision. This repairs one of +the existing five controls; it adds no sixth control or new lifecycle design. + +## R4 — Check the content selected by grouped actions + +**Frozen basis:** H1 and product journey step 4 require separate exact prefixes +for two same-category checkpoints sharing one visual group. + +`repl-history.test.ts:493` checks that a one-column group retains two member +markers, without selecting either. H5's root journey clicks a row and checks +only that history mode opens; its small checkpoint list does not crowd the rail. +The supplied crowded journey selects rows 2 and 3 and checks only that their +selection captions differ. Those rows are different categories, and a changing +caption could coexist with unchanged or incorrectly rounded content. + +The [Planner's retained-prefix probe](pr3-planner-review-evidence/crowded-prefix-probe.mjs) +provides a concrete case from the supplied cold snapshot. Positions 28 and 29 +are both component admissions, with markers `entry-5:yield:root:12` and +`entry-5:yield:root:13`. They share a measured group at all three profiles. +Their exact prefixes admit **11 versus 12 HistoryRecord component scopes**. +[Output](pr3-planner-review-evidence/crowded-prefix-probe.log) records the engine +measurements and prefix counts. This probe establishes the fixture and oracle; +it does not exercise drawer actions and is not claimed as the missing UI proof. + +**Required revision:** select such a confirmed same-category pair through the +root drawer actions and check each exact route marker plus the content the +prefix actually admits. For the supplied pair, traverse the Entries windows +and verify the 11-versus-12 admitted component rows, retaining the full later +navigation in both readings. Also select a later marker directly while +inspecting. On a revised fixture, record the equivalent measured pair and its +expected admitted-content difference. Caption changes and group membership +alone are insufficient. No new gallery state is needed; this completes the +existing grouped-history journey and H1 regression. + +## Planner fixture correction and seven-check disposition + +The original crowd recipe was wrong. Multiple Json invocations can publish in +one binding record, yielding one binding checkpoint. Two hundred actual +HistoryRecord Markdown invocations supply the needed real scope checkpoints. +That substitution is accepted. The handoff's H1 case now calls for two +same-category component-admission markers instead of two binding markers; the +same exact-prefix invariant remains. The shared fixture record is corrected. +Authored root source already admitted at both markers is not future payload: +the discriminator is the component content admitted between the two markers. + +| Frozen structural check | Disposition | +| --- | --- | +| 1 Authoritative retained identity | Unmet: R1; grouped exact-action evidence also outstanding in R4. | +| 2 Inspection reachability | The thin detached marker/kind shape and category wording are correct; root coherent-prefix verification remains subject to R1/R4. | +| 3 Execution ownership | Owned-work head derivation and settling evidence are sound; paused background and retained-ending evidence remain in R2. | +| 4 Persistence and reconstruction | No persistence protocol change; focused cold reconstruction evidence passes. | +| 5 Root and child boundaries | Direct downward view data and upward typed marker actions remain; root retained-reading ownership is incomplete in R1. | +| 6 Mounted targets and measurement | Measured rail, mounted drawer/resize regressions and visual evidence pass their placement checks; exact grouped content action remains R4. | +| 7 Resource and concurrency boundaries | No new reader, polling clock or resource owner introduced; existing ownership paths remain. KC3 still owes its prescribed real-frame evidence. | + +I have not completed the independent three-profile live product walk and do not +claim acceptance of that journey. The supplied frames already contradict its +paused offscreen step, so the next live walk must use the corrected sequence. +The green focused runs and visual review above are completed review work, not +a substitution for the remaining live verification. + +## Ready-to-send revision prompt + +Revise PR 3 from f509197bd1998b376b09986b79fce2740568e76f against R1–R4 above. +Implement the frozen root single-snapshot reading and full post-admission +refusal; prove paused background advancement with the actual controller; repair +KC3 to fail a real held-invocation frame; and prove distinct selected content +for a same-category grouped pair through root drawer actions. Use the accepted +HistoryRecord crowd correction. Keep the existing public APIs, persistence, +seven-row footer and original parity scope. + +Run both unchanged frozen focused commands and the endpoint whitespace gate. +Commit the corrected source/tests and the three capture fixtures through the +normal signed workflow as soon as focused evidence passes. Return the exact +SHA, commands, first control failures/restorations, and the same fresh 77-pair +assembled packet from that final unchanged revision. Fix the offscreen audit +claim and report which accepted product steps the journey actually performs. +Do not add gallery scenes or controls. Stop before push or PR creation. + +Continuity: PR 1 and PR 2 remain accepted at their recorded SHAs. PR 3 feedback +is REQUEST CHANGES at f509197b. Produced artifacts are this review, its +[checksummed evidence](pr3-planner-review-evidence/sha256sums.txt), and the two +fixture-wording corrections in the implementation handoff and shared stack +record. Next Implementor action is the revision prompt above. The Planner's +remaining live walk and final accept-or-request-changes follow that handback. diff --git a/.reviewer/issue-881/pr3-product-verification.md b/.reviewer/issue-881/pr3-product-verification.md new file mode 100644 index 000000000..427b6ba9f --- /dev/null +++ b/.reviewer/issue-881/pr3-product-verification.md @@ -0,0 +1,117 @@ +# PR 3: product verification review + +Status: the main journey is accepted by the Product Owner. The interface and +presentation contracts in [pr3-history-contract.md](pr3-history-contract.md) +are accepted. This record describes what the product must show working, not +tests or captures already run. PR 2 remains ready for planning independently. + +## Main journey: inspect an earlier checkpoint while the head advances + +Run at 160×36, 120×30 and 72×20, with the existing normalized input and explicit +drawer activation. Use the original [Plan entry](plan-entry.md), local provider +fixture and [generated README program](generated-readme.md) from PR 2's +accepted journey. Extend the same execution with real additional entry work +that produces enough repeated checkpoints to crowd the measured rail. The +Planner supplies the concrete input and controlled operation boundaries; the +product does not inject a fabricated presentation state or timing record. + +1. **Read the recorded sequence.** Complete the original Plan-to-README entry. + Admit additional work into the same execution. History shows distinct entry + boundaries and minor marks, using recorded-order spacing and the accepted + colours. The band has exactly five rows between the contextual action row + and persistent draft. Type an unsubmitted draft and keep it through the + remaining navigation. There are no seconds, compressed-wait durations or + scrubbing controls. +2. **Pause real expansion and inspect an earlier reading.** Request Pause while + work is active. The head reports PAUSING EXPANSION while the controller is + actually pausing and EXPANSION PAUSED once its holds establish that state. + Use Entries and History to inspect Entry 1 before generated admission. Source + shows its original Plan; later generated source, bindings, rendered output, + questions, permissions, Agent details and live lifecycle statuses stay out + of inspected panes. The frozen action row reads History. The full recorded + rail and category-only drawer rows remain available. +3. **Let owned background work finish offscreen.** Release actual work that had + already started before expansion paused. It may add retained checkpoints + without releasing the expansion hold. History updates its known navigation + list and truthful head state; inspected content stays at the selected marker. + Closing History neither answers a question nor continues expansion. The + diamond and caption still name the exact earlier checkpoint. +4. **Choose exact positions through a crowded rail.** Reach separate drawer + rows whose checkpoints share a grouped notch, using ↑ earlier / ↓ later as + needed. Selecting each changes the prefix to its exact marker, even when + both rows have the same category. The selected ordinal matches its drawer + number. Choose a later marker directly while inspecting; only facts admitted + by that new prefix become readable. Select the last offered checkpoint so + selection and head share a rail column: the amber diamond remains above and + the head marker remains below, with separate colours and captions. Entry + caption ranges name actual entries; no checkpoint loses its drawer action. +5. **Resize and return live.** With a historical selection and a populated + drawer, move through the three profiles and back. Grouping recalculates from + engine measurements while marker identity, draft, route and focus follow the + established admission/window rules. At narrow, only its routed surface and + admitted drawer exist. Return live, Continue the actual held expansion and + finish the remaining work. The current source/output and process lifecycle + reading return. Hold owned cleanup after the retained root outcome: History + says SETTLING until cleanup completes, then SETTLED in the neutral colour. + Head-state-only changes neither reflow the rail nor cover selection. +6. **Reopen the retained readings cold.** Close the settled session and reopen + its head and earlier selected location, including the retained draft. History + reconstructs the same checkpoint identities/order, grouping at each profile, + category labels, colours and head/selection relationship. Earlier inspected + content stays prefix-correct. No provider, component-source load, write or + reconstructed live lifecycle badge is needed; Journal bytes and provider + activity remain unchanged. Process-local window offsets begin at their + established initial position. + +This journey fails if the rail is a relabelled checkpoint list, inspecting +removes later navigation positions, grouped checkpoints become one action, +selection and head collapse into one indicator, source/output borrows later +content, a recorded root close announces finished cleanup, resize changes the +selected marker, or cold reconstruction runs the document again. + +**Decision: accepted.** The Product Owner accepts this six-step journey at all +three profiles, including real pause/offscreen work, exact grouped selection, +shared head/selection placement, resize, held cleanup and settled cold reopen. +Companion checks derive from the accepted contracts. This approves product +verification, not an implementation verdict or fixed gallery count. + +## Companion coverage derived from accepted contracts + +These cases give accepted states and boundaries discriminating evidence. They +do not introduce new product choices or another required journey interview. +The Planner chooses concrete fixtures and focused commands. + +| Accepted behavior | Observable evidence | Incomplete result caught | +| --- | --- | --- | +| Empty history has no fabricated checkpoint | Empty view says HEAD · EMPTY and No recorded checkpoints, with no rail tick or drawer marker target. | A synthetic initial event or selectable empty mark. | +| Non-live head states remain neutral | Separate retained success, failure and cancellation endings all read SETTLED after owned teardown. An unfinished retained reading with no owned task reads UNFINISHED. | Green success for any terminal close or inferring paused/live from incomplete history. | +| One checkpoint and shared positions remain distinct | Read a singleton rail and an inspected latest checkpoint with selection/head at the same column. | Division-by-zero placement, a hidden indicator or a combined marker. | +| Later navigation carries only identities and categories | Inspect before later binding, answer and Agent records, then open the full drawer. No future payload or original richer checkpoint label appears there. | Passing the head model into inspected panes or copying labels into the navigation summary. | +| Full-Journal validation precedes any navigation reading | A damaged later segment causes the existing reconstruction refusal even when the requested marker is earlier. | A plausible prefix paired with stale or partial full navigation. | +| Measurements and mounted targets agree | Crowded marks, merged captions and the longest head label fit at every supported profile; drawer rows outside its window have no nodes or targets. | Character-count placement, overlapping captions or invisible actions. | + +An unfinished reading without an owned task is a derived-state case. This +contract adds no cold-open mode that disables the REPL's existing resumption. +If an existing reopen actually starts owned work, its head state describes that +real process. Cold immutability in the main journey uses a settled execution. + +## Planner evidence boundary + +Use the older corrected archive, SHA-256 +86be64318121546f3208342edaf17f0a3aed35f3fde2766b523423e6c708c77b. +The accepted terminal adaptations govern comparison with the older History +studies. Map M9/M10 and the complete original journey to reference scenes; +do not import elapsed-time claims, new features or the newer Downloads archive. + +The Planner freezes the finite final gallery, focused tests and meaningful +isolated break controls under the ready +[PR 3 handoff](pr3-planner-handoff.md). The proposed matrix is +a source for that plan, not an independently frozen oracle. Independent literal +colour expectations and original archive/profile/commit provenance remain +required. Review every final pair; classify each difference as an approved +adaptation or unmet criterion. Tests do not replace that visual review. + +Preserve PR 1's accepted SHA and 35-pair evidence as historical slice feedback. +PR 3 supplies the complete-story comparison on the actual assembled revision; +it does not retroactively change the PR 1 verdict or assume PR 2 code is accepted. +Focused feedback commits and delivery/CI verification remain separate. diff --git a/.reviewer/issue-881/pr3-published-architecture-review.md b/.reviewer/issue-881/pr3-published-architecture-review.md new file mode 100644 index 000000000..dddb8b620 --- /dev/null +++ b/.reviewer/issue-881/pr3-published-architecture-review.md @@ -0,0 +1,132 @@ +# PR 3 architecture review — #887 + +**PASS** on `a9905f3cb93970206f06468164a7aa9021ad87d5`. +The recorded-order History rail preserves the accepted navigation, retained +identity, inspection and measured-frame boundaries. No architecture blockers +remain at this commit. + +## Reviewed boundary + +Reviewed [PR #887](https://github.com/taras/executable.md/pull/887) on 2026-10-10 +against main `9fe494d78d1b2f65d8efb12fffae5ea68da6c17b`. Its exact parent is +`525415f739fc0dc0be530fa1528ea5830689af88`. The PR head and base were checked +again during verification and remain unchanged. + +#885 and #886 have merged. Main's #886 squash tree is byte-identical to +`ecca5c459b77bed653bcdeab5efd4f9ab656bb2e`, the accepted PR 2 correction. +The published PR 3 tree differs from accepted Planner feedback +`05ba70d567cb80be4bfdea67e7ae0267376e2376` only in the three previously reviewed +PR 2 files: the lifecycle test cleanup, component failure reconciliation and its +regressions. All PR 3 implementation bytes match the accepted feedback. + +The actual tree delta against current main contains 20 files. The branch still +has the earlier stack ancestry; the hosting service's merge-base file listing +includes predecessor changes. This review uses the current main tree and +explicit predecessor comparisons to distinguish the slices. + +#889 depends on this exact #887 head and changes overlapping private REPL +fitting/application code. It is subsequent work, not a dependency or part of +this verdict. The separate #805 session-rendering proof retains its test-only +boundary. No newer reference feature enters the original #881 contract. + +Authority: [pr3-history-contract.md](pr3-history-contract.md), +[pr3-planner-handoff.md](pr3-planner-handoff.md), and +[pr3-implementation-handoff.md](pr3-implementation-handoff.md), including the +recorded pause-evidence correction. The seven structural checks remain frozen. + +## Structural findings + +1. **Retained identity and one snapshot.** `session.reading(at)` builds the + full validated model and selected prefix from one acknowledged-array slice. + Its cached Result narrows the pair together. The root carries that reading + through resolution, measurement, paint and resize; it does not fetch fresh + navigation after a suspending size read. Later malformed records refuse + earlier readings too. The admitted-session refusal path wakes the root and + selects the refused view, which has an empty model and navigation. + +2. **Inspection reachability.** Navigation copies and freezes only marker and + kind. Generic drawer wording derives checkpoint and entry ordinals from + that thin list rather than future labels or payloads. Head state is consumed + by the band. Other panes retain the prefix model and historical live-overlay + suppression; the historical action row receives no new execution controls. + +3. **Execution ownership.** Head derivation uses full retained entry/outcome + facts plus the actual session-owned liveness and expansion controller. + Retained outcome with owned teardown remains SETTLING; success, failure and + cancellation become neutral SETTLED after release. Missing outcome without + owned work is UNFINISHED. The existing entry finalizers, submission slot, + cancellation and fatal-precedence correction retain their owners. The band + supplies no execution capability. + +4. **Persistence and reconstruction.** History adds no durable event, sidecar, + timestamp, protocol, source load or provider call. Settled cold inspection + projects retained facts and uses the same grouping. Existing unfinished-run + resumption remains a separate session policy. + +5. **Root and child flow.** The root resolves exact marker selection. Immutable + navigation passes through the application view to History composition; + drawer actions carry their original marker back up. The full model remains + private to projection, and neither band, drawer nor renderer acquires a + Journal, session or controller handle. + +6. **Measurement and mounted targets.** The engine measures caption widths + before rail allocation. Grouping changes visual membership and placement, + never checkpoint identity. Every checkpoint retains its own drawer action. + The prepared rail supplies inert text/roles through existing frame assembly; + it mounts no actions or pointer targets. Drawer windows and absent narrow + outlets retain measured admission and mounted-tree ownership. Resize + preparation reuses the resolved reading and revalidates terminal size before + reconciliation; Freedom retains focus. + +7. **Resources and concurrency.** Rebuilds use the existing session/controller + wakes. History introduces no production host reader, polling loop, frame + subscription or observer owner. Existing scope-owned input/frame lifetimes + and session teardown remain intact. The controlled teardown fixture holds a + real installation's cleanup rather than fabricating a head state. + +The architecture and REPL specification changes describe the explicit History +navigation exception and preserved prefix restrictions. No new architecture +decision or amendment is needed. + +## Independent focused evidence + +Prepared an isolated detached worktree at the exact reviewed head with +`deno task setup`, then ran both unchanged frozen commands: + +```sh +deno task test packages/cli/tests/repl-history.test.ts packages/cli/tests/repl-model.test.ts packages/cli/tests/repl-execution.test.ts packages/cli/tests/repl-entries.test.ts packages/cli/tests/repl-layout-admission.test.ts packages/cli/tests/repl-composition.test.ts packages/cli/tests/repl-presentation-style.test.ts packages/cli/tests/repl-journey.test.ts +# exit 0 — 99 tests / 312 steps +deno task test packages/cli/tests/repl-source-reading.test.ts packages/cli/tests/repl-forms.test.ts packages/cli/tests/repl-agent-journey.test.ts +# exit 0 — 19 tests / 111 steps +git diff --check 9fe494d7 a9905f3c +# exit 0 +git diff --exit-code ecca5c459b77bed653bcdeab5efd4f9ab656bb2e 9fe494d78d1b2f65d8efb12fffae5ea68da6c17b +# exit 0 — accepted predecessor tree matches main +``` + +Total: **118 tests / 423 steps**, all passing. Saved outputs: +[History and root journeys](evidence/pr887-architecture-focused.log) and +[source/forms/Agent regressions](evidence/pr887-architecture-regressions.log). +The isolated checkout `/private/tmp/xmd-pr887-architecture-review` remains clean. + +The focused cases exercise same-category grouped selection with distinct +prefixes, full navigation beside earlier content, malformed later records before +and after admission, actual session head/cleanup, mounted window/resize behavior +and settled cold reconstruction without provider/source activity. + +[Planner acceptance](pr3-planner-acceptance.md) supplies the independent visual +review of all 77 pairs, five control records and actual live selection/teardown +evidence. Its documented source-equivalence and corrected wide grouping counts +remain attached to their actual revisions. This review neither recaptured the +gallery nor reclassified earlier captures as captures from the published head. +Product appearance and ordinary evidence sufficiency remain Planner feedback. + +No production changes, GitHub review publication or CI inspection were performed. + +## Continuity + +PR 3 architecture review is complete at `a9905f3c`. The original three parity +slices now have architecture acceptance at their recorded revisions. This +review performs no merge, closes no issue and does not cover dependent #889. +The delivery and publication boundaries remain separate from this architecture +verdict. diff --git a/.reviewer/issue-881/pr3-r2-evidence-correction.md b/.reviewer/issue-881/pr3-r2-evidence-correction.md new file mode 100644 index 000000000..80f96b20c --- /dev/null +++ b/.reviewer/issue-881/pr3-r2-evidence-correction.md @@ -0,0 +1,82 @@ +# PR 3 R2: corrected pause evidence order + +**Use the proposed PAUSING → retained advance → PAUSED sequence for R2.** The +Planner accepts this fixture correction. The previous requirement to establish +a complete pause before releasing the Plan provider was my ordering error. +This decision changes the evidence sequence, not the expansion controller or +History's product behavior. It is not acceptance of the uncommitted revision +or the gallery being rebuilt. + +## Why this is the correct boundary + +The unchanged controller in `packages/cli/src/repl/expansion.ts:217–231` reports +paused only when at least one expansion walk is active and every active walk +is satisfied: it holds a continuation or delegates to active children, and all +those children are satisfied. A walk suspended inside an already-started +provider operation has not necessarily reached such a gate. Requesting Pause +there can correctly remain PAUSING until that operation returns. + +This is already covered by `repl-execution.test.ts`'s “P1: the Journal advances +after pause is requested and before it takes effect.” That regression requests +Pause against an in-flight operation, observes pausing, releases the operation, +then checks a longer Journal and a paused controller. It passed in the Planner's +independent focused run at f509197b. The source and that result are retained in +[the correction evidence](pr3-r2-evidence-correction-evidence/sha256sums.txt). + +The Implementor's four PTY probes support this behavior for their tested shapes. +I read those reports; I did not independently repeat the timings. They do not +establish the broader claim that paused means “nothing is outstanding,” or +that only a question can produce a paused state. Pause describes expansion +walks, not all Effection work or resource lifetime. Keep the existing head-state +and entry-wide liveness contracts intact. No controller change is requested. + +## Frozen R2 evidence sequence + +Use the real command and its actual controller at each existing profile: + +1. Start Plan work behind the provider gate. Establish from the provider's own + log that it has received the request and has not returned it. +2. Request Pause and observe HEAD · PAUSING EXPANSION. Select the early marker + while that request remains outstanding. Record the exact selection, selected + content, retained record count and complete navigation checkpoint count. +3. Release the already-started provider work through the harness, without + answering, continuing or submitting from the inspected view. Let its records + append and the expansion walk reach its actual hold. +4. Require both retained-record growth and **navigation checkpoint growth**, + unchanged exact selected content and selection, and HEAD · EXPANSION PAUSED. + Capture the existing `offscreen-advance` state at 160×36, 120×30 and 72×20. + Its audit requires the paused head and rejects HEAD · LIVE. +5. Open and close History while still inspecting. Require that the paused head, + selected prefix and selection survive. Historical controls remain read-only; + do not require or introduce a mounted Continue action there. +6. Return live. Now require the real Continue action, activate it through the + controller and finish the entry. Closing History alone releases no hold and + answers no question. + +The checkpoint counts need an explicit `after > before` assertion. Recording +both numbers does not prove growth. The rebuilding journey inspected for this +correction recorded those numbers without comparing them, and checked for +Continue before returning live. Correct those two checks as part of R2; neither +changes an acceptance criterion or adds a gallery scene. + +This replaces the establish-before-release fixture order in R2 of +[the previous review](pr3-planner-review.md), the H3 evidence recipe and the +Planner's realization of product-journey steps 2–3. It does not claim that +background progress occurred after an already-established full pause. The +accepted visible outcome remains a truthful transition through PAUSING to PAUSED, +complete advancing navigation beside unchanged historical content, and real +controller authority only at the live route. + +The finite matrix remains 77 pairs and five controls. H3's separate retained +success/failure/cancellation and unowned unfinished evidence remains required. +R1's snapshot/refusal boundary, R3's real held-invocation control and complete +failure records, and R4's same-category exact-content actions are unchanged. + +Continuity: accepted PR 2 base is acadbbdb4fa7d8c8c86fa85f6657d29c5d95bc3e; +last reviewed product commit remains f509197bd1998b376b09986b79fce2740568e76f. +The current source is uncommitted and the gallery is rebuilding. Produced +artifacts are this correction, its retained evidence, and aligned wording in +the Planner's handoff, stack and gallery records. Next Implementor action: +finish the corrected sequence and existing final verification, then hand back +a stable signed revision and its exact 77-pair packet for independent review. +No new implementation verdict is issued here. diff --git a/.reviewer/issue-881/pr4-implementation-handback.md b/.reviewer/issue-881/pr4-implementation-handback.md new file mode 100644 index 000000000..f912f6b8c --- /dev/null +++ b/.reviewer/issue-881/pr4-implementation-handback.md @@ -0,0 +1,199 @@ +# REPL typing and focus responsiveness — implementation handback + +**Revision `6f5f150a`** (evidence corrections R1 and R2), superseding +`06080c640d5cae1fe96c355045177a462dcc040a`. Branch +`agent/issue-881-pr4`, worktree `.claude/worktrees/issue-881-pr4`, based on +`05ba70d567cb80be4bfdea67e7ae0267376e2376` (#881 PR 3, accepted). One signed +commit; `git status --porcelain` is empty. PR #887 and the rest of the stack +are untouched. Nothing pushed, no PR opened. + +## What is reused, and what invalidates it + +**Reading geometry.** `prepareReading` is split in two. `fitGeometry` performs +every engine render and answers where each logical line is cut and how wide +each piece measured; `decorate` builds the rows from the lines as they stand +now. A `ReplFitStore` created in `runReplProgram`'s own scope holds the last +geometry together with the inputs it came from, and is threaded into +`prepareFrame` and `commitReplFrame` as an optional parameter, so the test +fixtures that prepare a frame keep measuring everything. + +Reused when the `(text, depth)` sequence of the lines, the available room and +the terminal size are all unchanged. Invalidated by any of: a line's text, a +line's depth, the line count or order, the room, the terminal size. Inputs are +compared element-wise rather than digested. + +**Not** part of the geometry, and therefore re-derived every frame: rails, +badges, token roles, selection and `inspected`. A phase settling or a position +being inspected shows immediately over cuts measured once — which is what +keeps live lifecycle and head state fresh without a Journal append. + +**Measurement before an action.** `act()` prepared a whole frame before every +dispatched action and read one field of it. The reducer reads that admission +in four branches only, so `readsGeometry` — exported beside `reduceRepl`, +where a fifth reader would be written — now gates the preparation. Typing and +erasing skip the `build()`, the `screen.size()` read and the whole +`prepareFrame`. + +**Focus.** A traversal already moved focus in the tree before the loop looked. +`act()` now settles `focused` when the dispatch outcome is a focus move, so +the one frame is composed with the focus that is actually held. The +post-commit correction remains as the safety net, and startup's unconditional +second paint became the same question. + +## Before and after + +Two boundaries, labelled as such. The first review was right that the original +table measured only one of them. + +**Complete frames**, the production commit path — measure, admit, reconcile, +draw — with the **parent revision as the baseline**, both runs from +`pr4-evidence/frame-measure-*.ts` against their own worktrees: + +| Selected reading | `05ba70d5` first frame | `05ba70d5` after a keystroke | `6f5f150a` first frame | `6f5f150a` after a keystroke | +| --- | ---: | ---: | ---: | ---: | +| 12-line entry | 127 measures | **127** | 127 measures | **5** | +| 222-line entry | 2247 measures | **2247** | 2247 measures | **5** | + +Five is the fixed cost a complete frame always pays — three structural +measuring passes, the rail, and the drawer preview when one is open. It is the +same number for twelve lines and for two hundred and twenty-two, which is the +property RS2 asserts. + +**Source fitting alone**, `prepareReading` called directly, the same build with +and without a store (`pr4-evidence/measurements.txt`). Counts are per +keystroke after warmup and every fit is checked before it is counted or timed: + +| Reading | Size | Without a store | With one | +| --- | --- | ---: | ---: | +| 1-line entry | 160×36 | 15.0 measures, 0.83 ms | **0, 0.03 ms** | +| 12-line entry | 160×36 | 119.0 measures, 3.71 ms | **0, 0.19 ms** | +| 12-line entry | 72×20 | 128.0 measures, 1.67 ms | **0, 0.06 ms** | +| 222-line entry | 160×36 | 2265.0 measures, 59.69 ms | **0, 1.14 ms** | +| 222-line entry | 72×20 | 2524.0 measures, 29.44 ms | **0, 0.97 ms** | + +Through the real command, `pr4-evidence/walk.py` at both sizes with a +200-component entry selected, input-to-present timed from outside by piping +the pane — so it includes the tmux round trip and the frame cadence: + +``` +160x36 draft keystroke n=14 median 19.1 ms worst 26.9 ms +160x36 focus traversal n=8 median 17.7 ms worst 21.2 ms + 72x20 draft keystroke n=14 median 19.9 ms worst 27.6 ms + 72x20 focus traversal n=8 median 17.0 ms worst 22.0 ms +``` + +## Focused commands and results + +``` +deno task test packages/cli/tests/repl-source-reading.test.ts \ + packages/cli/tests/repl-presentation-style.test.ts \ + packages/cli/tests/repl-layout-admission.test.ts \ + packages/cli/tests/repl-entries.test.ts packages/cli/tests/repl-forms.test.ts +→ ok | 52 passed (218 steps) | 0 failed + +deno task test packages/cli/tests/repl-journey.test.ts \ + packages/cli/tests/repl-agent-journey.test.ts packages/cli/tests/repl-terminal.test.ts +→ ok | 56 passed (146 steps) | 0 failed + +deno task test --changed +→ ok | 140 passed (565 steps) | 0 failed + +git diff --check → exit 0 +oxlint packages/cli/src/repl packages/cli/tests → 7 errors, all pre-existing in + repl-lifecycle.test.ts; none in any file this change touches +``` + +New test files: none — the regressions join existing suites, so they are +already in all three runtime jobs. Checked anyway, because the counting +renderer is new: `repl-source-reading.test.ts` passes under Node (36 tests) +and Bun (36 pass, 0 fail), and `repl-entries.test.ts` under Node (66 pass). + +What each regression proves: + +- **RS2** (`repl-presentation-style.test.ts`) — *integrated, complete frame.* + Two commits through `commitReplFrame` against one real tree and engine pair, + differing only in the draft. The second costs the same for a 12-line and a + 222-line reading, that cost is above zero (it is a whole frame, not the + fitter alone), and it is under a tenth of what the first frame paid. This is + the assertion that fails when production stops threading the store. +- **RS3** (`repl-journey.test.ts`) — *integrated, through the real loop.* + Typing, erasing, Tab and Backtab beside a selected 12-line and 222-line + entry each read the terminal size exactly four times: the too-small check, + the resolution, the frame's measurement and its revalidation. A fifth read + is an action answered with a frame measured before it ran. This is the + assertion that fails when the gate is bypassed at its call site. +- **S5** (`repl-source-reading.test.ts`) — *isolated fitter.* A 222-line + reading costs >100 measures once and **0** for the next three frames, with + freshly built line objects each time; a phase arriving measures nothing and + still draws the new badge. Four invalidation cases move **one input each**, + with the exact inputs warmed immediately before: depth alone, room alone, + terminal size alone, one line's text alone. Each asserts that measurement + happened *and* that the result equals a freshly measured fit — rows, widths + and recovered text — and, where the input changes the shape, that it differs + from the warmed one. +- **EU2** (`repl-entries.test.ts`) — all 24 action kinds reduced with and + without a real admission; anything whose answer differs must be a geometry + action, at least one does, and `type` and `erase` specifically do not read + geometry. +- **RS1** (`repl-journey.test.ts`) — Tab and Backtab move the cue and the + focus and present exactly one frame each. + +## The mutation controls + +`pr4-evidence/.controls.py` against the committed worktree; each restored and +SHA-verified, complete output per control in `.controls-output/`. The runner +requires a control to break **the test it names**, so a suite failing for an +unrelated reason cannot make a mutation look effective. + +| Control | Outcome | First failing step | +| --- | --- | --- | +| `KR1-no-reuse` — the store is never consulted | BROKEN | `measures nothing again when only the draft beside it moved` | +| `KR2-measure-everything` — the gate answers yes for a keystroke | BROKEN | `answers every other action identically with and without an admission` | +| `KR3-focus-lags` — focus settles after the paint again | BROKEN | `RS1: Tab moves the cue and the focus, and presents once` | +| `KR4-gate-bypassed` — the gate's own call site always prepares | BROKEN | `RS3: … read the size a fixed number of times` | +| `KR5-store-not-threaded` — `prepareFrame` stops passing the store | BROKEN | `RS2: costs the same whether the selected reading is short or long` | +| `KR6-depth-ignored` — the depth comparison is dropped | BROKEN | `measures again when only the depth changed, and cuts for the new depth` | +| `KR7-size-ignored` — the size comparison is dropped | BROKEN | `measures again when only the terminal size changed` | + +KR5 is the one that shows the integrated regression reaches something the +isolated one cannot: with the store unthreaded it fails RS2 while S5's direct +fitter tests still pass (`15 passed (83 steps) | 1 failed`). + +## The removed read, and J2's adjusted premise + +Gating `act()` removes one `screen.size()` read per non-geometry action. That +shifted `J2: a window dragged while a frame is being prepared keeps the +command`, which arms its drag on an absolute read count. + +Confirmed from the call sequence rather than from the test going green. With +the five size-read sites in `program.ts` instrumented, one keystroke now +reads: + +``` +too-small-check → drawnAt → measurement → revalidation +``` + +`SIZE act` no longer appears, which is the removed read. The **third** read is +the one the frame is measured against, so a drag armed there answers it with +the old size and leaves the new one for the revalidation to find — the same +boundary the row describes. It was the fourth while every action also measured +a frame before reducing. + +Changed in the test: the constant `4` → `3` and its comment, which now states +which read that is and why. **Every assertion is untouched**; the diff for that +file is one constant, the comment, and the new RS1 case. + +## Remaining measured cost + +The engine work for an unchanged reading is zero, but a keystroke beside a +222-line entry still costs ~1.1 ms, and that part does grow with the entry: +`readingLines(readingOf(view))` rebuilds the whole reading tree every frame, +and `decorate` builds a row object per visual row. Neither touches the engine. + +I did not cache either, per requirement 4: the measurements do not justify it +at 1.1 ms, and the reading tree is where live phases come from, so retaining +it is a different and riskier invalidation problem than retaining geometry. +The History rail was left alone for the same reason — `prepareRail` is one +batched render and did not appear in the remaining cost. + +Nothing pushed. No PR opened or updated. Delivery verification remains separate. diff --git a/.reviewer/issue-881/pr4-planner-acceptance.md b/.reviewer/issue-881/pr4-planner-acceptance.md new file mode 100644 index 000000000..0b631867f --- /dev/null +++ b/.reviewer/issue-881/pr4-planner-acceptance.md @@ -0,0 +1,55 @@ +# REPL responsiveness — Planner acceptance + +**PASS at `6f5f150a630774d207ae3688f29f93834c08abdd`.** + +This closes R1 and R2 from `pr4-planner-review.md`. The accepted implementation base is `05ba70d567cb80be4bfdea67e7ae0267376e2376`; the follow-up contains signed commits `06080c640d5cae1fe96c355045177a462dcc040a` and `6f5f150a630774d207ae3688f29f93834c08abdd`. The revision changes tests only relative to the first feedback commit. The implementation worktree is clean. + +## What is accepted + +The running command owns one geometry store. It reuses fitted cuts when the text/depth sequence, measured room and terminal dimensions agree, and derives current decoration from current reading lines. Live lifecycle observations, head derivation, coherent history readings, refusal behavior and persistence boundaries remain unchanged. + +Non-geometry actions skip pre-action preparation. Traversal focus is read before composition, removing the redundant paint while retaining post-commit focus correction and reveal handling. The previously accepted J2 read-count adjustment stands. + +R1 is closed. RS2 observes complete commits against a real mounted tree and engine pair, and compares short and long selected readings after a draft change. RS3 observes the real command loop for typing, erasing, Tab and Backtab at both entry lengths. KR4 bypasses the gate at its production call site and fails RS3 with five size reads instead of four. KR5 removes the store argument at the preparation-to-fitting boundary and fails RS2, while the direct fitter checks remain green. These reach the wiring the earlier isolated evidence did not. + +R2 is closed. Each invalidation case warms the exact inputs, changes only depth, room, size or one line's text, observes new measurement work and compares the resulting fit with a fresh unretained fit. Depth and size have separate mutation controls that fail their own named assertions. + +## Independent verification + +From `.claude/worktrees/issue-881-pr4`: + +```text +deno task test packages/cli/tests/repl-source-reading.test.ts \ + packages/cli/tests/repl-presentation-style.test.ts \ + packages/cli/tests/repl-layout-admission.test.ts \ + packages/cli/tests/repl-entries.test.ts packages/cli/tests/repl-forms.test.ts +52 passed / 218 steps; exit 0 + +deno task test packages/cli/tests/repl-journey.test.ts \ + packages/cli/tests/repl-agent-journey.test.ts packages/cli/tests/repl-terminal.test.ts +56 passed / 146 steps; exit 0 + +git diff --check 05ba70d5 HEAD +exit 0 +``` + +The packet's SHA-256 manifest verifies all 30 listed files. The seven recorded controls fail their named assertions, and the restored-file hashes match current production bytes. The reviewer inspected their mutations and complete failure records; mutations were not rerun against the implementation worktree. + +The reviewer reran both supplied complete-frame measurement scripts, each from its own revision's worktree with `deno run --allow-all --node-modules-dir=manual --cached-only --frozen --config deno.json