Skip to content

feat: PawWork persona layer + i18n fixes + error page GitHub redirect#4

Merged
Astro-Han merged 3 commits into
devfrom
worktree-feat+prompt-persona-layer
Apr 16, 2026
Merged

feat: PawWork persona layer + i18n fixes + error page GitHub redirect#4
Astro-Han merged 3 commits into
devfrom
worktree-feat+prompt-persona-layer

Conversation

@Astro-Han

Copy link
Copy Markdown
Owner

Summary

  • Persona layer: Add pawwork-persona.txt prepended to all model system prompts via SystemPrompt.provider(). Establishes non-technical user positioning, natural paragraph style, task-adaptive verbosity, and plain-language tool descriptions across all LLM providers. No provider prompt files modified (cherry-pick compatible).
  • i18n fixes: Add 4 missing keys in zh.ts and zht.ts (sidebar.empty.title/description, session.child.promptDisabled/backToParent). Correct Zen provider description from "代码智能体" to "AI 助手".
  • Error page: Redirect feedback link from Discord to GitHub Issues. Rename i18n key and update prefix brand from OpenCode to PawWork across all 17 locale files.

Test plan

  • Open PawWork, start a new session with any model, verify AI responds naturally (not "One word answers are best")
  • Switch locale to Chinese, verify sidebar empty state shows "还没有打开项目"
  • Trigger an error page, verify link goes to GitHub Issues and label says "PawWork team"
  • Use a BYOK Claude/GPT model, verify persona is active (non-technical tone)

Prepend a shared persona text to every provider prompt via
SystemPrompt.provider(), establishing non-technical user positioning,
natural paragraph style, task-adaptive verbosity, and plain-language
tool descriptions across all LLM providers.
Add sidebar.empty.title/description and session.child.promptDisabled/
backToParent for both Simplified and Traditional Chinese. Change Zen
provider description from "代码智能体"/"程式碼代理程式" to "AI 助手".
Update error.tsx link, icon, and label. Rename i18n key from
error.page.report.discord to error.page.report.github across all
17 locale files. Update error.page.report.prefix brand from
OpenCode to PawWork in all locales.
@Astro-Han Astro-Han merged commit c6afa68 into dev Apr 16, 2026
2 checks passed
@Astro-Han Astro-Han deleted the worktree-feat+prompt-persona-layer branch April 16, 2026 15:14
Astro-Han added a commit that referenced this pull request May 13, 2026
Slice 11b.1 W1 retest hypothesis (P0 #4): AstroHan reported "向上滚动之后
就会不断向下滑" — scrolling the timeline upward immediately gets snapped
back to bottom. Pure-reactivity RCA across `createAutoScroll`,
`use-session-scroll-dock`, the timeline scroll controller, and the W1
leaves did not surface a deterministic code path that would override
`userScrolled`. The remaining suspect is a same-frame race: handleWheel
synchronously calls `stop()` (which writes `userScrolled = true` via
`setStore`), but the streaming-time `createResizeObserver` callback can
fire in the same frame *before* Solid propagates the store read inside
this hook, so `scrollToBottom(false)` lands while the gate still thinks
the user is at bottom.

Belt-and-braces fix: stamp `lastUpwardGestureAt` inside handleWheel and
short-circuit the resize-observer auto-scroll for 500ms after any
upward gesture. The window covers a single wheel tick + layout pass
while staying short enough that users can drop back into auto-follow by
scrolling to the bottom themselves.

No behavioural change while the user is idle or scrolling downward; the
existing isAuto / userScrolled / canScroll gates still apply. The fix is
intentionally local to the resize observer — handleScroll keeps its
threshold-based path so the auto-snap on real bottom-pin restores still
work as before.
Astro-Han added a commit that referenced this pull request May 13, 2026
…d frame

AstroHan W1 second retest flagged 3 structural regressions on the W1
leaves; this commit fixes the trio in one atomic change because all
three are CSS-only.

1. **Text selection regression (#1)** — The app shell sets `select-none`
   on the timeline body (layout.tsx L2320) and opts back in for input,
   textarea, and `[contenteditable]` only. The legacy carve-out at
   message-part.css L710 named `[data-component="user-message"]
   [data-slot="user-message-text"]` and `[data-component="text-part"]`
   so legacy bubble + assistant prose stayed selectable; the W1 leaves
   replaced both data-components without an equivalent carve-out, so
   bubble text and agent prose stopped responding to drag-select.
   Reinstated by adding `user-select: text` + `cursor: text` to
   `[data-slot="bubble-text"]`, `[data-slot="agent-prose"]`, and
   `[data-slot="agent-reasoning"]`.

2. **Trow chev direction (#3)** — The W1 icon is `chevron-down` (rest
   reads "click to expand"), but the open-state rotation was 90°,
   which pointed the glyph sideways. Per AstroHan's flag the open
   chev should read "click to fold up" — 180° rotates `chevron-down`
   to chevron-up, restoring the disclosure idiom.

3. **Trow expanded nested frame (#4)** — DESIGN.md L417 scopes the
   transparent + 1px `--border-weaker` + radius-sm body frame to each
   per-tool result body, not the trow group wrapper. The W1 trow-block
   wrapped the inner sub-rows in its own frame, which composed with
   the legacy per-tool chrome and produced a visible double border.
   Dropped the wrapper's border + padding so it only owns the vertical
   rhythm between sub-rows; the per-tool body keeps its own frame.

Tests still pass: `session-turn-user-bubble`, `session-turn-agent-round`,
and `session-turn-trow-block.reducer` suites are CSS-grep + reducer
based and do not assert any of the changed declarations.
Astro-Han added a commit that referenced this pull request May 13, 2026
AstroHan's third W1 retest (msg=362e9b72) raised two visual issues
on the trow block; both land in `session-turn-trow-block.css`.

**#2 — per-tool box wrapper.** Slice 11b.1 #5 B+ added a transparent
+ 1px --border-weaker frame around each tool's rich body
(`data-slot="trow-result-body"`) as the L417-spec scope marker.
AstroHan reported the chrome makes tools look like isolated cards
and (when bash is expanded) stacks on top of bash-output's own
border. The W1 intent is a flat stacked feed where tools 叠在一起.
The wrapper stays — it is still the scope boundary for the inner
chrome typography reset — but its visual chrome (border / radius /
padding) is removed.

**#4 — chev direction + inner tool chev size.** Two parts:

  (a) Trow summary chev direction. The third retest re-defined the
      affordance: 折叠朝右、展开朝下. The second-retest fix that
      pointed the chev up on `details[open]` is reverted —
      file-tree, Collapsible, and the W1 mocks all use down-when-
      open, so trow should match. Default `transform: rotate(-90deg)`
      (chevron-down → right when collapsed); `details[open]` flips to
      `rotate(0)` (natural down).

  (b) Inner Collapsible.Arrow chev size inside the trow result body.
      AstroHan flagged that the chev inside each tool trigger ("执行
      命令 XXXX" row) renders as a "大 chevron" — Collapsible's default
      is 16px, but the W1 caption surface (DESIGN.md L412 lock) caps
      the chev at 12px. Scoped reset fires only inside
      `[data-slot="trow-result-body"]`, so the Collapsible default
      elsewhere (file-tree, settings, etc.) is unaffected.
Astro-Han added a commit that referenced this pull request May 13, 2026
…te thinking heading

Two related AstroHan W1 retest 4 issues (msg=ac13481a) on the
"思考中" surface and the reasoning-summaries setting.

**#4 — Thinking heading overflows right edge.** When
`showReasoningSummaries` is off the thinking row renders a
`<TextReveal>` showing the latest reasoning heading. `TextReveal`
defaults to `white-space: nowrap` on its entering/leaving spans, so
a long heading bleeds past the column's right edge. The component
already exposes a `truncate` prop that caps width and adds
`text-overflow: ellipsis`; opt in.

**#5a — Reasoning-summaries setting had no effect on COT body.**
The settings toggle ("显示推理摘要 / Show reasoning summaries") flows
through to `SessionTurn` but only gated `showThinking`'s assistant-
visible counting and the secondary reasoning heading inside the
thinking row. `AgentRound` never received the prop, so reasoning
groups always rendered regardless of the toggle. Pass
`showReasoningSummaries` to `AgentRound` and drop `reasoning` groups
from the rendered output when it is explicitly `false`. The grouper
itself stays structural (does not know about user preferences); the
filter lives at the leaf consuming the groups, matching the existing
seam with `partState()` in `session-turn-helpers.ts`.
Astro-Han added a commit that referenced this pull request May 19, 2026
…hine

State machine: pending → resolved (tombstone, 30s TTL) → cleaned.
Exports: register, lookup, resolveIfPending, failIfPending, hasPending,
onSessionDestroyed. Cleanup is on-lookup (no timer thread); the clock
is injectable for tests.

Semantic split (addresses v10 round-3 P2 #4): onSessionDestroyed fires
only on server shutdown / session delete and rejects pending Deferreds
with `ExternalResultError({reason: "shutdown"})`. User turn aborts will
flow through ctx.abort → failIfPending with reason: "aborted" — wired
in a later commit. The two paths never overlap; reason is always
"aborted" XOR "shutdown" XOR completed-normally.

Registry semantics (addresses v10 round-2 P2 #1): hasPending counts
only pending entries (tombstones excluded); resolveIfPending returns a
discriminated outcome ("resolved" / "already_resolved" / "not_found")
that the route maps to 200 / 409 / 404. Within the 30s tombstone window
a retry of the same user gesture sees the deterministic 409 instead of
a 404 race.

No consumers yet (route, ctx.externalResult, session-destroy hook all
come in later commits).

Part of #756 PR A.
Astro-Han added a commit that referenced this pull request May 19, 2026
Wires ExternalResult.onSessionDestroyed into the existing
Session.clearPendingInteractions path that already tears down the
Question/Permission/SessionBlocker services on session delete and
session archive. Pending external-result Deferreds get rejected
with ExternalResultError({reason: "shutdown"}); tombstones are
dropped.

Per v10 semantic split (round-3 P2 #4): this hook does NOT fire on
turn abort or status transitions. Turn aborts route through
ctx.abort → failIfPending with reason: "aborted". So `reason:
"aborted"` and `reason: "shutdown"` never overlap.

Part of #756 PR A.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant