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.
Files changed (124) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +3 -3
  3. package/.next/standalone/.next/prerender-manifest.json +3 -3
  4. package/.next/standalone/.next/required-server-files.json +4 -4
  5. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  6. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  7. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  14. package/.next/standalone/.next/server/app/api/agent/activity/route.js.nft.json +1 -1
  15. package/.next/standalone/.next/server/app/api/agent/events/[...path]/route.js.nft.json +1 -1
  16. package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js.nft.json +1 -1
  17. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js.nft.json +1 -1
  18. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js.nft.json +1 -1
  19. package/.next/standalone/.next/server/app/api/agent/fs/move/route.js.nft.json +1 -1
  20. package/.next/standalone/.next/server/app/api/agent/fs/search/route.js.nft.json +1 -1
  21. package/.next/standalone/.next/server/app/api/agent/settings/route.js.nft.json +1 -1
  22. package/.next/standalone/.next/server/app/api/agent/sidecar/[...path]/route.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/api/app-proxy/[...path]/route.js.nft.json +1 -1
  24. package/.next/standalone/.next/server/app/api/assets/[...path]/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/pdf/save/route.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/api/share/[token]/asset/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/share/[token]/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/share/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/system/browse/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/system/reveal/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/branch/route.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/refresh/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/api/system/workspaces/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/upload/[...path]/route.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/api/wiki/app/route.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/api/wiki/backlinks/route.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/api/wiki/content/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/api/wiki/download/route.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/api/wiki/folder/route.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/api/wiki/git-branches/route.js.nft.json +1 -1
  43. package/.next/standalone/.next/server/app/api/wiki/git-checkout/route.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/api/wiki/git-diff/route.js.nft.json +1 -1
  45. package/.next/standalone/.next/server/app/api/wiki/git-file-info/route.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/api/wiki/git-history/route.js.nft.json +1 -1
  47. package/.next/standalone/.next/server/app/api/wiki/git-pull/route.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/api/wiki/move/route.js.nft.json +1 -1
  49. package/.next/standalone/.next/server/app/api/wiki/new-file/route.js.nft.json +1 -1
  50. package/.next/standalone/.next/server/app/api/wiki/outlinks/route.js.nft.json +1 -1
  51. package/.next/standalone/.next/server/app/api/wiki/page/route.js.nft.json +1 -1
  52. package/.next/standalone/.next/server/app/api/wiki/presence/route.js.nft.json +1 -1
  53. package/.next/standalone/.next/server/app/api/wiki/route.js.nft.json +1 -1
  54. package/.next/standalone/.next/server/app/api/wiki/scratch/route.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/api/wiki/search/route.js.nft.json +1 -1
  56. package/.next/standalone/.next/server/app/api/wiki/slugs/route.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/api/wiki/upload/route.js.nft.json +1 -1
  58. package/.next/standalone/.next/server/app/api/wiki/watch/route.js.nft.json +1 -1
  59. package/.next/standalone/.next/server/app/page/react-loadable-manifest.json +4 -5
  60. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  61. package/.next/standalone/.next/server/app/s/[token]/page_client-reference-manifest.js +1 -1
  62. package/.next/standalone/.next/server/app/signin/page_client-reference-manifest.js +1 -1
  63. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ltsov-._.js +1 -1
  64. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_system_workspaces_[id]_open_route_actions_1087xu7.js +1 -1
  65. package/.next/standalone/.next/server/chunks/ssr/0.u4_next_0kf.7hj._.js +1 -1
  66. package/.next/standalone/.next/server/chunks/ssr/0.u4_next_dist_0xugq-k._.js +1 -1
  67. package/.next/standalone/.next/server/chunks/ssr/12y~_mermaid_dist_chunks_mermaid_core_chunk-5ZQYHXKU_mjs_0z1.978._.js +1 -1
  68. package/.next/standalone/.next/server/chunks/ssr/12y~_mermaid_dist_chunks_mermaid_core_chunk-KSCS5N6A_mjs_0v4oeem._.js +1 -1
  69. package/.next/standalone/.next/server/chunks/ssr/_01eqklo._.js +1 -1
  70. package/.next/standalone/.next/server/chunks/ssr/_0858xdh._.js +1 -1
  71. package/.next/standalone/.next/server/chunks/ssr/_0k6g8yo._.js +3 -3
  72. package/.next/standalone/.next/server/chunks/ssr/_0sr4wj.._.js +1 -1
  73. package/.next/standalone/.next/server/chunks/ssr/node_modules__pnpm_06613~i._.js +1 -1
  74. package/.next/standalone/.next/server/chunks/ssr/node_modules__pnpm_0o~d81.._.js +1 -1
  75. package/.next/standalone/.next/server/chunks/ssr/node_modules__pnpm_0szp2v0._.js +1 -1
  76. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  77. package/.next/standalone/.next/server/pages/500.html +1 -1
  78. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  79. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  80. package/.next/standalone/.next/static/chunks/0.5ywu7_j899v.js +12 -0
  81. package/.next/standalone/.next/static/chunks/{0tjcc1wg-57l1.js → 065s1_n.1k11t.js} +1 -1
  82. package/.next/standalone/.next/static/chunks/{0y~5s_skz1l9a.js → 0ccw-uc_3ao.w.js} +1 -1
  83. package/.next/standalone/.next/static/chunks/{0ii.akeq7k4pf.js → 0f8kfd9d6kq0b.js} +1 -1
  84. package/.next/standalone/.next/static/chunks/0lsw6lsaj7lby.js +1 -0
  85. package/.next/standalone/.next/static/chunks/0rpxacw15~o7k.js +12 -0
  86. package/.next/standalone/.next/static/chunks/{0r7d-1tq61fa1.js → 0s2h7kvkrtq~p.js} +1 -1
  87. package/.next/standalone/.next/static/chunks/{0enm-3xy21jcx.js → 0tzi1~wpigp2y.js} +2 -2
  88. package/.next/standalone/.next/static/chunks/117dkzyg4c~us.js +1 -0
  89. package/.next/standalone/.next/static/chunks/{0j7kp7w2oum68.js → 11pa_9ucyrzh9.js} +1 -1
  90. package/.next/standalone/.scratch/tweak-running-app/craft-checklist.md +52 -0
  91. package/.next/standalone/.scratch/tweak-running-app/issues/01-isolated-origin.md +108 -0
  92. package/.next/standalone/.scratch/tweak-running-app/issues/01-runtime-containment.md +18 -0
  93. package/.next/standalone/.scratch/tweak-running-app/issues/02-injection-transform.md +18 -0
  94. package/.next/standalone/.scratch/tweak-running-app/issues/02-tracer-bullet.md +48 -0
  95. package/.next/standalone/.scratch/tweak-running-app/issues/03-accept-carbonize-mutator.md +19 -0
  96. package/.next/standalone/.scratch/tweak-running-app/issues/03-run-robustness.md +37 -0
  97. package/.next/standalone/.scratch/tweak-running-app/issues/04-multifile-safety.md +37 -0
  98. package/.next/standalone/.scratch/tweak-running-app/issues/04-static-tracer-bullet.md +27 -0
  99. package/.next/standalone/.scratch/tweak-running-app/issues/05-batch-parity.md +43 -0
  100. package/.next/standalone/.scratch/tweak-running-app/issues/05-dynamic-node-app.md +22 -0
  101. package/.next/standalone/.scratch/tweak-running-app/issues/06-remote-transport-bridge.md +20 -0
  102. package/.next/standalone/.scratch/tweak-running-app/issues/07-retire-bespoke-web-tweak.md +17 -0
  103. package/.next/standalone/.scratch/tweak-running-app/keep-ticket.md +74 -0
  104. package/.next/standalone/.scratch/tweak-running-app/mockups.html +305 -0
  105. package/.next/standalone/.scratch/tweak-running-app/ops1-updated.md +215 -0
  106. package/.next/standalone/.scratch/tweak-running-app/ops12-continuation.md +44 -0
  107. package/.next/standalone/.scratch/tweak-running-app/ops22-context.md +84 -0
  108. package/.next/standalone/.scratch/tweak-running-app/pivot-note.md +25 -0
  109. package/.next/standalone/.scratch/tweak-running-app/qa-live-engine.ts +104 -0
  110. package/.next/standalone/.scratch/tweak-running-app/spike.md +256 -0
  111. package/.next/standalone/.scratch/tweak-running-app/suggest-current-assessment.md +39 -0
  112. package/.next/standalone/.scratch/tweak-running-app/suggest-inline-interaction-spec.md +320 -0
  113. package/.next/standalone/.scratch/tweak-running-app/tweak-interaction-spec.md +161 -0
  114. package/.next/standalone/.scratch/tweak-running-app/two-actions-interaction-spec.md +234 -0
  115. package/.next/standalone/.scratch/tweak-running-app/unified-live-spec.md +261 -0
  116. package/.next/standalone/package.json +1 -1
  117. package/.next/standalone/server.js +1 -1
  118. package/package.json +1 -1
  119. package/.next/standalone/.next/static/chunks/04jvwlttwa_sw.js +0 -12
  120. package/.next/standalone/.next/static/chunks/161kgz.8h.3iq.js +0 -1
  121. package/.next/standalone/.next/static/chunks/16kzqur8~yg6b.js +0 -12
  122. /package/.next/standalone/.next/static/{7EbGXTo8ObPhr7UobKARQ → zwUX5EOT_44n1RoB_W9Bo}/_buildManifest.js +0 -0
  123. /package/.next/standalone/.next/static/{7EbGXTo8ObPhr7UobKARQ → zwUX5EOT_44n1RoB_W9Bo}/_clientMiddlewareManifest.js +0 -0
  124. /package/.next/standalone/.next/static/{7EbGXTo8ObPhr7UobKARQ → zwUX5EOT_44n1RoB_W9Bo}/_ssgManifest.js +0 -0
@@ -0,0 +1,52 @@
1
+ # Design-fidelity / craft checklist (acceptance-level)
2
+
3
+ Purpose: the old Tweak UX was loved for its *craft* — the elements, interactions,
4
+ and polish, not just that it worked. This checklist carries that craft into the
5
+ re-home (Comment + Suggest better UX + Copy-as-prompt). Treat each line as an
6
+ acceptance item a reviewer verifies by hand, not just "the feature works."
7
+
8
+ Applies to: the Suggest inline-redline surface, its review popover, the
9
+ Copy-as-prompt surface, and any composer/popover added. Retire only the
10
+ engine-bound widgets (see bottom); keep everything else.
11
+
12
+ ## Keyboard & input
13
+ - [ ] Primary commit on **Cmd/Ctrl+Enter** in every text input (composer, note, reply).
14
+ - [ ] **esc** cancels; **outside-click while the input is empty** = cancel (never a silent commit).
15
+ - [ ] Inputs **autofocus** on open; focus returns sensibly on close.
16
+ - [ ] Full keyboard path through review: open popover, cycle overlap (◂/▸), Accept/Reject without the mouse.
17
+
18
+ ## Anchoring & layout
19
+ - [ ] Popovers anchor to their target and are **viewport-clamped** (min ~8px margin, never off-screen).
20
+ - [ ] Scroll containment: long content scrolls inside the popover/panel (max-height viewport-safe), page doesn't jump.
21
+ - [ ] Tap targets meet **44px** touch slop on coarse pointers (badges use a 16px glyph with 44px hit area).
22
+
23
+ ## Motion (use existing tokens)
24
+ - [ ] Transitions use `--motion-fast 100ms` / `--motion-base 150ms`; nothing janky or instant-pop.
25
+ - [ ] Suggesting-mode flush **crossfades** typed text into posted redline in place (no flash-revert).
26
+ - [ ] Respect `prefers-reduced-motion`.
27
+
28
+ ## Visual language (existing tokens only — no new palette)
29
+ - [ ] Redline uses `--success` (insert, underline) / `--destructive` (delete, strike); block changes get left-bar + `*-soft` wash.
30
+ - [ ] Agent-authored ranges: 45° hatched texture + `✦` glyph, visibly distinct from human.
31
+ - [ ] **Mono snippet chips** for block/selector references; `pre` snippet blocks for quoted source; tag chips where a kind is shown.
32
+ - [ ] Tight editorial type scale (~10.5–13px on chrome, serif for prose/diff), warm-paper surfaces, soft `--shadow-*` elevation.
33
+
34
+ ## Feedback & states
35
+ - [ ] Copy actions show a **"Copied" flip for ~1500ms**, then revert.
36
+ - [ ] Clipboard-blocked (non-secure context) falls back to a **"Show text"** manual-copy box; one code path, always numbered `1.`.
37
+ - [ ] Hover-reveal for secondary row controls (remove/copy) on fine pointers; always visible on touch.
38
+ - [ ] Honest empty state = **zero chrome** (no stray bars/placeholders).
39
+ - [ ] Overlap switcher shows **N of M** and live-swaps the prose redline as you cycle.
40
+ - [ ] Drift / stale-anchor never silently drops: explicit `⚠ target changed` with Re-anchor / Remove.
41
+ - [ ] Author + kind attribution visible on every comment/suggestion (`by`, human vs agent).
42
+
43
+ ## Copy-as-prompt surface specifics
44
+ - [ ] Reads only persisted comments/suggestions; creates/writes nothing.
45
+ - [ ] Per-item ⎘ copy **and** Copy-all; default scope = open/unresolved items.
46
+ - [ ] Emits the established string: ``Edit the file `X` (a Markdown document). Apply these changes:\n\n1. `snippet`: text`` .
47
+
48
+ ## Retire (engine-bound widgets — do NOT resurrect)
49
+ - Bottom-center queue bar (existed only to batch the live engine's single round-trip).
50
+ - Variant apply/revert-into-iframe live preview + variant pills as a *generation* device.
51
+ - The "Apply with the agent?" confirm modal and the live poll/waiting panels.
52
+ Their *feel* (cycling, in-place feedback, keyboard-first, tactile chips) transfers to the new surfaces; the widgets themselves do not.
@@ -0,0 +1,108 @@
1
+ ## Parent
2
+
3
+ OPS-1 — Spec: Tweak on a running app (proxied node-app runtime).
4
+
5
+ ## What to build
6
+
7
+ Serve proxied running node-apps from a dedicated **isolated origin** so a
8
+ sandboxed, opaque-origin Tweak preview can talk to the wiki-viewer parent only
9
+ through the postMessage boundary, and page JS inside the proxied app can never
10
+ reach `parent.document` to forge an Accept.
11
+
12
+ Today the proxied app iframe is served from the wiki-viewer origin and keeps
13
+ `allow-same-origin` (required for the app to function), so hostile page script
14
+ could reach the parent and click Accept, bypassing the postMessage boundary.
15
+ The static-HTML Tweak surface avoids this by rendering into an opaque origin
16
+ (`srcDoc` + `sandbox="allow-scripts"`). A running app cannot use that trick
17
+ because it must stay same-origin to work. The only fix is a separate origin.
18
+
19
+ This ticket is the security foundation for the whole feature. It introduces the
20
+ isolated origin, the grant-based authorization for it, and the wiki-origin
21
+ hardening that becomes load-bearing once the app moves to a sibling origin. It
22
+ does **not** add any Tweak UI yet.
23
+
24
+ **Critical design fact (do not skip): a different origin is still the same
25
+ _site_.** Browser origin includes the port, but *site* does not, so serving the
26
+ app from `host:PORT2` (or a same-registrable-domain subdomain) is a different
27
+ origin yet the **same site** as the wiki UI. Consequences that this ticket MUST
28
+ handle, because they are the real boundary now:
29
+
30
+ - `SameSite` cookies do not stop the app's JS from issuing same-site
31
+ `fetch(..., {credentials:'include'})` against wiki mutating routes. CORS blocks
32
+ reading the response, not the state change. So **every** mutating wiki route
33
+ must enforce an Origin check (`checkOrigin`), and the app-proxy route (which
34
+ does not today) is included.
35
+ - The app page can nest an iframe of the wiki UI itself (session cookie is
36
+ delivered, same-site) and overlay/click the real Accept. So all wiki HTML must
37
+ send `frame-ancestors 'self'` (CSP) / `X-Frame-Options`.
38
+
39
+ The app is served from a sibling **same-site** origin only. A truly cross-site
40
+ `WIKI_APP_ORIGIN` is rejected at boot in v1 (so a `SameSite=Strict` grant cookie
41
+ is still delivered inside the iframe).
42
+
43
+ The origin and injection wiring must be **surface-agnostic**: keyed on "a
44
+ proxied live surface," not hard-wired to node-app-only assumptions, so a future
45
+ proxied surface (for example a dynamic HTML file served through the proxy)
46
+ reuses this path with no new mechanism. The running node app is the first and
47
+ driving consumer, not the only conceivable one.
48
+
49
+ ## Acceptance criteria
50
+
51
+ Origin + serving:
52
+ - [ ] Proxied node-apps are served from a dedicated **same-site** origin distinct
53
+ from the wiki-viewer app origin (default: same host, dedicated port;
54
+ overridable via `WIKI_APP_ORIGIN`), and the running app still functions end
55
+ to end (assets, forms, popups, navigation as before).
56
+ - [ ] A cross-site `WIKI_APP_ORIGIN` is rejected at boot with a clear error (v1
57
+ supports same-site sibling origins only).
58
+ - [ ] The isolated-origin listener serves ONLY the app proxy and the grant
59
+ exchange; every other path on that origin 404s (no wiki UI, no `/api/wiki/*`,
60
+ no auth routes reachable there). https mode reuses the existing cert.
61
+ - [ ] When no isolated origin is configured (e.g. `next dev` single-port), Tweak
62
+ on proxied apps is hard-disabled; the code never falls back to injecting the
63
+ picker on the same origin as the wiki UI.
64
+
65
+ Authorization (grant-only on the isolated origin):
66
+ - [ ] The isolated-origin proxy authorizes via a short-lived HMAC grant only; it
67
+ rejects wiki session-cookie and Bearer-API-key auth (ambient credentials
68
+ must not reach it). Cookies continue to be stripped before forwarding
69
+ upstream.
70
+ - [ ] The grant is scoped to `{userId, workspaceId, appRelPath, exp, jti}` and the
71
+ server enforces the requested `?ws` matches the grant workspace and the
72
+ requested path is under `appRelPath` (a grant for app A cannot drive app B).
73
+ - [ ] The grant HMAC key is derived from the server auth secret with a distinct
74
+ label (not reused from another subsystem). The exchange token is one-time
75
+ (server-side jti seen-set) with a short TTL (~60s); it swaps for a
76
+ path-scoped `HttpOnly` cookie on the isolated origin and is never left in a
77
+ logged URL.
78
+ - [ ] Existing workspace access + app-runner permission checks still gate before
79
+ the child process is reached (no regression to path containment or
80
+ workspace isolation).
81
+
82
+ Wiki-origin hardening (load-bearing once the app is a same-site sibling):
83
+ - [ ] Every mutating wiki route enforces `checkOrigin`; the app-proxy route gains
84
+ an Origin check. Verified by an audit test that fails if a mutating
85
+ `/api/wiki/*` or `/api/system/*` route omits it.
86
+ - [ ] All wiki HTML responses send `frame-ancestors 'self'` (CSP) and
87
+ `X-Frame-Options`, so the proxied app cannot frame-and-overlay the wiki UI.
88
+ - [ ] Both the wiki and isolated origins send `Origin-Agent-Cluster: ?1` (closes
89
+ the `document.domain` same-site bridge).
90
+
91
+ Surface-agnostic + docs:
92
+ - [ ] The isolated-origin serving and picker-injection point are surface-agnostic
93
+ (not coupled to node-app-only keying), so another proxied live surface could
94
+ be served through the same path without changing the origin layer.
95
+ - [ ] Tests: grant mint/verify + scope/replay rejection (unit, mirroring the
96
+ shared-docs access-grant tests); isolated listener refuses wiki API/UI;
97
+ proxy rejects missing/expired/mis-scoped grant and rejects session/Bearer;
98
+ the mutating-route Origin-check audit. In-process tests assert these
99
+ server-side contracts; the browser DOM cross-origin guarantee holds by
100
+ construction and is documented as a manual verification step (it cannot be
101
+ asserted in-process).
102
+ - [ ] `docs/ux-contracts.md` and the isometric map (`isometric-codebase-map.json`
103
+ + `.html`) updated in this same change to describe the isolated proxy origin,
104
+ the grant flow, and the hardening.
105
+
106
+ ## Blocked by
107
+
108
+ - None — can start immediately.
@@ -0,0 +1,18 @@
1
+ ## Parent
2
+ OPS-8 — Spec: Unified live tweak for web surfaces (Impeccable-live model)
3
+
4
+ ## What to build
5
+ The live engine's runtime directory is treated as internal runtime state, never as
6
+ user content: it cannot be resolved through path containment, cannot be reached
7
+ through any browser or agent file route, and is never committed. This is the safety
8
+ floor the rest of the feature builds on.
9
+
10
+ ## Acceptance criteria
11
+ - [ ] The engine runtime directory segment is denied by the canonical path-containment primitive, alongside the existing denied segments.
12
+ - [ ] File-browser and agent file routes cannot read, list, or write anything inside the engine runtime directory (verified by tests).
13
+ - [ ] The engine runtime directory is gitignored so it is never committed.
14
+ - [ ] Proof tests assert the directory is denied by path resolution and unreachable via file routes. Prior art: app-proxy-auth.test.ts, containment tests.
15
+ - [ ] docs/ux-contracts.md and the isometric codebase map are updated in this same change if this introduces any user-facing or subsystem change.
16
+
17
+ ## Blocked by
18
+ None — can start immediately.
@@ -0,0 +1,18 @@
1
+ ## Parent
2
+ OPS-8 — Spec: Unified live tweak for web surfaces (Impeccable-live model)
3
+
4
+ ## What to build
5
+ A single pure string transform that injects the live engine prelude globals plus
6
+ the overlay script tag into a page's HTML at the correct anchor. It is the shared
7
+ mechanism both the static-HTML viewer render and the app-proxy serve-time rewrite
8
+ will reuse, so tweak is enabled without editing any source file.
9
+
10
+ ## Acceptance criteria
11
+ - [ ] A pure function injects the prelude globals and the overlay script tag at the correct HTML anchor.
12
+ - [ ] The transform is idempotent (injecting twice yields the same result as once) and does not corrupt surrounding HTML.
13
+ - [ ] The injected globals are parameterized (engine endpoints/token) so callers can point the overlay at either a direct helper or proxied paths later.
14
+ - [ ] Unit-tested as a pure function. Prior art: app-proxy HTML-rewrite tests, web-tweak-picker.test.ts.
15
+ - [ ] docs/ux-contracts.md and the isometric codebase map are updated in this same change if this introduces any user-facing or subsystem change.
16
+
17
+ ## Blocked by
18
+ None — can start immediately.
@@ -0,0 +1,48 @@
1
+ ## Parent
2
+
3
+ OPS-1 — Spec: Tweak on a running app (proxied node-app runtime).
4
+
5
+ ## What to build
6
+
7
+ The first complete, demoable Tweak round-trip on a running app: happy path,
8
+ one element, one file.
9
+
10
+ The user opens their running app in the proxied view, enters Tweak mode, points
11
+ at one real element on the live page, types one instruction, and dispatches. The
12
+ attached agent receives the request through the existing poll/reply channel and
13
+ returns one reviewable proposal. The user reviews and Accepts. On Accept,
14
+ wiki-viewer sends an approval to the agent (carrying the proposal identity and
15
+ the base hash captured at proposal time); the agent writes the single source
16
+ file, triggers the app rebuild/reload, and returns a success receipt.
17
+ wiki-viewer records the receipt and the user sees the running app reflect the
18
+ change.
19
+
20
+ Scope is the tracer bullet only: exactly one queued element, one written file,
21
+ success path. Failure/cancel/discard, multi-file, drift refusal, and full batch
22
+ + parity affordances are separate tickets.
23
+
24
+ The running node app is the concrete driver for this round-trip, but the Tweak
25
+ surface wiring should sit on the surface-agnostic proxied-live-surface
26
+ foundation from ticket 1, not bake in node-app-only assumptions beyond what this
27
+ slice needs.
28
+
29
+ ## Acceptance criteria
30
+
31
+ - [ ] The proxied running-app view exposes a Tweak entry point (picker injected
32
+ into the proxied app via the isolated origin from ticket 1).
33
+ - [ ] Selecting one element highlights it as the Tweak target and lets the user
34
+ type an instruction.
35
+ - [ ] Dispatch sends the request over the existing human→agent request channel;
36
+ the agent replies with one reviewable proposal over the existing poll/reply
37
+ channel (no new transport).
38
+ - [ ] Accept transitions the proposal to approval-sent and hands the agent an
39
+ approval carrying the proposal identity and the per-file base hash.
40
+ - [ ] The agent write of a single file, followed by app reload, is reflected in
41
+ the running app; wiki-viewer records a success receipt and shows success.
42
+ - [ ] Route-level proof test in `src/tests/proof/` exercises the full
43
+ dispatch → propose → accept → approval → receipt-success path in process.
44
+ - [ ] `docs/ux-contracts.md` and the isometric map updated in this same change.
45
+
46
+ ## Blocked by
47
+
48
+ - Ticket 1 (isolated proxy origin).
@@ -0,0 +1,19 @@
1
+ ## Parent
2
+ OPS-8 — Spec: Unified live tweak for web surfaces (Impeccable-live model)
3
+
4
+ ## What to build
5
+ A pure transform that turns an accepted variant into clean permanent source:
6
+ locate the engine markers, extract the chosen variant, bake in the tuned knob
7
+ values, and emit the final source with all live-mode scaffolding removed. It
8
+ enforces the speculative-until-Accept invariant by refusing when the base content
9
+ has drifted since the preview began.
10
+
11
+ ## Acceptance criteria
12
+ - [ ] A pure function locates markers, extracts the chosen variant, bakes knob values, and produces clean final source with no live-mode leftovers.
13
+ - [ ] Accept is refused when the base content hash no longer matches (drift), and commits verbatim when it matches.
14
+ - [ ] Non-accepted variants and their scaffolding are fully removed from the output.
15
+ - [ ] Unit-tested as a pure function including the drift-refusal and verbatim-commit paths. Prior art: web-tweak-collab.test.ts.
16
+ - [ ] docs/ux-contracts.md and the isometric codebase map are updated in this same change if this introduces any user-facing or subsystem change.
17
+
18
+ ## Blocked by
19
+ None — can start immediately.
@@ -0,0 +1,37 @@
1
+ ## Parent
2
+
3
+ OPS-1 — Spec: Tweak on a running app (proxied node-app runtime).
4
+
5
+ ## What to build
6
+
7
+ Make the running-app Tweak run survive the unhappy paths, reusing the same
8
+ recovery discipline the markdown/HTML surfaces already have (core parity).
9
+
10
+ Covers the failure and control transitions layered on the tracer bullet:
11
+
12
+ - **Receipt-failed**: when the agent's write receipt reports failure, the user
13
+ sees a clear reason, the queue is preserved, and the same proposal can be
14
+ retried without re-describing it.
15
+ - **Cancel run**: while a run waits on the agent, the user can cancel it, which
16
+ frees the single outstanding slot and writes nothing.
17
+ - **Discard proposal**: the user can discard a returned proposal; the app source
18
+ is left byte-identical.
19
+ - **Single-outstanding enforcement**: dispatching while a run is already
20
+ outstanding is cleanly rejected and the queued work is not lost.
21
+
22
+ ## Acceptance criteria
23
+
24
+ - [ ] A failure receipt surfaces a clear reason, preserves the queue, and allows
25
+ retry of the same proposal (state returns to a retryable point, not lost).
26
+ - [ ] Cancel while waiting on the agent frees the outstanding slot and performs
27
+ no write.
28
+ - [ ] Discard leaves the app source byte-identical (verified by hash/no-op).
29
+ - [ ] A second dispatch while one run is outstanding is rejected with a clear
30
+ message and the queue is preserved.
31
+ - [ ] Route-level proof tests cover receipt-failure retry, cancel, discard, and
32
+ the outstanding-run rejection.
33
+ - [ ] `docs/ux-contracts.md` and the isometric map updated in this same change.
34
+
35
+ ## Blocked by
36
+
37
+ - Ticket 2 (tracer bullet round-trip).
@@ -0,0 +1,37 @@
1
+ ## Parent
2
+
3
+ OPS-1 — Spec: Tweak on a running app (proxied node-app runtime).
4
+
5
+ ## What to build
6
+
7
+ Let a single accepted running-app tweak span multiple source files, and enforce
8
+ the write-safety guarantees every other wiki-viewer write already honors.
9
+
10
+ - **Multi-file write**: lift the v1 "candidate must edit exactly one file" cap
11
+ for this flow. Because the agent owns the write, an accepted tweak may
12
+ legitimately touch several files; the approval carries per-file base hashes.
13
+ - **Drift / stale refusal**: if any underlying source file changed since the
14
+ proposal was made (base-hash mismatch at approval time), the write is refused
15
+ (invalidated) rather than silently clobbering a concurrent edit.
16
+ - **Containment + isolation**: every written path is validated through the
17
+ canonical path-containment primitive and stays inside the target workspace.
18
+ - **File-vs-collab safety**: a `.md` file a human currently has open (`active`
19
+ collab state) is never overwritten by a proxied-app tweak write.
20
+
21
+ ## Acceptance criteria
22
+
23
+ - [ ] An accepted tweak can write more than one file in a single approval, with
24
+ per-file base hashes carried on the approval.
25
+ - [ ] A base-hash mismatch on any file at approval time refuses the whole write
26
+ (invalidated, no partial write) and reports it to the user.
27
+ - [ ] Every written path is resolved through `resolveWorkspacePath` and cannot
28
+ escape the workspace (traversal / symlink / absolute path rejected).
29
+ - [ ] A write targeting a `.md` file in `active` collab state is rejected in
30
+ honor of file-vs-collab authority.
31
+ - [ ] Route-level proof tests cover multi-file success, drift refusal, a
32
+ containment escape attempt, and the collab-active rejection.
33
+ - [ ] `docs/ux-contracts.md` and the isometric map updated in this same change.
34
+
35
+ ## Blocked by
36
+
37
+ - Ticket 2 (tracer bullet round-trip).
@@ -0,0 +1,27 @@
1
+ ## Parent
2
+ OPS-8 — Spec: Unified live tweak for web surfaces (Impeccable-live model)
3
+
4
+ ## What to build
5
+ The complete unified live-tweak spine, proven end to end on the simplest surface:
6
+ a static HTML file, localhost. The user opens a static `.html` in wiki-viewer,
7
+ points at an element, picks an action or types an instruction, hits Go, gets 2 to 5
8
+ variants with tunable knobs, cycles and tunes them with instant client-side
9
+ feedback, and Accepts the chosen variant into the file (or Discards to restore the
10
+ original). This is the tracer bullet: it wires together the engine helper
11
+ lifecycle, the overlay injection (02), the product-side poll loop / live bridge,
12
+ the existing attached-agent channel for variant generation, and the accept mutator
13
+ (03) through wiki-viewer's own writer. It is a deliberate serialization point; the
14
+ wider surfaces build on it.
15
+
16
+ ## Acceptance criteria
17
+ - [ ] wiki-viewer spawns, supervises (health, stop), and tears down the engine helper for a static-file tweak session, keyed per surface like the node-app runner keys apps.
18
+ - [ ] The overlay is injected into the static-file render via the transform from ticket 02; the picker highlights elements and offers named actions plus freeform.
19
+ - [ ] A product-side poll loop (the live bridge) translates engine generate/steer/accept/discard events into the existing live-store request kinds and back, honoring one-outstanding-per-session and idempotent replay.
20
+ - [ ] A generate request is fulfilled by the user's existing attached agent; 2 to 5 variants with 0 to 4 knobs each appear via instant client-side swap (no reload).
21
+ - [ ] Accept writes the chosen variant (with baked knob values) into the file through wiki-viewer's writer + path containment + write lock, only on matching base hash; Discard restores the original exactly; nothing writes before Accept.
22
+ - [ ] An interrupted session (reload/disconnect) recovers to a safe state via the engine journal rather than leaving half-applied variants.
23
+ - [ ] Proof tests drive the bridge at the route-handler level asserting the reconciled state machine, write-on-accept-only, and drift refusal. Prior art: live-collab.test.ts, web-tweak-collab.test.ts.
24
+ - [ ] docs/ux-contracts.md (§1.4 area) and the isometric codebase map are updated in this same change to describe the unified static-HTML flow.
25
+
26
+ ## Blocked by
27
+ 01, 02, 03.
@@ -0,0 +1,43 @@
1
+ ## Parent
2
+
3
+ OPS-1 — Spec: Tweak on a running app (proxied node-app runtime).
4
+
5
+ ## What to build
6
+
7
+ Bring the running-app Tweak surface to full **core parity** with the existing
8
+ markdown and HTML surfaces: batch queueing and the shared affordances.
9
+
10
+ - **Batch queue**: queue several element tweaks before dispatching and send them
11
+ as one batch; the agent returns one reviewable proposal per queued item.
12
+ - **Select-again-to-update**: re-selecting an already-queued element updates its
13
+ instruction in place rather than inflating the queued count.
14
+ - **Remove one**: drop a single queued tweak without losing the rest; Cancel-all
15
+ clears the whole queue without dispatching.
16
+ - **Presence indicator**: show whether an agent is listening.
17
+ - **Connect-an-agent**: with queued tweaks but no attached agent, the dispatch
18
+ button becomes "Connect an agent" and opens the agent panel without losing the
19
+ queue.
20
+ - **Surface-specific dispatch label**: the dispatch button carries a label that
21
+ reads naturally on the running-app surface (parity with markdown "Rewrite" /
22
+ HTML "Apply").
23
+ - **Per-item review**: the user reviews and Accepts/Discards each item's proposal
24
+ independently.
25
+
26
+ ## Acceptance criteria
27
+
28
+ - [ ] Multiple element tweaks can be queued and dispatched as one batch; the
29
+ agent returns one proposal per item, each independently reviewable.
30
+ - [ ] Re-selecting a queued element updates its instruction in place (queued
31
+ count unchanged); a single queued tweak can be removed; Cancel-all clears
32
+ the queue without dispatching.
33
+ - [ ] Presence indicator reflects agent-listening state; with no agent the
34
+ dispatch button becomes "Connect an agent" and opens the panel, queue
35
+ intact.
36
+ - [ ] The dispatch button shows the surface-specific label.
37
+ - [ ] Route-level / component proof tests cover batch dispatch, in-place update,
38
+ remove-one, and the no-agent Connect affordance.
39
+ - [ ] `docs/ux-contracts.md` and the isometric map updated in this same change.
40
+
41
+ ## Blocked by
42
+
43
+ - Ticket 2 (tracer bullet round-trip).
@@ -0,0 +1,22 @@
1
+ ## Parent
2
+ OPS-8 — Spec: Unified live tweak for web surfaces (Impeccable-live model)
3
+
4
+ ## What to build
5
+ Extend the unified live tweak to running node apps viewed through the proxy. The
6
+ overlay is injected at proxy serve time so the tweak surface is available on the
7
+ app's own page. After Go, the page performs one full reload through the proxy to
8
+ render the freshly written variants; the overlay re-attaches automatically. After
9
+ that single reload, cycling and knob-tuning stay instant and client-side. Accept
10
+ writes to the true template/component source, never a generated build output.
11
+
12
+ ## Acceptance criteria
13
+ - [ ] The overlay is injected into proxied app HTML at serve time (reusing ticket 02), only where the user is authorized for the workspace and app-runner permissions allow.
14
+ - [ ] After a generate on a compiled app, a single full-reload-through-proxy renders the variants and the overlay re-attaches via its durable per-origin session.
15
+ - [ ] Cycling variants and tuning knobs after the reload are instant and client-side (variants already present in the page).
16
+ - [ ] Accept writes to true source; generated/build-output files are guarded and routed to the real template/component via the fallback path.
17
+ - [ ] Node-app launching remains gated by the existing app-runner permission model (no change to who may start apps).
18
+ - [ ] Proof tests cover injection authorization and the accept-to-true-source path. Prior art: app-proxy-auth.test.ts, web-tweak-collab.test.ts.
19
+ - [ ] docs/ux-contracts.md and the isometric codebase map are updated in this same change to describe the dynamic/node-app flow, including the one-reload behavior.
20
+
21
+ ## Blocked by
22
+ 04.
@@ -0,0 +1,20 @@
1
+ ## Parent
2
+ OPS-8 — Spec: Unified live tweak for web surfaces (Impeccable-live model)
3
+
4
+ ## What to build
5
+ Make the tweak overlay work when wiki-viewer is served remotely, not just on
6
+ localhost. The overlay runs on wiki-viewer's origin but the browser may be on a
7
+ different machine than the engine helper, so the engine endpoints the overlay
8
+ needs are exposed through wiki-viewer's own origin, and the injected globals point
9
+ the overlay at those proxied paths instead of a hardcoded local helper port.
10
+
11
+ ## Acceptance criteria
12
+ - [ ] The overlay bundle, event downlink (SSE), event uplink, source read, design-system read, and annotation upload are all reachable through wiki-viewer's own origin.
13
+ - [ ] The injected globals (ticket 02) point the overlay at the proxied paths so it never depends on the browser reaching the helper's local port directly.
14
+ - [ ] The proxied endpoints enforce wiki-viewer session/agent authorization and the existing CSRF Origin checks; unauthorized access is rejected.
15
+ - [ ] Both static-HTML and node-app tweak sessions function with wiki-viewer served on a non-localhost origin.
16
+ - [ ] Proof tests assert auth/CSRF enforcement on the proxied engine endpoints. Prior art: app-proxy-auth.test.ts.
17
+ - [ ] docs/ux-contracts.md and the isometric codebase map are updated in this same change.
18
+
19
+ ## Blocked by
20
+ 04.
@@ -0,0 +1,17 @@
1
+ ## Parent
2
+ OPS-8 — Spec: Unified live tweak for web surfaces (Impeccable-live model)
3
+
4
+ ## What to build
5
+ Remove the previous bespoke static-HTML tweak flow (opaque-origin sandbox, DOM-ops
6
+ picker, "Iterate" variants) and its supporting code and tests, so there is a single
7
+ unified tweak behavior rather than two. The unified flow from ticket 04 fully covers
8
+ the static-HTML case before this deletion lands.
9
+
10
+ ## Acceptance criteria
11
+ - [ ] The bespoke web-tweak request/resolve/picker/preview/accept paths that the unified flow replaces are removed, along with their now-dead tests.
12
+ - [ ] No user-facing static-HTML tweak capability regresses relative to the unified flow.
13
+ - [ ] The full test suite passes and the test floor is updated only via the sanctioned path.
14
+ - [ ] docs/ux-contracts.md is updated to remove the retired §1.4 bespoke behavior and reflect only the unified flow; the isometric codebase map is updated to drop the retired subsystem.
15
+
16
+ ## Blocked by
17
+ 04.
@@ -0,0 +1,74 @@
1
+ ## Purpose
2
+
3
+ The live "tweak" collaboration engine (web + markdown live-instruct) is being
4
+ **removed** (see the tweak-engine removal commits). The tweak *interaction* was
5
+ genuinely pleasant and should be rebuilt later on top of the existing
6
+ comments/suggestions (sidecar "proof") engine, so there is exactly one
7
+ collaboration engine underneath. This ticket captures everything needed to
8
+ resurrect the UX. **No design work is scoped here yet.**
9
+
10
+ ## Recovery pointer
11
+
12
+ - git tag **`pre-tweak-removal`** = commit `056fd01` — the last commit where the
13
+ tweak UX exists in full. Recover any file via
14
+ `git show pre-tweak-removal:<path>`.
15
+
16
+ ## Reusable chrome to resurrect (surface-agnostic)
17
+
18
+ - `src/components/editor/tweak/tweak-overlay.tsx` — thin shell (targeting + queue bar + run panel)
19
+ - `src/components/editor/tweak/tweak-queue-bar.tsx` — fixed bottom-center queue bar, per-item remove, Cancel-clears-all, dispatch label, extras slot
20
+ - `src/components/editor/tweak/tweak-queue.ts` — queue model (dedup by targetKey)
21
+ - `src/components/editor/tweak/use-tweak-session.ts` — session/phase state, add/update-in-place, presence gate
22
+ - `src/components/editor/tweak/tweak-types.ts` — the `ContentKindAdapter` pattern (contentKind, dispatchLabel, items, onDispatch, renderTargeting, renderRunPanel, renderQueueBarExtras)
23
+ - **Copy-as-prompt** (already built): `buildPrompt()` / `handleCopyPrompt` in
24
+ `adapters/markdown-adapter.tsx:218` and `adapters/html-adapter.tsx:388`
25
+ ("Edit the file X … Apply these changes: 1. <snippet>: <instruction> …"),
26
+ secure-context clipboard gate + textarea fallback.
27
+
28
+ ## UX contract (verbatim extraction from docs/ux-contracts.md pre-removal)
29
+
30
+ ### Tweak queue (shared across surfaces) — §1.2
31
+
32
+ The user-facing feature is **Tweak**. In the editor action menu, **Comment**
33
+ starts a discussion/annotation, **Suggest** proposes a human edit for review, and
34
+ **Tweak** asks the AI to rewrite the selected target. A Tweak is first added to a
35
+ queue. Selecting the same target again updates its queued instruction and snippet
36
+ in place, so the count does not increase. Users can remove one queued item or
37
+ choose **Cancel** to clear all queued selections without dispatching. Clicking
38
+ outside while an instruction input is empty equals **Cancel**. The dispatch button
39
+ label is surface-specific. Queue bars also offer **Copy as prompt** and **Show**
40
+ fallback controls. When no agent is attached, dispatch becomes **Connect an
41
+ agent**.
42
+
43
+ ### Markdown targets — §1.3 (interaction only; the live-dispatch mechanics are being removed)
44
+
45
+ Target is a rendered **block** (paragraph, heading, list item), with an optional
46
+ in-block text selection carried only as context. Markdown/text gather queued
47
+ targets before dispatch (batch, no immediate single-target dispatch). Previews
48
+ are ephemeral; **Accept** is the only write (write-on-accept), gated on the
49
+ block's base hash with drift refusal. Cancel discards without writing.
50
+
51
+ ### Web targets — §1.4 (interaction only; the live engine is being removed)
52
+
53
+ Point at an element, say what you want, see a few variants to compare and tune
54
+ (knobs), Accept one into source. Previews speculative; Accept is the only write,
55
+ with containment + base-drift protection.
56
+
57
+ ## Design direction (deferred — do NOT implement without a fresh spec)
58
+
59
+ Fold the above UX onto the sidecar comments/suggestions engine: the dispatch
60
+ button persists each queued item as an instruction-comment
61
+ (`comment.add {kind:"instruction"}`) via `POST /api/agent/files`, which the user's
62
+ agent picks up through its normal snapshot/activity flow and answers with
63
+ suggestions (reviewed in the existing `suggestion-card`). Copy-as-prompt stays as
64
+ the no-agent escape hatch.
65
+
66
+ **Open default (undecided):** does the tweak action default to creating an
67
+ instruction-comment (durable, agent picks up on its own schedule) or copy-as-prompt
68
+ only? PM leaned copy-as-prompt for simplicity; implementer leaned instruction-comment
69
+ default with copy-as-prompt as the escape hatch. Decide when this is specced.
70
+
71
+ ## Out of scope
72
+
73
+ Any code here. This is a capture-only ticket. Removal of the live tweak engine
74
+ lands separately; this ticket is picked up later for the re-home design.