Skip to content

Track Pi agent sessions with Entire - #119

Closed
elviskahoro wants to merge 46 commits into
LineIndent:mainfrom
elviskahoro:conductor/pi-agent-add
Closed

elviskahoro wants to merge 46 commits into
LineIndent:mainfrom
elviskahoro:conductor/pi-agent-add

Conversation

@elviskahoro

Copy link
Copy Markdown
Collaborator

Why

Pi had no integration in this repo, so Entire could not checkpoint, capture transcripts, or offer rewind/resume for Pi sessions here — while Claude Code already had it (#120).

What

Installs the official Entire extension for Pi via entire agent add pi, which generates .pi/extensions/entire/index.ts (auto-generated; do not edit manually). The extension forwards Pi lifecycle events (session_start, before_agent_start, agent_end, session_shutdown) to entire hooks pi <event> so Entire can create checkpoints, capture transcripts, and offer rewind/resume.

Verification

  • entire agent list now shows ✓ pi (was unlisted).
  • Ran pi -p "Reply with exactly: OK" in this repo: no extension load errors.
  • entire session list shows the tracked session: Pi · glm-fast-latest · port-of-spain · session 01a1400b… — end-to-end proof the hooks fire.
  • roborev review (job 2372): "The commit fully achieves its stated intent." Two findings (stdin error-handler, skill-arg capture) live upstream in Entire's auto-generated template — dispositioned as won't-fix here since the file is installer-generated and identical copies are committed in wedding/marcelladotdev/sdk-python-attio-v1.

Matches the precedent from wedding: 84a2449 "feat: add Entire CLI integration plugins for OpenCode and Pi".

detail-app Bot and others added 30 commits October 2, 2026 21:42
Co-authored-by: detail-app[bot] <180357370+detail-app[bot]@users.noreply.github.com>
…ed, toBase62) (#5)

Co-authored-by: detail-app[bot] <180357370+detail-app[bot]@users.noreply.github.com>
Co-authored-by: detail-app[bot] <180357370+detail-app[bot]@users.noreply.github.com>
Co-authored-by: detail-app[bot] <180357370+detail-app[bot]@users.noreply.github.com>
Co-authored-by: detail-app[bot] <180357370+detail-app[bot]@users.noreply.github.com>
Co-authored-by: detail-app[bot] <180357370+detail-app[bot]@users.noreply.github.com>
Co-authored-by: detail-app[bot] <180357370+detail-app[bot]@users.noreply.github.com>
Co-authored-by: detail-app[bot] <180357370+detail-app[bot]@users.noreply.github.com>
Co-authored-by: detail-app[bot] <180357370+detail-app[bot]@users.noreply.github.com>
Fixes copy buttons in chart_util_wrapper and file_codeblock being
absolutely positioned without a positioned ancestor, which caused
them to anchor to the page root instead of the codeblock. Matches
the pattern already used in demo_wrapper. Closes AI-342.
Collapsible panels snap open and closed because the height state selectors have no transition. Match Accordion timing so both interactions animate consistently.
* chore: remove dead menu.py constants and type aliases

* Regenerate menu.md after dead-code removal

---------

Co-authored-by: detail-app[bot] <180357370+detail-app[bot]@users.noreply.github.com>
* chore(tools): add gtm-linear and issue-fetch CLI

gtm-linear is a Python SDK with no executable, so
scripts/linear_cli.py wraps LinearWorkflow as read-only
commands (viewer/teams/issues/issue/search) for fetching
Linear issues. Auth resolves LINEAR_API_KEY from env or
gitignored .env.local.

* refactor(tools): port Linear CLI to Typer

Type-hint-driven commands, enum state choices, rich --help,
typer.echo/secho output. Typer added as a dev dependency.

* fix(tools): harden Linear CLI after review

- Disable Typer pretty exceptions (locals in tracebacks could
  expose the API key)
- One _fail() error style for all failure paths
- Bound --limit to 1-100 via option validation instead of
  silent clamping
- Add CliRunner tests covering state enum, exit codes, auth
  failure, and LinearAPIError mapping

* test(tools): tighten Linear CLI tests after review

Assert main() prints the API error to stderr, cover
ValidationError handling with from_env patched, document
the verified settings sources on the missing-key test, use
result.output directly (click 8.2+ interleaves stderr), note
the --limit validation behavior in the CLI docstring.

* test(tools): finish Linear CLI test polish after review

Clear every LINEAR_* env var in the missing-key smoke test,
drop the version-pinned comment, add a case proving
unrelated from_env exceptions are not misreported.

* test(tools): match LINEAR_ env vars case-insensitively

pydantic-settings resolves env names case-insensitively;
also assert the original exception message survives and
document why ValueError guards a ValidationError regression.
…es (#23)

Co-authored-by: detail-app[bot] <180357370+detail-app[bot]@users.noreply.github.com>
* Prevent external links from being routed as internal pages

* Keep generated attachment docs aligned with link behavior
The Pullfrog workflow failed with "no API key found" — no provider
credentials were configured in GitHub Actions secrets.

Route Pullfrog runs to Fireworks GLM 5.3 (the same model roborev uses
for reviews in gtm-sdk, accounts/fireworks/models/glm-5p3) via BYOK:

- Pin the agent model with a raw models.dev specifier
  (fireworks-ai/accounts/fireworks/models/glm-5p3) on the pullfrog
  action's `model` input.
- Map FIREWORKS_API_KEY from GitHub Actions secrets into the run env.

FIREWORKS_API_KEY has been added as a repo secret. The Pullfrog
console model must be set to "Custom (set in workflow)" so the stored
console pick does not override the workflow's model input.
Replace the AGPL-licensed wrapper with MIT-licensed class utilities so generated frontend dependencies match the project license.
* Prevent documentation crashes from negative order values

* Prevent documentation crashes from mixed order values
Font selections beyond the old five-slot range were being packed into adjacent seed digits, so opening their shared URLs could silently produce another font and style. Deriving codec radices from the registries keeps the browser, shuffle, and CLI aligned. The unversioned format expansion may remap older 9-character URLs; the changelog and regression coverage make that accepted compatibility break explicit.
elviskahoro and others added 16 commits October 5, 2026 07:39
* Let users customize inputs without fighting default styles

Inputs ignored the shared unstyled contract, forcing consumers to override design-system defaults for custom designs. Use CoreComponent class handling to support unstyled inputs and standard class merging.

* Keep generated input docs aligned with styling behavior
Issue #40 reports that the default ImportVar package path can produce an invalid package subpath. Set the package path explicitly and verify the import propagated by the shared CN function.
* Restore tooltip centering on custom render targets

TooltipTrigger dropped its default centering classes whenever callers supplied render_, leaving native div and anchor targets uncentered. Keep render_ replacement semantics for components by default and opt TooltipTrigger into forwarding its defaults. Regression coverage checks emitted props, custom classes, the unstyled escape hatch, and unaffected render targets.

* Keep generated docs aligned with the generator
* Prevent context-menu submenus from being clipped

Keep submenu positioners outside the parent popup overflow context so larger submenu content remains visible.

* Keep generated context-menu docs in sync

The docs artifact embeds the submenu example and needs regeneration when its composition changes.

* Keep context-menu docs aligned with submenu anatomy

Ensure the hand-written and generated docs show the portal wrapper, and validate anatomy compositions in CI.
* Keep documentation paths independent of the working directory

* Keep remaining docs tooling rooted in the repository
* Restore FieldSeparator support for documented children usage

* Keep generated FieldSeparator docs in sync with the fix
* Keep block copy feedback from removing the terminal icon

* Remove redundant block-card test helper
* Unblock ES module consumers of cn()

Reflex defaults omitted ImportVar package paths to a trailing slash, which Node.js ES module imports reject and prevents cn() from working in consumers.

* Name cn import regression test after core module

* Assert compiled class-merge imports in core test
* Keep the ClientStateVar form-state example usable and documented

* Align the form example annotation with its live demo

* Make the form-state regression test resilient to formatting

* Keep the ClientStateVar guide and generated docs in sync
A later alphabetical sort overrode the frontmatter ordering authored for component and chart docs. Keep order as the primary key and title as a deterministic tie-breaker.
* Restore dataset switching in dynamic chart demos

Native option click handlers do not fire when browser dropdown selections change, leaving each dynamic chart stuck on its initial data.

* Update generated chart docs and selector tests
* Keep compact button icons visually balanced

Unsized SVGs looked oversized in 28px icon-sm buttons because they inherited a 16px default. Use a balanced 14px default and keep generated docs and regression checks aligned with the component.

* Generalize component install snippet sync coverage

* Limit install sync checks to generated snippets
Agent sessions here left no searchable history or checkpoints. Install
the claude-code agent hooks, git-ref checkpoints (synced to origin),
and the graph and brain plugins with shared agent instructions in
AGENTS.md/CLAUDE.md. Telemetry is opted out, matching the ai repo
setup.
Pi had no integration in this repo, so Entire could not checkpoint or
rewind Pi sessions here. Install the official extension via
'entire agent add pi' so Pi lifecycle events are forwarded to
'entire hooks pi <event>' for checkpoints, transcripts, and rewind/resume.
elviskahoro added a commit that referenced this pull request Oct 25, 2026
<!-- entire-trail-link-start -->
https://entire.io/gh/elviskahoro/buridan-ui/trails/5
<!-- entire-trail-link-end -->

## What

`pullfrog-approval` (Pullfrog's AI review verdict) is now a **required
check in both enforcement layers**:

- **GitHub side** — ruleset `main - PR requirements` plus classic branch
protection on `main`, both pinned to the Pullfrog app (id 1768019).
`enforce_admins` and the strict up-to-date policy are unchanged. This
blocks direct merges and gates **Trunk merge queue admission** (the
queue only admits PRs GitHub considers mergeable).
- **Trunk queue side** — added to `.trunk/trunk.yaml`
`merge.required_statuses`, so the queue also waits for a **fresh
Pullfrog verdict on the exact merge state it tests**, not just the PR
head at admission.

## Why it is safe to require during queue testing

The queue tests in **draft-PR mode**: trunk-io opens a draft PR from the
`trunk-merge/**` branch, and Pullfrog auto-reviews draft PRs
(`review.drafts` on; the trunk-io app is not in Pullfrog's bot-exclusion
list, which covers
Dependabot/Renovate/Greenkeeper/Snyk/`github-actions[bot]`/changesets).
So `pullfrog-approval` posts on the tested head and the queue
requirement is satisfiable.

The comment in `trunk.yaml` and the paragraph in `AGENTS.md` document
the load-bearing assumptions: if a queue entry ever stalls on a missing
`pullfrog-approval`, check (1) the queue is still in draft-PR mode, (2)
Pullfrog is still reviewing queue draft PRs, (3) the Pullfrog run itself
didn't fail or get cancelled — a failed run posts no check.

## Effects to know

- New PRs: Pullfrog auto-reviews on open and re-reviews on push, so the
check lands on every head automatically. Unresolved Pullfrog feedback
fails the check and blocks the merge — that is the point.
- Queue submissions: the queue now waits for Pullfrog's verdict on the
tested merge state before landing, adding one LLM review (typically a
few minutes, PR-size dependent) per queue test.
- Existing open PRs whose heads were last reviewed before the
approval-check toggle was enabled (e.g. #119, #118, #114, #113, #112,
#108, #107) show `pullfrog-approval` as *Expected — waiting for status*.
Unblock with a one-off `@pullfrog review` comment or a new push.
- If a Pullfrog run fails or is cancelled, no check posts on that head
and the merge/queue stays blocked until the next run reports (documented
Pullfrog behavior).
- A negative verdict on the tested merge state fails the check and
ejects the PR from the queue — address the feedback, push to the
original PR, and resubmit; the new submission opens a new draft PR,
which gets a fresh verdict. No human override exists short of editing
the config.

## Verification

- The GitHub-side gate is verified live on this PR: #126 sat `BLOCKED`
with all CI green while Pullfrog's review was running, cleared once
`pullfrog-approval: SUCCESS` posted, and blocked again on the new
merge-commit head until re-review — exactly the intended per-commit
gate. PR #125 also merged (13:56Z, after the rule went live) with
`pullfrog-approval: SUCCESS` among its checks.
- The queue-side requirement is verified by this PR's own queue run: the
queue reads `required_statuses` from `main`'s trunk.yaml, so #126 is
tested under the old three-check list while Pullfrog independently
auto-reviews the queue's draft PR. During Testing, `gh pr checks
<draft-pr>` will show whether `pullfrog-approval` posts on the
`trunk-merge/**` head. If it does not, the queue entry is cancelled
before landing and the `required_statuses` addition is reverted; if it
does, that evidence is the confirmation the new config is safe for
future submissions.
elviskahoro added a commit that referenced this pull request Oct 25, 2026
…ment (#119)

**Detail bug report:** [View on
Detail](https://app.detail.dev/org_d38a878f-9df9-4c4b-a96a-f5180b860085/bugs/bug_4375577e-69b1-42f0-ba52-a019cfccbfd9)

Closes #117

## Bug

The documentation TOC scrollspy never highlighted the active heading.
`setActive(id)` in `app/templates/toc.py` compared each link's full
rendered `href` against the bare fragment `"#" + id`:

```js
link => link.getAttribute('href') === '#' + id
```

But TOC entries render through `rx.el.a`, which is a React Router
`<Link>`. React Router renders a hash-only `to` (e.g. `"#dev"`) as an
`<a>` whose `href` is path-prefixed (e.g.
`/docs/getting-started/dev#dev`). The equality was therefore never true,
so no `.toc-link` was ever marked `data-active="true"` — clicking a TOC
entry still scrolled, but never highlighted, and scrolling through a
page never highlighted the corresponding entry.

This was introduced in `5efe74b` (PR #75), which replaced the original
substring selector
`document.querySelector(\`.toc-link[href*="#${id}"]\`)` with the
exact-`===` comparison to fix a `dev`-vs-`dev.py` prefix collision. That
over-corrected a partial mis-highlight into a total loss of highlight,
and the accompanying static-only test baked in the buggy shape, giving a
false green.

## Fix

Compare the rendered href's trailing fragment against `id`, matching
what the click/scroll handlers already do:

```js
link => link.getAttribute('href').split('#')[1] === id
```

This compares the actual rendered fragment (`dev` vs `dev.py`), so
`setActive("dev")` highlights the `#dev` link rather than nothing, and
`setActive("dev.py")` still highlights `#dev.py` (the `dev`-vs-`dev.py`
prefix collision from #75 stays resolved). It also removes the
inconsistency the report flagged: `setActive` now interprets the
rendered href the same way the click/scroll paths already did.

## Testing

The scrollspy is embedded JS executed under React Router at runtime, so
static source-shape checks alone cannot catch this regression (the
original tests gave a false green). Added runtime coverage that
exercises the real `setActive` source under a production-shaped React
Router renderer:

- **Static shape tests** (`tests/test_toc_scrollspy.py`): assert the
comparison uses `getAttribute('href').split('#')[1] === id` (either
operand order), forbids `querySelector`/attribute-substring selectors,
and forbids `includes`/`indexOf`/`startsWith`/`endsWith` — keeping the
#75 collision from reappearing.
- **Runtime jsdom + react-router-dom test**: renders `<Link
to="#dev.py">` before `<Link to="#dev">` (the ordering that exposes the
#75 collision) via `createBrowserRouter` + `RouterProvider` in jsdom at
the production pathname, then runs the **real** `setActive` source
extracted from `toc.py` and asserts the rendered hrefs are path-prefixed
and that `setActive("dev")` → `#dev` and `setActive("dev.py")` →
`#dev.py`. The harness deps are pinned to `reflex.lock/package.json`
versions in `tests/toc_scrollspy_repro/` (`npm ci` to install; test
skips with an instruction if deps or Node are absent).

Verification:
- Unit tests, typecheck (`uv run pyright`), and lint/format (`ruff`) all
pass; the full suite is 825 passed.
- Mutation-checked the suite: reverting to the buggy `=== '#' + id`
fails both the static and runtime tests (`after_dev == None`); reverting
to the original substring selector fails the runtime test (`after_dev ==
'devpytoc'`, the #75 collision) and the no-selector static test. Neither
regression can recur silently.
- End-to-end in real Chromium via Playwright against the running Reflex
docs app on the `dev.md` page (which has both `# dev.py` and `## Dev`
headings): all 12 `.toc-link` hrefs are path-prefixed
(`/docs/getting-started/dev#<id>`); clicking `#dev` highlights "Dev" and
clicking `#dev.py` highlights "dev.py"; scrolling each heading into the
IntersectionObserver's active band highlights the matching entry;
reloading with `#dev` scrolls to and highlights "Dev" on mount. The
`dev`-vs-`dev.py` prefix collision is resolved in the real browser.

---
_Automatic Fixes PRs can be [configured
here](https://app.detail.dev/org_d38a878f-9df9-4c4b-a96a-f5180b860085/settings/repos/repo_04b9d58c-daa0-46b6-9560-7f39569ec6eb/bugs)._

---------

Co-authored-by: detail-app[bot] <180357370+detail-app[bot]@users.noreply.github.com>
Co-authored-by: elvis kahoro <github@elvis.ai>
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