wiki-viewer 2.16.0 → 2.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +4 -4
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/agent/activity/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/events/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/move/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/search/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/settings/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/sidecar/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/app-proxy/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/assets/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/pdf/save/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/share/[token]/asset/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/share/[token]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/share/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/browse/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/reveal/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/branch/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/refresh/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/workspaces/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/upload/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/app/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/backlinks/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/content/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/download/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/folder/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/git-branches/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/git-checkout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/git-diff/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/git-file-info/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/git-history/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/git-pull/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/move/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/new-file/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/outlinks/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/page/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/presence/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/scratch/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/search/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/slugs/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/upload/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/watch/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page/react-loadable-manifest.json +4 -5
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/s/[token]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/signin/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ltsov-._.js +1 -1
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_system_workspaces_[id]_open_route_actions_1087xu7.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/0.u4_next_0kf.7hj._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/0.u4_next_dist_0xugq-k._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/12y~_mermaid_dist_chunks_mermaid_core_chunk-5ZQYHXKU_mjs_0z1.978._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/12y~_mermaid_dist_chunks_mermaid_core_chunk-KSCS5N6A_mjs_0v4oeem._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_01eqklo._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0858xdh._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0k6g8yo._.js +3 -3
- package/.next/standalone/.next/server/chunks/ssr/_0sr4wj.._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules__pnpm_06613~i._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules__pnpm_0o~d81.._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules__pnpm_0szp2v0._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/static/chunks/0.5ywu7_j899v.js +12 -0
- package/.next/standalone/.next/static/chunks/{0tjcc1wg-57l1.js → 065s1_n.1k11t.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0y~5s_skz1l9a.js → 0ccw-uc_3ao.w.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0ii.akeq7k4pf.js → 0f8kfd9d6kq0b.js} +1 -1
- package/.next/standalone/.next/static/chunks/0lsw6lsaj7lby.js +1 -0
- package/.next/standalone/.next/static/chunks/0rpxacw15~o7k.js +12 -0
- package/.next/standalone/.next/static/chunks/{0r7d-1tq61fa1.js → 0s2h7kvkrtq~p.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0enm-3xy21jcx.js → 0tzi1~wpigp2y.js} +2 -2
- package/.next/standalone/.next/static/chunks/117dkzyg4c~us.js +1 -0
- package/.next/standalone/.next/static/chunks/{0j7kp7w2oum68.js → 11pa_9ucyrzh9.js} +1 -1
- package/.next/standalone/.scratch/tweak-running-app/craft-checklist.md +52 -0
- package/.next/standalone/.scratch/tweak-running-app/issues/01-isolated-origin.md +108 -0
- package/.next/standalone/.scratch/tweak-running-app/issues/01-runtime-containment.md +18 -0
- package/.next/standalone/.scratch/tweak-running-app/issues/02-injection-transform.md +18 -0
- package/.next/standalone/.scratch/tweak-running-app/issues/02-tracer-bullet.md +48 -0
- package/.next/standalone/.scratch/tweak-running-app/issues/03-accept-carbonize-mutator.md +19 -0
- package/.next/standalone/.scratch/tweak-running-app/issues/03-run-robustness.md +37 -0
- package/.next/standalone/.scratch/tweak-running-app/issues/04-multifile-safety.md +37 -0
- package/.next/standalone/.scratch/tweak-running-app/issues/04-static-tracer-bullet.md +27 -0
- package/.next/standalone/.scratch/tweak-running-app/issues/05-batch-parity.md +43 -0
- package/.next/standalone/.scratch/tweak-running-app/issues/05-dynamic-node-app.md +22 -0
- package/.next/standalone/.scratch/tweak-running-app/issues/06-remote-transport-bridge.md +20 -0
- package/.next/standalone/.scratch/tweak-running-app/issues/07-retire-bespoke-web-tweak.md +17 -0
- package/.next/standalone/.scratch/tweak-running-app/keep-ticket.md +74 -0
- package/.next/standalone/.scratch/tweak-running-app/mockups.html +305 -0
- package/.next/standalone/.scratch/tweak-running-app/ops1-updated.md +215 -0
- package/.next/standalone/.scratch/tweak-running-app/ops12-continuation.md +44 -0
- package/.next/standalone/.scratch/tweak-running-app/ops22-context.md +84 -0
- package/.next/standalone/.scratch/tweak-running-app/pivot-note.md +25 -0
- package/.next/standalone/.scratch/tweak-running-app/qa-live-engine.ts +104 -0
- package/.next/standalone/.scratch/tweak-running-app/spike.md +256 -0
- package/.next/standalone/.scratch/tweak-running-app/suggest-current-assessment.md +39 -0
- package/.next/standalone/.scratch/tweak-running-app/suggest-inline-interaction-spec.md +320 -0
- package/.next/standalone/.scratch/tweak-running-app/tweak-interaction-spec.md +161 -0
- package/.next/standalone/.scratch/tweak-running-app/two-actions-interaction-spec.md +234 -0
- package/.next/standalone/.scratch/tweak-running-app/unified-live-spec.md +261 -0
- package/.next/standalone/package.json +1 -1
- package/.next/standalone/server.js +1 -1
- package/package.json +1 -1
- package/.next/standalone/.next/static/chunks/04jvwlttwa_sw.js +0 -12
- package/.next/standalone/.next/static/chunks/161kgz.8h.3iq.js +0 -1
- package/.next/standalone/.next/static/chunks/16kzqur8~yg6b.js +0 -12
- /package/.next/standalone/.next/static/{7EbGXTo8ObPhr7UobKARQ → zwUX5EOT_44n1RoB_W9Bo}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{7EbGXTo8ObPhr7UobKARQ → zwUX5EOT_44n1RoB_W9Bo}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{7EbGXTo8ObPhr7UobKARQ → zwUX5EOT_44n1RoB_W9Bo}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
> SUPERSEDED (2026-08-23): the "Ask agent" composer mode, the instruction-comment
|
|
2
|
+
> dispatch/lifecycle, and the pending/answered cards below are NO LONGER in scope.
|
|
3
|
+
> Per user direction there is NO agent-triggering. The re-home is: Comment +
|
|
4
|
+
> Suggest with better UX, plus a Copy-as-prompt surface that serializes EXISTING
|
|
5
|
+
> comments/suggestions. Authoritative current design: ../tweak-running-app/mockups.html
|
|
6
|
+
> + suggest-inline-interaction-spec.md + craft-checklist.md. Keep this file only
|
|
7
|
+
> for the parts still valid (two-actions framing, copy-as-prompt string format,
|
|
8
|
+
> dedup-by-reply reasoning).
|
|
9
|
+
|
|
10
|
+
# Tweak UX ported into Comment + Suggest — interaction spec (OPS-22, rev 2)
|
|
11
|
+
|
|
12
|
+
Reference-only design artifact. Supersedes `tweak-interaction-spec.md` decision A
|
|
13
|
+
(third button — REJECTED). Decisions B/C/D/E of that spec are carried forward and
|
|
14
|
+
re-attached to the two existing actions. Bubble menu stays exactly:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
[ B I U S <> | sup sub | link | 💬 Comment ✎ Suggest ]
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
- **Comment** = talk about this target — to a human *or* to an agent (one-line semantics).
|
|
21
|
+
- **Suggest** = an edit to review — written by a human, *or* arrived from an agent.
|
|
22
|
+
|
|
23
|
+
Nothing in the chrome changes count. What changes is what Comment's composer can
|
|
24
|
+
produce and how Suggest's card can be reached.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 1. The mapping — which ported affordance lives where
|
|
29
|
+
|
|
30
|
+
### Comment absorbs (human → agent intent)
|
|
31
|
+
|
|
32
|
+
| Ported affordance | Where it lands in Comment |
|
|
33
|
+
|---|---|
|
|
34
|
+
| Targeting panel "What should change?" | The comment composer's **instruction mode** (see §2). Same anchor-to-block geometry. |
|
|
35
|
+
| "Ask agent" dispatch | Composer primary button when in instruction mode. Writes `comment.add {kind:"instruction", instructionState:"queued"}` immediately. No queue step. |
|
|
36
|
+
| Copy-as-prompt | Secondary button inside the composer footer, and on every pending/answered instruction card (§3, §7). |
|
|
37
|
+
| Connect-an-agent | Replaces primary-button label in instruction mode when no agent attached; opens AI panel; instruction already persisted so nothing is lost (§7 no-agent state). |
|
|
38
|
+
| Dedup / re-target | Re-targeting a block with a pending instruction opens its existing thread, not a new composer (§6). |
|
|
39
|
+
| Doc-level "N pending" chip | Toolbar chip counts pending **instruction-kind comments**; click jumps to first. Replaces the deleted queue bar's only real value. |
|
|
40
|
+
|
|
41
|
+
### Suggest absorbs (agent → human review)
|
|
42
|
+
|
|
43
|
+
| Ported affordance | Where it lands in Suggest |
|
|
44
|
+
|---|---|
|
|
45
|
+
| The agent's rewrite | Arrives as ordinary `suggestion.add` (replace/insert/delete), reviewed in the existing `suggestion-card.tsx`. No UI change to the card's Accept/Reject mechanics. |
|
|
46
|
+
| Linkage to intent | Card header gains one optional line above the reason: `In response to: "<instruction text>"` when the suggestion carries `fromInstructionId` (open question 2 from prior spec — recommend the explicit field). |
|
|
47
|
+
| Settling the instruction | Accept **or** Reject of the linked suggestion flips the instruction to `answered`/resolved. Agent clarification without a suggestion lands as a reply on the instruction thread instead. |
|
|
48
|
+
|
|
49
|
+
### Volunteered improvement over the "likely shape" in the brief
|
|
50
|
+
|
|
51
|
+
The brief's shape is confirmed, with one sharpening: **Suggest itself stays
|
|
52
|
+
human-only as an entry point.** The bubble-menu Suggest button keeps its current
|
|
53
|
+
meaning (human proposes an edit). The agent never needs an entry point — it
|
|
54
|
+
writes to the sidecar directly. So "Suggest absorbs the agent rewrite" means the
|
|
55
|
+
*suggestion surface* (card + review loop) absorbs it, not the Suggest button.
|
|
56
|
+
This keeps both buttons' semantics single-clause and avoids implying the user
|
|
57
|
+
can click Suggest to summon an agent.
|
|
58
|
+
|
|
59
|
+
Resulting one-liners:
|
|
60
|
+
|
|
61
|
+
- **Comment — "say something about this: discuss it, or tell your agent what to change."**
|
|
62
|
+
- **Suggest — "review a proposed edit: yours, or your agent's answer."**
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 2. One composer, two kinds — the kind picker
|
|
67
|
+
|
|
68
|
+
**Decision: ONE composer. A two-option segmented control at the top of the
|
|
69
|
+
composer, defaulting to the context-appropriate segment.**
|
|
70
|
+
|
|
71
|
+
Not two buttons, not a kind dropdown buried in a menu, not a magic prefix
|
|
72
|
+
("@agent"). A segmented control because: the choice is binary, both options must
|
|
73
|
+
be visible before typing (the user's mental model of *who reads this* shapes
|
|
74
|
+
what they write), and it must be flippable mid-draft without losing text.
|
|
75
|
+
|
|
76
|
+
Default segment rule (resolves the open decision):
|
|
77
|
+
|
|
78
|
+
- **Selection has no agent attached and file is markdown → default "Ask agent" is NOT the default.** Default = **Discuss** (plain comment). Rationale: the dominant, established Comment path pays zero new friction; the instruction path is one click away and its controls (targeting placeholder, footer) teach it on hover.
|
|
79
|
+
- **If the user has used "Ask agent" before in this session** → remember last-used segment for the session. Sticky, not global.
|
|
80
|
+
- Text/code surfaces: same control, same default. Comment pip unchanged.
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
┌─ composer (anchored to block, existing comment geometry) ─────────┐
|
|
84
|
+
│ ┌─────────────┬─────────────┐ │
|
|
85
|
+
│ │ ● Discuss │ ○ Ask agent │ ← segmented, 44px hit, 11px type │
|
|
86
|
+
│ └─────────────┴─────────────┘ │
|
|
87
|
+
│ ┌──────────────────────────────────────────────────────────────┐ │
|
|
88
|
+
│ │ Add a comment… (Discuss placeholder) │ │
|
|
89
|
+
│ │ What should change? (Ask agent placeholder) │ │
|
|
90
|
+
│ └──────────────────────────────────────────────────────────────┘ │
|
|
91
|
+
│ [⎘ Copy as prompt]* ⏎ Comment / ⏎ Ask esc Cancel │
|
|
92
|
+
└───────────────────────────────────────────────────────────────────┘
|
|
93
|
+
* Copy as prompt visible only in Ask-agent mode (see §3).
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Behavioral rules:
|
|
97
|
+
|
|
98
|
+
- Flipping the segment swaps placeholder + primary button label + footer hints. Draft text survives the flip. Flipping Ask→Discuss with text present: keep text, no warning (a plain comment with imperative text is harmless).
|
|
99
|
+
- Flipping Discuss→Ask with text present: keep text, no warning. The text becomes the instruction.
|
|
100
|
+
- Cmd+Enter dispatches per active segment: `kind:"comment"` or `kind:"instruction", instructionState:"queued"`. Immediate persist. No queue, no batch.
|
|
101
|
+
- Outside-click with empty input = cancel (ported unchanged).
|
|
102
|
+
- Read-only mode: Discuss only. Ask-agent is hidden in read-only (writing an instruction implies the agent may later write the doc; surfaces that are read-only for the human should not queue machine edits — keeps one mental rule: read-only = discuss).
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 3. Copy-as-prompt placement
|
|
107
|
+
|
|
108
|
+
Reachable with and without an agent, in three places, always the same string
|
|
109
|
+
format (`Edit the file \`X\` (a Markdown document). Apply these changes:\n\n1. \`<snippet>\`: <instruction>`), always with clipboard-gate + "Show" textarea fallback:
|
|
110
|
+
|
|
111
|
+
1. **Composer, Ask-agent mode** — footer secondary button `[⎘ Copy as prompt]`. Copies draft-as-instruction without persisting anything. This is the true no-agent escape hatch at authoring time. Hidden in Discuss mode (a discussion comment is not a prompt).
|
|
112
|
+
2. **Pending instruction card** (§4) — `[Copy prompt]` button. Available even after dispatch; the durable artifact and the clipboard path coexist.
|
|
113
|
+
3. **Answered/stale instruction card** — same `[Copy prompt]`, for re-asking elsewhere after drift.
|
|
114
|
+
|
|
115
|
+
Numbering: keep `1.` prefix always, one code path (carried from prior spec F.2).
|
|
116
|
+
|
|
117
|
+
**Connect-an-agent placement:** in Ask-agent mode with no agent attached, the
|
|
118
|
+
primary button reads `Connect an agent` and opens the AI panel. Dispatch has
|
|
119
|
+
*already happened on Cmd+Enter* if the user pressed it first — button relabel is
|
|
120
|
+
a CTA, not a gate. The instruction sits queued in the sidecar either way. Copy
|
|
121
|
+
as prompt stays visible beside it.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 4. Chrome without the queue bar
|
|
126
|
+
|
|
127
|
+
No bottom bar. The sidecar is the store. Three pieces of chrome total:
|
|
128
|
+
|
|
129
|
+
**Composer** — as §2. Exists only while open.
|
|
130
|
+
|
|
131
|
+
**Pending instruction card** (block gutter / margin, pip exactly like a comment
|
|
132
|
+
pip, distinct glyph — reuse the instruction styling from `comment-thread.tsx`'s
|
|
133
|
+
"Turn into an instruction" output):
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
┌─ instruction card (pending) ──────────────────────────────────────┐
|
|
137
|
+
│ ✦ you · waiting for your agent │
|
|
138
|
+
│ "Tighten this paragraph, keep the citation." │
|
|
139
|
+
│ Your agent picks this up when it next reads this file. │
|
|
140
|
+
│ [Copy prompt] [Remove] │
|
|
141
|
+
└───────────────────────────────────────────────────────────────────┘
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
No spinner. No fake progress. State line is a true statement about `queued`.
|
|
145
|
+
`sent` state (when lifecycle is driven) swaps the line to "sent to your agent —
|
|
146
|
+
waiting for answer"; chrome otherwise identical.
|
|
147
|
+
|
|
148
|
+
**Answered state** — markdown: the suggestion-card appears inline (existing);
|
|
149
|
+
the instruction card collapses to one line anchored above it:
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
┌─ instruction (answered) ──────────────────────────────────────────┐
|
|
153
|
+
│ ✦ answered — review the suggestion below [Copy prompt] │
|
|
154
|
+
└───────────────────────────────────────────────────────────────────┘
|
|
155
|
+
┌─ suggestion-card (existing, unchanged) ───────────────────────────┐
|
|
156
|
+
│ agent suggests replacing this block │
|
|
157
|
+
│ In response to: "Tighten this paragraph…" │
|
|
158
|
+
│ ─ current ─ / ─ proposed ─ [Accept][Reject] │
|
|
159
|
+
└───────────────────────────────────────────────────────────────────┘
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Text/code answered: reply lands in the instruction thread with fenced code;
|
|
163
|
+
card gains `[Mark done]` (human-settles, no doc write) beside `[Copy prompt]`.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 5. Review loop — confirmed
|
|
168
|
+
|
|
169
|
+
**Markdown (full loop):** agent reads queued instruction → writes
|
|
170
|
+
`suggestion.add` + flips instruction to `answered` → user reviews in
|
|
171
|
+
suggestion-card → Accept pushes block op with `baseRevision` (409 → one retry
|
|
172
|
+
with `getLatestRevision()`, existing behavior) → instruction resolves when the
|
|
173
|
+
suggestion settles. Clarifying questions arrive as thread replies, not
|
|
174
|
+
suggestions. **Confirmed as designed.**
|
|
175
|
+
|
|
176
|
+
**Text/code (degraded, honest):** instruction persists at the lineAnchor; agent
|
|
177
|
+
cannot suggest; answer arrives as a comment reply containing fenced replacement
|
|
178
|
+
lines; user hand-applies. Expectation set **at dispatch time** — footnote under
|
|
179
|
+
the composer's Ask button on non-md surfaces: *"On this file type the agent
|
|
180
|
+
replies with a comment; you apply the change."* **Confirmed.**
|
|
181
|
+
|
|
182
|
+
**HTML iframe:** nothing. Source view only. **Confirmed** (permanently dropped
|
|
183
|
+
with the old engine).
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 6. Re-targeting a block with a pending instruction (no `comment.update`)
|
|
188
|
+
|
|
189
|
+
Three options — picking **reuse the existing thread via a prefilled composer**, with an explicit cost note:
|
|
190
|
+
|
|
191
|
+
| Option | Verdict | Cost |
|
|
192
|
+
|---|---|---|
|
|
193
|
+
| **(a) Reuse thread: open the pending instruction's thread in place of a fresh composer; composer's Ask field prefilled with current instruction text; Cmd+Enter posts a `comment.reply`** | **PICK** | A "revised instruction" is a reply, not an edit — the instruction card needs latest-reply-wins display logic (show newest reply from the instruction author as the effective instruction). Small client-side rule, zero schema change, zero new op. |
|
|
194
|
+
| (b) Add `comment.update` op | Rejected for v1 | New op type, new revision/idempotency edge cases, server + tests, for one affordance. Disproportionate. |
|
|
195
|
+
| (c) Just create another instruction | Rejected | Two pending instructions on one block = agent sees contradictory intent; dedup was a named good-part of the old UX. |
|
|
196
|
+
|
|
197
|
+
Concretely (a): Comment button on a block whose only open thread is a pending
|
|
198
|
+
instruction **opens that thread directly** (skip the composer). The thread's own
|
|
199
|
+
reply box uses Ask-agent styling when replying on an instruction thread:
|
|
200
|
+
placeholder "Revise this instruction…", Cmd+Enter = reply. Card body renders the
|
|
201
|
+
latest author reply as the instruction text, with a subtle `edited` marker. The
|
|
202
|
+
agent reads the thread top-down; recency-semantics ("last instruction wins") is
|
|
203
|
+
a one-line note in the context doc, not new machinery.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## 7. States
|
|
208
|
+
|
|
209
|
+
| State | Chrome | Copy-as-prompt | Connect-an-agent |
|
|
210
|
+
|---|---|---|---|
|
|
211
|
+
| **Composing (Discuss)** | Composer, Discuss segment | hidden | hidden |
|
|
212
|
+
| **Composing (Ask agent)** | Composer, Ask segment, "What should change?" | footer secondary | visible only if no agent (as primary relabel) |
|
|
213
|
+
| **No agent** | Ask mode fully functional; instruction persists queued | present (composer + card) | primary CTA → AI panel; nothing lost |
|
|
214
|
+
| **Queued/pending** | Instruction card + gutter pip; toolbar "✦ N pending" chip if N>0 | card button | toolbar chip area / AI panel entry point |
|
|
215
|
+
| **Answered (md)** | Collapsed instruction + suggestion-card | card button | n/a |
|
|
216
|
+
| **Answered (text/code)** | Thread reply + `[Mark done]` | card button | n/a |
|
|
217
|
+
| **Drift / stale anchor** (ref/textHash miss) | Pip → `⚠ target changed`; actions: `[Re-anchor]` (re-open composer targeting best-effort match), `[Copy prompt]`, `[Remove]` | present — this is its most important state | hidden |
|
|
218
|
+
| **Empty** | Zero chrome. No bar, no placeholder | n/a | n/a |
|
|
219
|
+
|
|
220
|
+
Accept-collision drift (409 after retry, fingerprint mismatch) stays inside
|
|
221
|
+
suggestion-card: "Document changed since this suggestion — refresh review."
|
|
222
|
+
Unchanged from current implementation.
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Summary
|
|
227
|
+
|
|
228
|
+
1. Two actions stay two. Comment = say something (discuss or instruct); Suggest = review an edit (human or agent).
|
|
229
|
+
2. One composer with a Discuss / Ask-agent segmented control; defaults to Discuss; session-sticky; draft survives flips.
|
|
230
|
+
3. Ask-agent dispatch writes `comment.add {kind:"instruction", queued}` immediately — no queue bar, sidecar is the store.
|
|
231
|
+
4. Copy-as-prompt lives in the composer footer (Ask mode), on every instruction card, and in every drift state — the constant escape hatch; Connect-an-agent only appears when no agent is attached.
|
|
232
|
+
5. Agent answers land in the existing suggestion-card (md, full Accept-writes-doc) or as thread replies (text/code, hand-apply, limitation stated at dispatch).
|
|
233
|
+
6. Re-target dedup = open existing thread, revise via reply, latest-reply-wins display — no `comment.update` op in v1.
|
|
234
|
+
7. **Riskiest assumption:** the agent actually consumes the sidecar and answers with a suggestion op. If it never integrates, every Ask-agent comment dead-ends at "queued + Copy prompt" — acceptable only because copy-as-prompt is one click away in every state, which is why its placement is non-negotiable.
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# Spec: Unified live tweak for web surfaces (Impeccable-live model)
|
|
2
|
+
|
|
3
|
+
> Supersedes OPS-1 ("Tweak on a running app / proxied node-app runtime") and the
|
|
4
|
+
> canceled OPS-2..6 isolated-origin/grant/hardening line. Those described an
|
|
5
|
+
> embed-in-iframe architecture; this spec replaces the whole approach with the
|
|
6
|
+
> Impeccable `live` model. Feasibility confirmed by the B1 spike (see Further
|
|
7
|
+
> Notes).
|
|
8
|
+
|
|
9
|
+
## Problem Statement
|
|
10
|
+
|
|
11
|
+
A user running wiki-viewer wants to point at any element on a rendered web page,
|
|
12
|
+
say what they want ("make this bolder", "try a different layout"), see a few live
|
|
13
|
+
design variants they can compare and tune, and Accept the one they like straight
|
|
14
|
+
into source. Today this only half-exists, in fragmented and inconsistent forms:
|
|
15
|
+
|
|
16
|
+
- **Static HTML** gets a bespoke tweak flow (opaque-origin sandbox, DOM ops,
|
|
17
|
+
"Iterate" variants) that is limited and SPA-hostile.
|
|
18
|
+
- **Running node apps / dynamic surfaces** get **no tweak surface at all** — the
|
|
19
|
+
picker is deliberately not injected into proxied apps. The one place the user
|
|
20
|
+
most wants to point-and-fix is the one place the feature is missing.
|
|
21
|
+
- The two surfaces behave differently, so there is no single mental model.
|
|
22
|
+
|
|
23
|
+
The user is forced to leave the rendered page, hunt for the right source by hand,
|
|
24
|
+
edit blind, and reload to check. The visual, direct-manipulation promise is
|
|
25
|
+
broken for exactly the surfaces where it matters most.
|
|
26
|
+
|
|
27
|
+
## Solution
|
|
28
|
+
|
|
29
|
+
One unified live-tweak experience across all web/visual surfaces (static HTML,
|
|
30
|
+
dynamic/server-rendered HTML, running node apps), modeled on the Impeccable `live`
|
|
31
|
+
skill. The user opens a surface, points at an element, picks a design action or
|
|
32
|
+
types a freeform instruction, and hits Go. The system produces 2 to 5 full-element
|
|
33
|
+
variants, each with 0 to 4 tunable knobs (sliders, toggles, segmented controls).
|
|
34
|
+
The user cycles variants and drags knobs with instant feedback, then Accepts the
|
|
35
|
+
chosen variant, which lands in the real source file. Discard restores the
|
|
36
|
+
original. Nothing is written to disk until Accept.
|
|
37
|
+
|
|
38
|
+
The variants are generated by the user's existing attached agent (the same AI
|
|
39
|
+
channel that already powers markdown and static-HTML tweak today), so no new AI
|
|
40
|
+
plumbing is introduced. The Impeccable live engine (a local helper server plus
|
|
41
|
+
its browser overlay and source-mutation logic) is hosted and driven by the
|
|
42
|
+
wiki-viewer product itself, not by a chat agent running the skill by hand.
|
|
43
|
+
|
|
44
|
+
Because Impeccable injects its overlay into the app's own page (the user edits
|
|
45
|
+
their own app, in place), there is no parent frame to protect. That relocation of
|
|
46
|
+
trust deletes the isolated-origin security problem that the previous
|
|
47
|
+
(now-canceled) design was built to solve.
|
|
48
|
+
|
|
49
|
+
### Surface-specific experience (user-facing)
|
|
50
|
+
|
|
51
|
+
The top-level flow (point, instruct, Go, compare variants, tune knobs, Accept or
|
|
52
|
+
Discard) is identical on every surface. The only user-visible difference is how
|
|
53
|
+
variants first appear on screen.
|
|
54
|
+
|
|
55
|
+
- **Static HTML file.** No dev server involved; the file is both served and
|
|
56
|
+
source. After Go, variants appear via an instant client-side swap: no reload, no
|
|
57
|
+
flicker, no lost state. Cycling variants and dragging knobs are instant. Accept
|
|
58
|
+
writes into the `.html` file directly. This is the flagship, flicker-free
|
|
59
|
+
experience and ships first.
|
|
60
|
+
|
|
61
|
+
- **Dynamic / server-rendered HTML that maps to editable templates.** Where the
|
|
62
|
+
served HTML corresponds to real editable source (raw templates, not compiled
|
|
63
|
+
component trees), the same fetch-source swap applies and the reload below is
|
|
64
|
+
usually avoided.
|
|
65
|
+
|
|
66
|
+
- **Running node apps (compiled frameworks: React, Vue, Next, etc.).** The app
|
|
67
|
+
must be running and viewed through the proxy. Variant markup is written into the
|
|
68
|
+
app's real component/template source. To render compiled source, the page
|
|
69
|
+
performs **one full reload per Go**; the overlay re-attaches automatically (it
|
|
70
|
+
remembers its session per page). After that single reload, all variants are
|
|
71
|
+
already present in the page, so cycling and knob-tuning are instant and
|
|
72
|
+
client-side, exactly like static. Accept bakes the choice into source and may
|
|
73
|
+
trigger one more brief reload for the clean final render.
|
|
74
|
+
|
|
75
|
+
The one felt cost on compiled apps: a full reload resets transient in-app state
|
|
76
|
+
(open modals, form input, deep scroll, SPA sub-route). Static HTML never has
|
|
77
|
+
this. Closing that gap (flicker-free, state-preserving hot-swap) is deferred
|
|
78
|
+
optional work; see Out of Scope.
|
|
79
|
+
|
|
80
|
+
## User Stories
|
|
81
|
+
|
|
82
|
+
1. As a wiki-viewer user, I want to point at any element on a rendered web page and have it highlight, so that I can target exactly what I want to change.
|
|
83
|
+
2. As a user, I want to pick a named design action (bolder, quieter, distill, polish, typeset, colorize, layout, adapt, animate, delight) for the selected element, so that I can steer the direction without writing a prompt.
|
|
84
|
+
3. As a user, I want to type a freeform instruction for the selected element, so that I can express intent the named actions do not cover.
|
|
85
|
+
4. As a user, I want to scribble or annotate directly on the element before generating, so that I can point at sub-parts and give spatial direction.
|
|
86
|
+
5. As a user, I want 2 to 5 distinct variants generated per request, so that I can compare real alternatives rather than accept the first idea.
|
|
87
|
+
6. As a user, I want to cycle between the generated variants quickly, so that I can judge them side by side in the real page.
|
|
88
|
+
7. As a user, I want each variant to expose a few tunable knobs (sliders, toggles, segmented controls), so that I can fine-tune a direction without regenerating.
|
|
89
|
+
8. As a user, I want knob changes to update the preview instantly, so that tuning feels direct.
|
|
90
|
+
9. As a user, I want to Accept a chosen variant and have it written into the real source file, so that the change persists in my project.
|
|
91
|
+
10. As a user, I want Discard to restore the original exactly, so that experimenting is risk-free.
|
|
92
|
+
11. As a user, I want nothing written to disk until I Accept, so that previews never corrupt my files.
|
|
93
|
+
12. As a user, I want Accept refused if the underlying source changed since the preview began, so that a concurrent edit is never silently overwritten.
|
|
94
|
+
13. As a user editing a static HTML file, I want variants to appear instantly with no reload or flicker, so that the experience feels live.
|
|
95
|
+
14. As a user tweaking a running node app, I want the tweak overlay available on the proxied app page, so that I can point-and-fix without leaving the app.
|
|
96
|
+
15. As a user tweaking a running node app, I want the overlay to re-attach itself after the post-generate reload, so that my session is not interrupted.
|
|
97
|
+
16. As a user tweaking a compiled app, I want cycling and knob-tuning to stay instant after the initial reload, so that only the first render costs a reload.
|
|
98
|
+
17. As a user, I want the accepted change written to the true source (template or component), never to a generated build output, so that my change is not wiped by the next build.
|
|
99
|
+
18. As a user, I want a clear indication when a surface is generating variants versus ready to review, so that I know what the system is doing.
|
|
100
|
+
19. As a user, I want to steer the whole page (a page-level instruction with no specific element), so that I can request broad direction.
|
|
101
|
+
20. As a user, I want to start a tweak on a static HTML surface with no dev server or app launch required, so that the simplest case is frictionless.
|
|
102
|
+
21. As an admin in authenticated mode, I want node-app launching to remain gated to me (or explicitly allowed runners), so that arbitrary users cannot start host processes just to tweak.
|
|
103
|
+
22. As a user, I want the tweak overlay to only load where I am authorized for the workspace, so that the feature respects existing access boundaries.
|
|
104
|
+
23. As a user, I want the tweak engine's runtime files kept out of my served pages, my file browser, and my commits, so that internal state never leaks into my project or repo.
|
|
105
|
+
24. As a user, I want an interrupted tweak session (reload, crash, disconnect) to recover to a safe state, so that I never end up with half-applied variants.
|
|
106
|
+
25. As a user, I want at most one outstanding generate request per surface session, so that rapid clicks do not stack conflicting generations.
|
|
107
|
+
26. As a user, I want the accepted variant's knob values baked into the final source, so that what I tuned is what persists.
|
|
108
|
+
27. As a user, I want the previous bespoke static-HTML tweak flow replaced by this unified one, so that I do not have to learn two different behaviors.
|
|
109
|
+
28. As a user, I want the markdown prose tweak flow to keep working as it does today, so that this change does not regress non-visual editing.
|
|
110
|
+
29. As a user, I want variants that respect my app's existing visual identity by default, so that I can actually accept them rather than getting off-brand results.
|
|
111
|
+
30. As a user, I want a departure (redesign) direction only when I explicitly ask for it, so that "make it better" does not throw away my brand.
|
|
112
|
+
31. As a user, I want a live indication when the overlay cannot reach the engine, so that I know to reconnect rather than assume it is working.
|
|
113
|
+
32. As a user viewing a remotely-hosted wiki-viewer (not localhost), I want the tweak overlay to still function, so that the feature is not limited to local use.
|
|
114
|
+
33. As a user, I want a failed variant render to surface as a recoverable error rather than a blank page, so that one bad generation does not break the session.
|
|
115
|
+
34. As a developer, I want the accept/carbonize write path to go through wiki-viewer's own containment and locking, so that tweak writes obey the same safety as every other file write.
|
|
116
|
+
|
|
117
|
+
## Implementation Decisions
|
|
118
|
+
|
|
119
|
+
- **Topology: product hosts the engine; the existing attached agent generates.**
|
|
120
|
+
wiki-viewer spawns and supervises the Impeccable live helper server (one per
|
|
121
|
+
served surface, keyed like the node-app runner keys apps), injects the overlay,
|
|
122
|
+
and runs the engine's poll loop **server-side**. On a generate event, wiki-viewer
|
|
123
|
+
translates it into a request on its existing attached-agent live channel, so the
|
|
124
|
+
user's current AI session produces the variants. wiki-viewer applies the variant
|
|
125
|
+
writes and replies to the engine; on Accept it runs the accept/carbonize
|
|
126
|
+
mutation through its own writer.
|
|
127
|
+
|
|
128
|
+
- **Primary new module: the live bridge.** A product-side bridge translates
|
|
129
|
+
Impeccable poll events (generate, steer, accept, discard, prefetch,
|
|
130
|
+
variant-mount-failed, manual-edit-apply) into the existing live-store request
|
|
131
|
+
kinds and back. It owns the reconciliation between the engine's poll/lease model
|
|
132
|
+
and wiki-viewer's one-outstanding-per-session, delivered/working/resolved state
|
|
133
|
+
machine, and idempotency keying. This is the single primary seam.
|
|
134
|
+
|
|
135
|
+
- **Injection as a shared pure transform.** A single string transform injects the
|
|
136
|
+
engine prelude globals plus the overlay `<script>`. It is reused by the app-proxy
|
|
137
|
+
serve-time HTML rewrite (for running apps) and the static-HTML viewer render (for
|
|
138
|
+
files). Serve-time injection means no source files are edited to enable tweak and
|
|
139
|
+
no removal step is needed. The stock live-inject source-file editor is not used.
|
|
140
|
+
|
|
141
|
+
- **Accept/carbonize as a pure mutator over wiki-viewer's writer.** The engine's
|
|
142
|
+
accept logic (locate markers, extract the chosen variant, carbonize/bake knob
|
|
143
|
+
values, produce clean final source) is hosted as a pure transform whose writes
|
|
144
|
+
go through `resolveWorkspacePath` containment plus wiki-viewer's existing write
|
|
145
|
+
lock and collab-state checks. The engine's own raw file write and separate
|
|
146
|
+
lockfile are not used for source mutation, so there is exactly one authoritative
|
|
147
|
+
write/lock spine.
|
|
148
|
+
|
|
149
|
+
- **Speculative-until-Accept invariant preserved.** Previews never write source.
|
|
150
|
+
Accept is the only operation that writes, and only if the base content hash still
|
|
151
|
+
matches (drift refuses the accept). This mirrors the current web-tweak accept
|
|
152
|
+
contract and the engine's accept-receipt idempotency.
|
|
153
|
+
|
|
154
|
+
- **Browser-to-helper transport must survive remote hosting.** Because the overlay
|
|
155
|
+
runs on wiki-viewer's origin and the browser may be remote, the engine endpoints
|
|
156
|
+
the overlay needs (overlay bundle, event downlink/SSE, uplink, source read,
|
|
157
|
+
design-system read, annotation upload) are exposed through wiki-viewer's own
|
|
158
|
+
origin, and the injected globals point the overlay at those proxied paths rather
|
|
159
|
+
than a hardcoded localhost helper port. Proxied endpoints inherit wiki-viewer
|
|
160
|
+
session/agent auth and CSRF Origin checks.
|
|
161
|
+
|
|
162
|
+
- **Dynamic-app rendering uses full-reload-through-proxy.** HMR WebSocket does not
|
|
163
|
+
pass through the app-proxy today (confirmed). For compiled apps, a post-generate
|
|
164
|
+
full page reload renders the written variants; the overlay re-attaches via its
|
|
165
|
+
durable per-origin session. Cycling and knobs remain client-side after that one
|
|
166
|
+
reload. Static and template-mapped surfaces use the instant client-side / fetch-
|
|
167
|
+
source swap and do not reload.
|
|
168
|
+
|
|
169
|
+
- **Engine runtime state is denied and ignored.** The engine's runtime directory
|
|
170
|
+
is added to path-containment denied segments (so it is never served, traversed,
|
|
171
|
+
or reachable via file routes) and to gitignore (so it is never committed),
|
|
172
|
+
consistent with the existing treatment of `.proof` and `.git`.
|
|
173
|
+
|
|
174
|
+
- **Node-app authorization unchanged.** Launching an app to tweak it obeys the
|
|
175
|
+
existing app-runner permission model (admin-only in auth mode unless the runner
|
|
176
|
+
allowance is set). Overlay availability follows workspace access.
|
|
177
|
+
|
|
178
|
+
- **Variant quality contract inherited from the engine.** Identity-preserving
|
|
179
|
+
"default" mode is the norm; a "departure" redesign direction is used only on
|
|
180
|
+
explicit user request. This is engine behavior wiki-viewer surfaces, not new
|
|
181
|
+
product logic.
|
|
182
|
+
|
|
183
|
+
- **Recovery via the engine journal.** Session state is the engine's append-only
|
|
184
|
+
per-session journal; interrupted sessions replay to a safe state on reconnect
|
|
185
|
+
rather than leaving half-applied variants.
|
|
186
|
+
|
|
187
|
+
## Testing Decisions
|
|
188
|
+
|
|
189
|
+
- **Good tests assert external behavior, not internals.** Tests drive the feature
|
|
190
|
+
through its route handlers and pure transforms and assert the observable
|
|
191
|
+
contract: previews never write; Accept writes verbatim only on matching base
|
|
192
|
+
hash; one-outstanding-per-session; idempotent replay; original restored on
|
|
193
|
+
Discard; runtime dir denied. They do not assert internal call sequences.
|
|
194
|
+
|
|
195
|
+
- **Primary seam: the live bridge at the route-handler level.** Tested exactly
|
|
196
|
+
like the existing live-collab proof tests: a temp workspace and registered
|
|
197
|
+
agent, drive the poll/reply loop through the real route handlers, assert the
|
|
198
|
+
reconciled state machine, idempotency, and that source is written only on Accept.
|
|
199
|
+
Prior art: `live-collab.test.ts`, `live-md-batch.test.ts`.
|
|
200
|
+
|
|
201
|
+
- **Injection transform: pure-function test.** Assert the transform injects the
|
|
202
|
+
prelude globals and overlay script at the correct anchor, is idempotent, and does
|
|
203
|
+
not corrupt surrounding HTML. Prior art: the existing app-proxy HTML-rewrite
|
|
204
|
+
tests and `web-tweak-picker.test.ts`.
|
|
205
|
+
|
|
206
|
+
- **Accept/carbonize mutator: pure-function + verbatim-commit test.** Assert marker
|
|
207
|
+
location, variant extraction, knob-value baking, clean final output, and the
|
|
208
|
+
base-hash drift guard (accept refused when source drifted; committed verbatim
|
|
209
|
+
when unchanged). Prior art: `web-tweak-collab.test.ts`.
|
|
210
|
+
|
|
211
|
+
- **Authorization and containment.** Assert overlay/endpoints reject unauthorized
|
|
212
|
+
workspace access and that the runtime dir is unreachable through file routes and
|
|
213
|
+
path resolution. Prior art: `app-proxy-auth.test.ts`.
|
|
214
|
+
|
|
215
|
+
- **Helper-server process lifecycle is integration-only.** The live helper is a
|
|
216
|
+
spawned child process; its lifecycle is not part of the unit seam, mirroring how
|
|
217
|
+
`app-runner.test.ts` treats spawned apps. The bridge is tested against the
|
|
218
|
+
engine's HTTP/file contract, not a live child.
|
|
219
|
+
|
|
220
|
+
- **Test floor.** New proof tests are added under the proof suite and the floor is
|
|
221
|
+
updated only via the sanctioned `--update-floor` path.
|
|
222
|
+
|
|
223
|
+
## Out of Scope
|
|
224
|
+
|
|
225
|
+
- **Flicker-free, state-preserving hot-swap for compiled node apps.** Requires
|
|
226
|
+
adding WebSocket-upgrade passthrough to the proxy (forwarding the app's HMR
|
|
227
|
+
socket). Deliberately deferred to a later ticket; compiled apps ship with
|
|
228
|
+
full-reload-through-proxy first. Not a blocker.
|
|
229
|
+
- **Markdown / prose tweak redesign.** The existing markdown variants-in-place flow
|
|
230
|
+
stays as is; this spec covers web/visual surfaces only.
|
|
231
|
+
- **Non-web surfaces** (PDFs, images, binary previews).
|
|
232
|
+
- **Re-implementing the Impeccable live engine natively.** The engine is reused,
|
|
233
|
+
not rebuilt. Rejected during the spike as large, duplicated, security-sensitive
|
|
234
|
+
work.
|
|
235
|
+
- **Multi-user concurrent tweaking of the same element.** Single-user-at-a-time per
|
|
236
|
+
surface session is assumed, consistent with the existing one-outstanding model.
|
|
237
|
+
- **Changing the node-app authorization model.** Existing app-runner permissions
|
|
238
|
+
are reused unchanged.
|
|
239
|
+
|
|
240
|
+
## Further Notes
|
|
241
|
+
|
|
242
|
+
- **Feasibility is established.** The B1 spike confirmed the engine is HTTP plus
|
|
243
|
+
file-based state with no hard chat-agent dependency, that wiki-viewer's proxy and
|
|
244
|
+
static viewer are natural injection points, that the accept/carbonize logic can
|
|
245
|
+
be hosted over wiki-viewer's writer, and that the engine poll loop maps 1:1 onto
|
|
246
|
+
the existing attached-agent channel. The single confirmed constraint (HMR does
|
|
247
|
+
not traverse the proxy) is handled by full-reload-through-proxy and does not gate
|
|
248
|
+
shipping.
|
|
249
|
+
- **Highest remaining risk is the remote-hosting transport bridge** (proxying the
|
|
250
|
+
overlay's engine endpoints through wiki-viewer's origin). It is bounded and
|
|
251
|
+
defined, but it is real new code and should be an early ticket for any non-
|
|
252
|
+
localhost use.
|
|
253
|
+
- **Suggested tracer bullet** (for to-tickets): the static-HTML surface end to end
|
|
254
|
+
(spawn/host engine, inject overlay, run the product-side poll loop, wire one
|
|
255
|
+
generate through the existing agent channel, land one Accept through wiki-viewer's
|
|
256
|
+
writer). It proves the whole spine on the simplest surface; dynamic apps and the
|
|
257
|
+
transport bridge layer on top.
|
|
258
|
+
- **Repo conventions:** every implementing ticket must fold in the matching
|
|
259
|
+
`docs/ux-contracts.md` update (the unified flow replaces the current §1.4
|
|
260
|
+
HTML-tweak/Iterate behavior) and the isometric codebase-map update, in the same
|
|
261
|
+
change as the behavior.
|
|
@@ -15,7 +15,7 @@ const currentPort = parseInt(process.env.PORT, 10) || 3000
|
|
|
15
15
|
const hostname = process.env.HOSTNAME || '0.0.0.0'
|
|
16
16
|
|
|
17
17
|
let keepAliveTimeout = parseInt(process.env.KEEP_ALIVE_TIMEOUT, 10)
|
|
18
|
-
const nextConfig = {"env":{"NEXT_PUBLIC_APP_VERSION":"2.16.
|
|
18
|
+
const nextConfig = {"env":{"NEXT_PUBLIC_APP_VERSION":"2.16.1"},"webpack":null,"typescript":{"ignoreBuildErrors":false},"typedRoutes":false,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":true,"customCacheHandler":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{"serverFunctions":true,"browserToTerminal":"warn"},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/sil/wiki-viewer","allowedDevOrigins":["localhost"],"cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"appNewScrollHandler":false,"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"cachedNavigations":false,"partialFallbacks":false,"dynamicOnHover":false,"varyParams":false,"prefetchInlining":false,"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"imgOptSkipMetadata":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"strictRouteTypes":false,"viewTransition":false,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":false,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":true,"serverComponentsHmrCache":true,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"gestureTransition":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":"warn","lockDistDir":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":false,"turbopackInferModuleSideEffects":true,"turbopackPluginRuntimeStrategy":"childProcesses","optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","turbopack":{"root":"/home/sil/wiki-viewer"},"distDirRoot":".next"}
|
|
19
19
|
|
|
20
20
|
process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig)
|
|
21
21
|
|
package/package.json
CHANGED