Commit Graph

38 Commits

Author SHA1 Message Date
shitratgit[bot] 80639a382a fix: bound flowing capture and retire old memory surfaces 2026-08-25 07:22:16 +00:00
shitratgit[bot] 4e7d6ec353 fix(web): remove undeployable local dependencies 2026-07-29 22:24:12 -07:00
shitratgit[bot] 60d5333730 fix(search): retire Typesense run projections 2026-07-29 19:10:22 -07:00
Joel Hooks 2dd747de22 feat: retire run_chunks_dev write path
Joel-approved cutover (2026-07-20): sessions.db is the only
full-transcript chunk index. The index-chunks Typesense import is
removed, ensureCollections no longer recreates run_chunks_dev, and the
stale web polling hint now points at joelclaw sessions search. Typesense
keeps runs_dev metadata for provenance and health.
2026-07-19 21:38:00 -07:00
shitratgit[bot] 4ca283b185 fix(web): point docs proxy fallback upstream at flagg, not panda
Panda is being decommissioned. The docs proxy's hardcoded fallback in
apps/web/app/api/docs/[[...path]]/route.ts pointed at panda's Tailscale
Funnel URL; it now falls back to flagg's docs-api Funnel URL instead.
DOCS_API_UPSTREAM_URL is already set in Vercel and points at flagg, so
this is behaviorally inert -- panda-decommissioning hygiene only.

"Deprecation can feel like the dirty work of cleaning up the street
after the circus parade has just passed through town, yet these
efforts improve the overall software ecosystem by reducing maintenance
overhead and cognitive burden of engineers." -- Software Engineering at
Google: Lessons Learned from Programming Over Time, Ch. 15 "Deprecation"

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 14:38:38 +00:00
shitratgit[bot] 5cc9423eb5 fix: require explicit Inngest event keys 2026-06-26 08:05:41 -07:00
Joel Hooks cafdf2b45e feat(memory): Phase 3 — PDS App Password auth (code-complete; verify pending infra)
Replaces the dev-bearer table with PDS-backed App Password authentication
per ADR-0243 Rule 20, scoped to single-user (Joel only) for now.

packages/system-bus/src/lib/pds.ts
  + pdsCreateAppPassword — calls com.atproto.server.createAppPassword on
    the caller's session; returns { name, password, did, handle }
  + pdsRevokeAppPassword — revokes by name
  + pdsValidateAppPassword — one-shot validation via createSession; used
    at register time only, NOT per-request (hash lookup is cheaper +
    safer, and doesn't create server-side session state at PDS)

packages/memory/src/schemas/machines.ts — NEW Typesense schema for
  machines_dev collection: id, user_id, did, handle, machine_name,
  app_password_name, app_password_sha256, created_at, last_seen_at,
  revoked_at

apps/web/lib/memory-auth.ts — NEW auth middleware
  authenticateMemoryRequest(req) → MemoryIdentity | null
  Hot path: sha256(bearer) → Typesense machines_dev lookup →
    { user_id, machine_id, did, source: "app-password" }
  No PDS roundtrip per request. App Password validity is established
  at register time; the hash is the identity key thereafter.
  Dev-bearer fallback retained during transition (MEMORY_DEV_BEARER_TOKENS
  env var); effectively disappears when that var is empty in prod.
  Phase 3.5 TODO: users_dev collection (DID→user_id map is hardcoded for
  now).

apps/web/app/api/runs/*/route.ts — all 6 handlers now call
  authenticateMemoryRequest instead of the inline DEV_BEARER_TOKENS
  table + local authenticate() helper. Rule 4 privacy filtering is
  unchanged (still keyed on auth.user_id from the middleware).

scripts/joelclaw-machine-register.ts — NEW provisioning CLI
  Flow: load cached PDS session from ~/.joelclaw/pds-session.json →
  call com.atproto.server.createAppPassword → sha256(plaintext) →
  upsert machines_dev row → back up old auth.json → write new
  auth.json (0600) with the plaintext bearer. Ready to register Panda
  once the infra is back.

Verification status (pending Typesense reachability):
  [x] pds.ts compiles; curl-tested createAppPassword directly against
      PDS (returned valid password)
  [x] Bun fetch works against PDS directly (ruled out fetch-lib bugs)
  [x] All route handlers typecheck + biome clean
  [x] Auth middleware compiles
  [ ] End-to-end: register panda → POST /api/runs with new bearer →
      Run indexes → search returns it — BLOCKED on Colima SSH tunnel
      which is flapping (ssh 192.168.64.2:22 timing out; matches the
      2026-04-17 healer-suicide-loop memory note)

When infra comes back:
  TYPESENSE_API_KEY=<...> joelclaw-machine-register --name panda --user joel
  then POST /api/runs with the new bearer to confirm.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:12:04 -07:00
Joel Hooks 90e283ccdd feat(memory): GET /api/runs/forest + joelclaw-runs-tree — global pi-tree
Inspired by pi's /tree (badlogic/pi-mono). Pi's tree is per-turn within
one session; this one is per-Run across all sessions and all runtimes.
Every Run carries parent_run_id + root_run_id (Rule 3), so the forest
exists in the schema — we just didn't have a view.

apps/web/app/api/runs/forest/route.ts
  GET /api/runs/forest
    ?since=<epoch_ms>           default: 7d window
    ?runtime=pi,claude-code     comma-separated filter
    ?root_run_id=<id>           zoom into a subtree
    ?limit=<n>                  cap 1-250 (Typesense per_page max)

  Returns a flat list of Runs sorted by started_at + metadata for
  client-side tree assembly. Privacy-filtered by readable_by (Rule 4).

scripts/joelclaw-runs-tree.ts → ~/.bun/bin/joelclaw-runs-tree
  Terminal renderer with ANSI-colored runtime badges, box-drawing tree
  connectors, relative timestamps, turn counts, tag chips, intent
  clipped to 80 chars, clean sort order (started_at asc per bucket).

Orphan-root handling: a Run whose parent_run_id isn't in the result
set (trimmed by limit/since/runtime filters) becomes a visible root
rather than being dropped. Deterministic output.

Verified live:
  $ joelclaw-runs-tree --since=6h --limit=100
  3 Runs (3 roots) since 2026-04-19T20:09
  ├─ claude-code 22m ago 2t #phase1-v3
  │     third attempt with typesense key in env
  ├─ claude-code 21m ago 1t #smoke-e2e
  │     test
  └─ claude-code 18m ago 82t #smoke-e2e
        Explore the project at /Users/joel/Code/joelhooks/joelclaw…

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 19:09:44 -07:00
Joel Hooks 47188aebd2 feat(memory): Phase 1 slice — Run traversal endpoints
Adds the three GET traversal endpoints from ADR-0243 Rule 13 (D shape):

apps/web/app/api/runs/[id]/route.ts
  - GET: fetch the Run metadata row from runs_dev
  - Enforces Rule 4 at read time by checking readable_by.includes(caller)
  - 404 (not 403) on unauthorized — leaks zero information about existence

apps/web/app/api/runs/[id]/jsonl/route.ts
  - GET: stream the full jsonl transcript from NAS
  - Verifies readable_by on the Run row before streaming
  - 410 Gone if the blob is missing on disk (distinct from 404 "no Run")
  - Returns application/x-ndjson with Content-Length; zero buffering

apps/web/app/api/runs/[id]/descendants/route.ts
  - GET: walk a Run's subtree via root_run_id filter
  - Returns root + all descendants ordered by started_at ascending
  - Lets agents reconstruct a workload-rig DAG or a gateway session tree
    in one call

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 18:29:24 -07:00
Joel Hooks e269155fbe feat(memory): Phase 1 slice — POST /api/runs/search + E2E smoke script
Completes the Phase 1 ingest + retrieval loop per ADR-0243 build order step 7.

apps/web
  - new app/api/runs/search/route.ts — hybrid Typesense search with the
    full agent-first API surface (Rule 12 + 13):
      * Auto-applied privacy filters (user_id + readable_by) from the
        bearer token — NEVER from the request body (Rule 4)
      * Tag filters default to AND semantics
      * Modes: hybrid (default), semantic, keyword
      * Embeds the query at priority="query" so it preempts any pending
        ingest work in the Ollama queue (Rule 9a)
      * HATEOAS envelope with _links, next_actions, and timing breakdown
        (query_embed_ms, query_queued_ms, typesense_ms, total_ms)

scripts/memory-spike
  - new smoke-e2e.ts — full pipeline validation:
      1. POST /api/runs with a real claude-code jsonl fixture
      2. Poll Typesense for chunks matching the new run_id
      3. POST /api/runs/search filtered to the smoke-e2e tag
      4. Assert the ingested Run is findable
    Run against a live dev stack (Next.js on :3000, worker deployed,
    Typesense + Ollama + Inngest healthy).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 18:23:57 -07:00
Joel Hooks a02ece9702 feat(memory): Phase 1 slice — memory/run.captured + POST /api/runs
Adds the central ingest path for agent Run capture per ADR-0243 build order
steps 5 and 6:

packages/memory
  - src/schemas/runs.ts — Typesense `runs_dev` collection schema covering
    the full Run row from types.ts
  - src/nas.ts — blob writer honoring Rule 11 (user-partitioned paths);
    env var MEMORY_RUN_STORE defaults to ~/.joelclaw/runs-dev/ for local
    development, set to /nas/memory/runs in production

packages/system-bus
  - new memory/run.captured + memory/run.indexed event contracts
  - new functions/memory/run-captured.ts — receives event, loads jsonl
    from NAS (or inline payload), format-detects, chunks via per-turn
    chunker, embeds each chunk at ingest-realtime priority through
    @joelclaw/inference-router (so queries preempt), writes chunks to
    run_chunks_dev and Run row to runs_dev, emits OTEL + fanout indexed
    event; concurrency:4, retries:3; ensures collections exist idempotently
  - @joelclaw/memory added to dependencies

apps/web
  - new app/api/runs/route.ts — POST handler; dev bearer token auth
    (hardcoded allowlist, PDS flow lands Phase 3), writes jsonl to NAS
    via @joelclaw/memory writeRunBlob, fires memory/run.captured via
    HTTP to local Inngest, returns 202 HATEOAS envelope with run_id +
    _links + next_actions
  - @joelclaw/inference-router + @joelclaw/memory added to dependencies

Still v1 / dev scope:
  - Dev bearer token, not PDS App Password (Phase 3)
  - _dev collection suffix, will alias to run_chunks_current after cutover
  - No search endpoint yet (next slice)
  - No capture hooks yet (Phase 4)
  - No entity enrichment yet (Phase 6)

Typecheck clean, biome clean, 12 chunking tests still green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 18:21:35 -07:00
Joel Hooks 5d56dac230 Guard apps/web search top-hit access, route convex-content through canonical readers, and pass resourceId into the registry review FAB so apps/web/tsconfig compiles clean again 2026-03-08 20:49:22 -07:00
Joel Hooks 53207f60ca Add short ADR route aliases, resolve them to canonical Convex slugs, and redirect legacy full-slug ADR URLs 2026-03-07 21:55:25 -08:00
Joel Hooks 8a62b9b3ad Update /api/pi-mono and docs/web.md to replace the planned placeholder with real install steps for the public contributing-to-pi-mono skill and extension repo 2026-03-07 12:48:28 -08:00
Joel Hooks a9466b058e Implement pi-mono Restate corpus sync, expose public joelclaw.com discovery/search, and replace the bogus async /output hint with real workflow inspection 2026-03-07 11:48:41 -08:00
Joel Hooks 5deb2eebc9 feat(content): migrate adr/discovery reads to convex 2026-02-28 10:36:57 -08:00
Joel Hooks e0e1b0d257 delete: remove dogfooding discovery — exposes sensitive materials
Removed discovery note that referenced internal egghead infrastructure,
private Loom recording, and internal PR details.
2026-02-27 21:47:17 -08:00
Joel Hooks a5914ece57 feat: joelclaw webhook provider for Inngest event proxy
- /webhooks/joelclaw with HMAC-SHA256 signature verification
- Forwards events to self-hosted Inngest at localhost:8288
- Submit route signs requests with x-joelclaw-signature
- Removed duplicate /webhooks/inngest-event endpoint
- Added post:slug cacheTag for revalidation (FBP-4)
2026-02-27 16:45:11 -08:00
Joel Hooks 7338a5c815 feat(FBP-4): Cache invalidation after content-review edit 2026-02-27 16:36:37 -08:00
Joel Hooks 1f18980006 feat(FBP-1): Fix review submit route for Vercel → self-hosted Inngest 2026-02-27 16:21:34 -08:00
Joel Hooks 7f5129cb7b feat(CFP-5): Inngest function: content/review.submitted handler 2026-02-27 15:04:28 -08:00
Joel Hooks 8881242236 chore: biome auto-fix import ordering across repo 2026-02-27 14:55:43 -08:00
Joel Hooks 973cf3739c feat(CFP-4): cache invalidation endpoint
POST /api/revalidate with x-revalidation-secret header + { tag } body.
Calls revalidateTag() for on-demand ISR. 401 on bad secret, 400 on missing tag.
2026-02-27 14:34:52 -08:00
Joel Hooks acd0dcd1a3 move agent search to /api/search, remove /api/agent prefix
- /api/search now serves HATEOAS envelope for agents AND web UI
- Search dialog reads from .result.hits (envelope-aware)
- Updated /api discovery and layout comment
- Removed /api/agent/ directory
2026-02-26 18:48:50 -08:00
Joel Hooks 828bd65b1e api discovery: cacheLife max — only changes on deploy 2026-02-26 18:45:12 -08:00
Joel Hooks 43596db249 fix: separate cached data from NextResponse in /api route
use cache only works on serializable return values, not NextResponse objects
2026-02-26 18:44:09 -08:00
Joel Hooks bad43bf1b4 root /api discovery: cached HATEOAS map of all APIs, content, and agent tips 2026-02-26 18:42:41 -08:00
Joel Hooks cc36806768 agent search discovery: rich about/topics, sample searches for actual content 2026-02-26 18:31:08 -08:00
Joel Hooks 054c62515d agent search API: HATEOAS envelope, markdown snippets, Upstash rate limiting
- /api/agent/search?q={query} — agent-first search endpoint
- Public: blog posts, discoveries, ADRs
- Authenticated (Bearer): adds vault, memory, system log, transcripts
- HATEOAS discovery at /api/agent/search (no query)
- Upstash sliding window rate limit (60/min default)
- Updated layout HTML comment to reference agent APIs
2026-02-26 18:30:27 -08:00
Joel Hooks 8731d90199 Open docs API routes with generous Upstash limits 2026-02-26 16:42:30 -08:00
Joel Hooks 539bdc6016 Support Vercel KV env aliases for docs API rate limit 2026-02-26 16:34:25 -08:00
Joel Hooks adc33f3204 Add /api/docs proxy with Upstash rate limits 2026-02-26 16:29:54 -08:00
Joel Hooks c3b1c92590 adr: ADR-0114 researching — Elixir/BEAM/Jido migration evaluation
Full architecture analysis: what BEAM replaces natively, what doesn't map,
three migration strategies (full rewrite, hybrid, strangler), Jido framework
assessment, cost/benefit matrix, open questions. Status: researching.
2026-02-23 10:57:36 -08:00
Joel Hooks 6079824945 web: restore shiki highlighting and harden public search 2026-02-22 15:46:38 -08:00
Joel Hooks 39518c6c34 feat: Next.js best practices audit fixes (ADR-0108)
Error boundaries:
- app/error.tsx: route-level error recovery with reset button
- app/global-error.tsx: root layout failure handler with html/body

Loading skeletons:
- vault, memory, syslog, system, system/events, dashboard, voice
- Pulse shimmer matching each page's actual layout structure
- font-pixel labels for consistent dashboard aesthetic

Import aliases:
- Converted all relative imports (../../lib/, ../../../lib/) to @/*
- 40+ files across app/, components/site-header, components/mobile-nav
- tsconfig @/* alias was already configured, now actually used
2026-02-22 12:13:22 -08:00
Joel Hooks 0e6e1a6c85 refactor(review): generalize from ADR-only to universal content review
- Drop adrComments table, use contentResources + contentResourceResource
- New reviewComments.ts Convex functions (getByContent, addComment, etc)
- Rename Adr* components → Review* (review-gate, review-wrapper, etc)
- Move /api/adrs/submit-review → /api/review/submit
- Event: content/review.submitted (was adr/review.submitted)
- Props: contentId + contentType + contentSlug (was adrSlug)
- Add content-review.ts Inngest function in system-bus
- Registry renamed: adr-review → content-review
- listLinkedReviewComments query added to contentResources

ADR-0106. Zero data existed so schema migration was free.
2026-02-22 11:00:06 -08:00
Joel Hooks 6bff2cc455 feat(adr-review): ADR-0106 — inline paragraph comment system
- Convex adrComments table + 7 mutations/queries
- rehype-paragraph-ids plugin (content-hash anchoring)
- Review UI: comment drawer, review sheet, FAB, auth gate
- shadcn init (Tailwind v4) + registry.json
- Submit review API route (fires Inngest event)
- @/* path alias for imports
2026-02-22 10:38:59 -08:00
Joel Hooks 016dccc295 redesign: cool finds index — full titles, readable descriptions, compact cards
- Titles wrap fully instead of truncating
- Relevance text shows complete (no line-clamp)
- Date shown as relative time (2d ago) above title, not stealing width
- Single type badge (repo/article/video) replaces full tag list
- Source URL removed from index (shown on detail page)
- Tighter card spacing for better scan density
- Re-removed duplicate self-hosting discovery (also from Vault source)
2026-02-22 08:07:35 -08:00