c68b2303a0
Serves a localhost page in the pseudo-skill register with the reference markers as clickable buttons: clicks land in <workdir>/events.jsonl, a persistent Monitor tail wakes the session, the session rewrites page.html, and the browser live-reloads over SSE. Actions per marker: expand / show real code / explain / ask, plus a page-level ask box; anchors become forge deep-links when the project has a reachable remote; incidental findings are surfaced on the page as anchored notes. The port is configured in one place (the PORT constant atop scripts/server.py; --port overrides per run). Mechanics proven live against the aura repo before extraction into this skill.
120 lines
6.3 KiB
Markdown
120 lines
6.3 KiB
Markdown
---
|
||
name: explore
|
||
description: Use when the user wants to explore a project interactively in the browser — invoked as `/explore <project>` or when the user asks for a clickable/served pseudocode page. Serves a localhost page showing the project as commented pseudocode in the pseudo-skill register, with the reference markers rendered as clickable buttons; every click (expand / show real code / explain / ask, plus a free-text box) lands as an event that wakes the session through a Monitor back-channel, the session rewrites the page, and the browser live-reloads via SSE. Anchors become forge deep-links when the project has a web-reachable remote; incidental findings (doc/code drift, stale comments) are surfaced on the page itself as anchored finding notes.
|
||
---
|
||
|
||
# explore — interactive pseudocode browser
|
||
|
||
## Overview
|
||
|
||
`/explore <project>` turns the `pseudo` skill's register into a served,
|
||
clickable page. The user reads pseudocode in the browser and zooms by
|
||
clicking instead of typing: each marker is a button, each click wakes
|
||
the session, the session rewrites the page, SSE reloads the browser.
|
||
|
||
The loop:
|
||
|
||
```
|
||
browser click ──POST /event──▶ server.py ──append──▶ <workdir>/events.jsonl
|
||
│
|
||
Monitor "tail -F -n 0 events.jsonl"
|
||
│
|
||
this session
|
||
│
|
||
browser ◀──SSE "reload"── server.py ◀──mtime── rewrites <workdir>/page.html
|
||
```
|
||
|
||
Latency expectations are conversational, not app-like: every click costs
|
||
one thinking cycle. Tell the user this once at start.
|
||
|
||
## Moving parts
|
||
|
||
- `scripts/server.py` — stdlib localhost server. **The port is
|
||
configured in exactly one place: the `PORT` constant at the top of
|
||
this file.** A per-run override exists (`--port N`) for a second
|
||
concurrent instance; the constant is the default every instance
|
||
shares.
|
||
- `templates/page.html` — the page scaffold (CSS, click menu, ask box,
|
||
SSE client). Placeholders: `{{TITLE}}` (project name, appears in
|
||
tab and header), `{{HINT}}` (one line: what the project is + current
|
||
altitude), `{{CONTENT}}` (the pseudocode block, see content rules).
|
||
- Workdir `~/.cache/explore/<project-slug>/` — holds the generated
|
||
`page.html` and `events.jsonl`. Scratch, never committed, safe to
|
||
delete after the session.
|
||
|
||
## Start procedure
|
||
|
||
1. `mkdir -p ~/.cache/explore/<project-slug>`
|
||
2. Generate `<workdir>/page.html` from `templates/page.html`, filling
|
||
the three placeholders. `{{CONTENT}}` starts at the project's main
|
||
entry point (pseudo rule 9) unless the user pointed elsewhere.
|
||
3. Start the server in the background:
|
||
`python3 <skill-dir>/scripts/server.py <workdir>` (add `--port N`
|
||
only for a second concurrent instance).
|
||
4. Arm the back-channel as a persistent Monitor:
|
||
`tail -F -n 0 <workdir>/events.jsonl` (`-n 0` is load-bearing:
|
||
without it, stale events replay at arm time).
|
||
5. Give the user the URL the server printed.
|
||
|
||
## Content rules
|
||
|
||
The `pseudo` skill's Iron Law governs everything inside `{{CONTENT}}`:
|
||
anchor line first, one altitude per view, markers as pointing handles
|
||
explained inline (never a legend), data shapes beside control flow,
|
||
reduce/omit the rest. Read that skill's rules before generating the
|
||
first page. On top of it, the served medium adds:
|
||
|
||
- **Escape first, tag second.** `{{CONTENT}}` and every `.note` body
|
||
are substituted into HTML: escape `&`, `<`, `>` in all source and
|
||
pseudocode text before insertion (Rust is full of `Vec<T>`, `&mut`,
|
||
`a < b`), and only then wrap tokens in highlight spans. A stray `<`
|
||
swallows the rest of the page, including the SSE script.
|
||
- **Markers are buttons.** `[N]` renders as
|
||
`<button class="marker" data-marker="N">[N]</button>`. Expansions
|
||
introduce sub-markers (`4a`, `4b`) — the zoom is recursive.
|
||
- **Anchors are links.** When the project has a web-reachable forge
|
||
remote (Gitea/GitHub), every file anchor becomes an
|
||
`<a class="src" href="…#L10-L20" target="_blank" rel="noopener">`
|
||
deep-link. Verify the URL pattern once per project (curl the file
|
||
URL, expect 200) before emitting the first link; skip links when
|
||
there is no reachable remote.
|
||
- **Real code** (`code` action): a `.note.code` block at the marker —
|
||
caption line = linked `file:from–to` anchor, then the code verbatim
|
||
with light span highlighting (`.c` comments, `.k` keywords, `.s`
|
||
strings).
|
||
- **Explanations** (`explain` action): a `.note` block anchored at the
|
||
marker. Page-level `ask` answers go in a `<section id="qa">` between
|
||
the pseudocode and the menu div (question dimmed in `.q`, answer in
|
||
`.note`).
|
||
- **Findings.** Anything noticed in passing — doc/code drift, a stale
|
||
comment, a suspicious contract — is surfaced on the page itself: an
|
||
amber `.note.finding` (⚠) anchored at the spot with deep-links to
|
||
the evidence, and a wavy `.warn` span (with `title` tooltip) on the
|
||
stale phrase where it is displayed. A one-line chat mention suffices
|
||
beside it; filing a tracker issue stays a separate ask.
|
||
- **Language.** Scaffold and pseudocode are English (repo register).
|
||
Answers to `ask` events are written in the user's language.
|
||
|
||
## Handling events
|
||
|
||
Each Monitor line is one click: `{marker, action, text?, ts}`
|
||
(`marker: null` = page-level; `text` only on `ask`). Respond by
|
||
rewriting `<workdir>/page.html` — the SSE watcher reloads the browser
|
||
automatically, so the rewrite IS the reply. Every rewrite MUST
|
||
preserve the full template scaffold: the SSE `<script>` (EventSource +
|
||
reload listener), the `#menu` div, and the `#ask` form — after each
|
||
reload that script is what re-binds every marker button. Edit only the
|
||
pseudocode, the anchored notes, and the `#qa` section; dropping the
|
||
scaffold silently kills the loop. Read the real source
|
||
before expanding or explaining; keep each response at the altitude the
|
||
click asked for. Batch related edits into as few writes as possible
|
||
(each write triggers a visible reload).
|
||
|
||
## Stop
|
||
|
||
`TaskStop` the server task and the Monitor. The workdir is scratch and
|
||
may be deleted. To switch projects: stop the server, start it again on
|
||
the new project's workdir, and re-arm the Monitor on the NEW workdir's
|
||
`events.jsonl` — server and monitor are both bound to one workdir at
|
||
startup, so neither survives a workdir switch.
|