stabilize live api memory and add an options pipeline explainer #8

Open
dirtydishes wants to merge 6 commits from stabilize-live-api-memory into main
9 changed files with 559 additions and 24 deletions
Showing only changes of commit 6584f7d154 - Show all commits

View file

@ -1,3 +1,4 @@
{"_type":"issue","id":"islandflow-3o0","title":"address forgejo issue #10 security dependency cves","description":"Track remediation for Forgejo issue #10 (2026-05-23 security CVE triage): upgrade dependency chain to resolve tar/ws/postcss/tmp advisories, validate with bun audit and relevant quality gates.","status":"closed","priority":1,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-23T16:59:34Z","created_by":"dirtydishes","updated_at":"2026-05-23T17:03:06Z","started_at":"2026-05-23T16:59:38Z","closed_at":"2026-05-23T17:03:06Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"islandflow-thp","title":"stabilize live api memory and reduce internal cache churn","description":"The native VPS deployment is repeatedly OOM-killing islandflow-api.service during live operation. The API live cache is retaining oversized channel histories and rewriting large Redis lists on every flush, which drives multi-GB Bun RSS and heavy loopback traffic between the API, Redis, NATS, and ClickHouse. Implement an emergency VPS mitigation plus repo hardening so unsafe env values, reconnect snapshots, and Redis persistence patterns cannot push the live API back into OOM.","acceptance_criteria":"1. VPS live cache env values are reduced to safe defaults and live redis state is cleared before restart. 2. services/api/src/live.ts enforces server-side live cache caps and clamps snapshot_limit accordingly. 3. Hot generic feed Redis persistence no longer rewrites entire lists on every flush. 4. Metrics/logging expose subscription counts, snapshot sizes, redis flush volume, and API memory trend. 5. Relevant tests pass and the deployment is restarted successfully.","notes":"Implemented and deployed the live-state hardening to the VPS. Final validation after restart showed the API around 120 MB RSS with capped live cache depths and clean systemd restarts.","status":"closed","priority":1,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-23T01:30:43Z","created_by":"dirtydishes","updated_at":"2026-05-23T01:50:41Z","started_at":"2026-05-23T01:30:52Z","closed_at":"2026-05-23T01:50:41Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"islandflow-sc6","title":"fix electron codex bridge preload loading","description":"Electron settings showed the browser-only Desktop Required fallback because the renderer did not see the native islandflowDesktop preload bridge or an Electron user-agent marker. Fix the desktop launch path so ChatGPT/Codex subscription controls are available inside Islandflow Desktop again.","notes":"Reopened after live Electron still showed the browser-only fallback. Follow-up fix adds an explicit preload runtime marker and web runtime detection for that marker so Electron is recognized even when the bridge is not ready and the user agent lacks an Electron token.","status":"closed","priority":1,"issue_type":"bug","owner":"dishes@dpdrm.com","created_at":"2026-05-20T23:42:58Z","created_by":"dirtydishes","updated_at":"2026-05-20T23:51:43Z","closed_at":"2026-05-20T23:51:43Z","close_reason":"Follow-up fix added an explicit islandflowDesktopRuntime preload marker and taught the web runtime to recognize that marker plus IslandflowDesktop user-agent tokens, so Electron no longer falls into the browser-only fallback when the AI bridge is delayed or unavailable. Desktop build and focused desktop/web tests pass; full web build still blocked by islandflow-c8f.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"islandflow-hj3","title":"Fix Electron preload for desktop AI bridge","description":"## Why\\nThe desktop settings page reports the native AI bridge as unavailable because Electron fails to load the preload script in local dev.\\n\\n## What\\nUpdate the desktop preload implementation/build so Electron can execute it, restore window.islandflowDesktop, and verify the Copilot settings panel detects the bridge again.\\n\\n## Acceptance Criteria\\n- Electron no longer logs a preload syntax error\\n- window.islandflowDesktop is available in the desktop renderer\\n- The settings page no longer shows bridge unavailable solely because preload failed\\n- Relevant desktop/web tests pass","status":"closed","priority":1,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-20T23:16:39Z","created_by":"dirtydishes","updated_at":"2026-05-20T23:20:20Z","started_at":"2026-05-20T23:16:48Z","closed_at":"2026-05-20T23:20:20Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
@ -20,6 +21,9 @@
{"_type":"issue","id":"islandflow-ayo","title":"Drop stale backlog events from live fanout","description":"Follow-up to live freshness rollout: /ws/live was still fanning out stale backlog events for freshness-gated channels, which kept tape panes in Live feed behind despite active synthetic ingest. Gate fanout and cache ingest by freshness for options/nbbo/equities/flow.","status":"closed","priority":1,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-04-28T21:26:39Z","created_by":"dirtydishes","updated_at":"2026-04-28T21:26:44Z","started_at":"2026-04-28T21:26:44Z","closed_at":"2026-04-28T21:26:44Z","close_reason":"Completed","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"islandflow-0v6","title":"Fix tape freshness, NBBO coverage, pause controls, and filter popup","description":"Implement the tape fixes requested for synthetic options notional sizing, strict live freshness, live-mode pause/resume behavior, stronger NBBO snapshot coverage, and moving flow filters behind a popup. Includes server-side live cache changes, web terminal state/UI changes, and tests for synthetic pricing, live snapshot freshness/NBBO retention, and live pause/filter interactions.","status":"closed","priority":1,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-04-28T21:02:52Z","created_by":"dirtydishes","updated_at":"2026-04-28T21:13:38Z","started_at":"2026-04-28T21:02:57Z","closed_at":"2026-04-28T21:13:38Z","close_reason":"Completed","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"islandflow-e4r","title":"Implement smart-money flow filtering and synthetic firehose modes","description":"Implement the approved multi-surface plan for named synthetic market profiles, options raw-vs-signal filtering, live/API filter contracts, Tape page client-side flow filters, firehose-readiness improvements, tests, and README updates.","status":"closed","priority":1,"issue_type":"feature","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-04-28T20:10:49Z","created_by":"dirtydishes","updated_at":"2026-04-28T20:29:29Z","started_at":"2026-04-28T20:10:53Z","closed_at":"2026-04-28T20:29:29Z","close_reason":"Implemented synthetic market profiles, options signal-path filtering, signal-aware API/replay contracts, Tape page filters, tests, and README updates. Follow-up tracked in islandflow-biq.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"islandflow-kgu","title":"Reconcile PR #8 branch with current main","description":"Why this issue exists and what needs to be done: user requested reconciliation for PR #8. Identify the PR #8 branch, merge/rebase with current main, resolve conflicts, validate, and push the updated branch so the PR can merge cleanly.","status":"in_progress","priority":2,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-23T20:14:36Z","created_by":"dirtydishes","updated_at":"2026-05-23T20:14:39Z","started_at":"2026-05-23T20:14:39Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"islandflow-l9h","title":"stop persisting non-signal option prints in clickhouse","description":"Why: non-signal option prints are storage noise and should not be persisted by default.\\n\\nWhat: add OPTIONS_PERSIST_SIGNAL_ONLY env flag (default true), gate option_print inserts in ingest-options, add tests for persistence behavior, update env examples, and document one-off cleanup SQL for existing non-signal rows.","status":"closed","priority":2,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-23T03:02:32Z","created_by":"dirtydishes","updated_at":"2026-05-23T03:06:34Z","started_at":"2026-05-23T03:02:35Z","closed_at":"2026-05-23T03:06:34Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"islandflow-2cj","title":"Add Forgejo-first agent workflow guidance to AGENTS.md","description":"Why this issue exists and what needs to be done:\\n- The repositorys canonical home is Forgejo at git.deltaisland.io, but AGENTS.md does not currently direct agents to prefer Forgejo-specific workflows.\\n- Update AGENTS.md so agents treat Forgejo as primary and use the fj CLI for pull request workflows.\\n- Keep existing Beads and completion instructions intact while clarifying remote preference and command usage.","status":"closed","priority":2,"issue_type":"task","owner":"dishes@dpdrm.com","created_at":"2026-05-23T02:51:31Z","created_by":"dirtydishes","updated_at":"2026-05-23T02:55:42Z","closed_at":"2026-05-23T02:55:42Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"islandflow-xc5","title":"One-time bidirectional git remote backfill between github and forgejo","description":"Perform a one-time sync so github and forgejo contain the same branch/tag refs and historical commits, including pre-transition github history and newer forgejo commits. Document exact commands and validation results.","status":"closed","priority":2,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-21T01:25:05Z","created_by":"dirtydishes","updated_at":"2026-05-21T01:26:19Z","started_at":"2026-05-21T01:25:16Z","closed_at":"2026-05-21T01:26:19Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"islandflow-y7b","title":"Fix false browser fallback in Electron renderer","description":"Why this issue exists and what needs to be done:\\nElectron sessions can briefly or permanently render browser-only fallback copy when runtime detection depends on async desktop AI state loading.\\n\\nImplement a runtime snapshot that is resolved synchronously on the client (shell marker + bridge presence) and kept independent from bridge.ai state fetch/subscribe behavior. Add bounded runtime resync/retry and lifecycle-triggered resync on focus/pageshow so late bridge exposure flips to desktop mode.\\n\\nUpdate desktop-ai tests to cover: runtime marker present before AI state resolves, bridge present with pending/rejected getState, and late runtime availability. Keep preload/IPC contract unchanged unless a verified failure requires it.","status":"closed","priority":2,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-21T00:06:52Z","created_by":"dirtydishes","updated_at":"2026-05-21T00:11:21Z","started_at":"2026-05-21T00:06:55Z","closed_at":"2026-05-21T00:11:21Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"islandflow-xtg","title":"implement ai alert copilot ux refinements","description":"Implement the AI alert Copilot UX plan: markdown result rendering, reusable task result states, in-session result caching with regenerate, task cancellation through the desktop bridge, tests, and required turn documentation.","status":"closed","priority":2,"issue_type":"feature","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-20T23:30:50Z","created_by":"dirtydishes","updated_at":"2026-05-20T23:37:58Z","started_at":"2026-05-20T23:30:58Z","closed_at":"2026-05-20T23:37:58Z","close_reason":"Implemented markdown Copilot rendering, session result caching, regenerate controls, task cancellation plumbing, tests, and turn documentation.","dependency_count":0,"dependent_count":0,"comment_count":0}

View file

@ -31,8 +31,8 @@ bd close <id> # Complete work
```bash
git pull --rebase
bd dolt push
git push
git status # MUST show "up to date with origin"
git push forgejo <branch>
git status # MUST show "up to date with forgejo/<branch>"
```
5. **Clean up** - Clear stashes, prune remote branches
6. **Verify** - All changes committed AND pushed
@ -69,6 +69,21 @@ Working style that avoids common problems here:
- Keep `.env` aligned with `.env.example`; adapters default to synthetic modes for local development.
- Dev runners persist child PID state in `.tmp/`; if a previous run crashed, restart via the standard `bun run dev*` commands so stale processes are cleaned up.
## Forgejo Is Canonical
This repository's primary home is Forgejo:
- URL: `https://git.deltaisland.io/dirtydishes/islandflow`
- Git remote: `forgejo`
- Push target: `forgejo` (not GitHub)
Agent expectations:
- Prefer `git push forgejo <branch>` when publishing work.
- Treat GitHub as a mirror unless explicitly instructed otherwise.
- Use `fj` for Forgejo pull request workflows (create/view/update PRs).
- When sharing PR links in handoff, use the Forgejo PR URL.
## Required Turn Documentation
At the end of every completed implementation task, before final handoff, create a user-readable HTML document describing the work.
@ -134,8 +149,8 @@ A task is not complete until:
3. Relevant quality gates have passed or failures are documented
4. Changes are committed
5. `bd dolt push` succeeds
6. `git push` succeeds
7. `git status` shows the branch is up to date with origin
6. `git push forgejo <branch>` succeeds
7. `git status` shows the branch is up to date with `forgejo/<branch>`
For trivial changes, the document may be brief, but it must still exist and clearly explain what changed and how it was validated.

View file

@ -118,7 +118,7 @@
"@islandflow/observability": "workspace:*",
"@islandflow/storage": "workspace:*",
"@islandflow/types": "workspace:*",
"ws": "^8.18.3",
"ws": "^8.21.0",
"zod": "^3.23.8",
},
},
@ -129,7 +129,7 @@
"@islandflow/config": "workspace:*",
"@islandflow/observability": "workspace:*",
"@islandflow/types": "workspace:*",
"ws": "^8.18.3",
"ws": "^8.21.0",
"zod": "^3.23.8",
},
},
@ -142,7 +142,7 @@
"@islandflow/storage": "workspace:*",
"@islandflow/types": "workspace:*",
"@msgpack/msgpack": "^3.1.3",
"ws": "^8.18.3",
"ws": "^8.21.0",
"zod": "^3.23.8",
},
},
@ -165,6 +165,11 @@
},
},
},
"overrides": {
"postcss": "^8.5.15",
"tar": "^7.5.15",
"tmp": "^0.2.5",
},
"packages": {
"@clickhouse/client": ["@clickhouse/client@0.2.10", "", { "dependencies": { "@clickhouse/client-common": "0.2.10" } }, "sha512-ZwBgzjEAFN/ogS0ym5KHVbR7Hx/oYCX01qGp2baEyfN2HM73kf/7Vp3GvMHWRy+zUXISONEtFv7UTViOXnmFrg=="],
@ -202,7 +207,7 @@
"@electron/get": ["@electron/get@3.1.0", "", { "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "optionalDependencies": { "global-agent": "^3.0.0" } }, "sha512-F+nKc0xW+kVbBRhFzaMgPy3KwmuNTYX1fx6+FxxoSnNgwYX6LD7AKBTWkU0MQ6IBoe7dz069CNkR673sPAgkCQ=="],
"@electron/node-gyp": ["@electron/node-gyp@github:electron/node-gyp#06b29aa", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "glob": "^8.1.0", "graceful-fs": "^4.2.6", "make-fetch-happen": "^10.2.1", "nopt": "^6.0.0", "proc-log": "^2.0.1", "semver": "^7.3.5", "tar": "^6.2.1", "which": "^2.0.2" }, "bin": "./bin/node-gyp.js" }, "electron-node-gyp-06b29aa", "sha512-UJwi6aXMAiUaOvqPHVlMtCOLRa1QAU2SqYD9H07KHpN+I2mBoFuxP1HnUOkt86+j+/o/XyHpM7D33JFFQi/jfA=="],
"@electron/node-gyp": ["@electron/node-gyp@github:electron/node-gyp#06b29aa", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "glob": "^8.1.0", "graceful-fs": "^4.2.6", "make-fetch-happen": "^10.2.1", "nopt": "^6.0.0", "proc-log": "^2.0.1", "semver": "^7.3.5", "tar": "^6.2.1", "which": "^2.0.2" }, "bin": "./bin/node-gyp.js" }, "electron-node-gyp-06b29aa"],
"@electron/notarize": ["@electron/notarize@2.5.0", "", { "dependencies": { "debug": "^4.1.1", "fs-extra": "^9.0.1", "promise-retry": "^2.0.1" } }, "sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A=="],
@ -298,6 +303,8 @@
"@inquirer/type": ["@inquirer/type@1.5.5", "", { "dependencies": { "mute-stream": "^1.0.0" } }, "sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA=="],
"@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
"@islandflow/api": ["@islandflow/api@workspace:services/api"],
"@islandflow/bus": ["@islandflow/bus@workspace:packages/bus"],
@ -526,7 +533,7 @@
"chardet": ["chardet@0.7.0", "", {}, "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="],
"chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="],
"chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
"chrome-trace-event": ["chrome-trace-event@1.0.4", "", {}, "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ=="],
@ -818,7 +825,7 @@
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
"minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="],
"minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
"minipass-collect": ["minipass-collect@1.0.2", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA=="],
@ -830,7 +837,7 @@
"minipass-sized": ["minipass-sized@1.0.3", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g=="],
"minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="],
"minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="],
"mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="],
@ -838,7 +845,7 @@
"mute-stream": ["mute-stream@1.0.0", "", {}, "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA=="],
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
"nanoid": ["nanoid@3.3.12", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ=="],
"nats": ["nats@2.29.3", "", { "dependencies": { "nkeys.js": "1.1.0" } }, "sha512-tOQCRCwC74DgBTk4pWZ9V45sk4d7peoE2njVprMRCBXrhJ5q5cYM7i6W+Uvw2qUrcfOSnuisrX7bEx3b3Wx4QA=="],
@ -876,8 +883,6 @@
"ora": ["ora@5.4.1", "", { "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.5.0", "is-interactive": "^1.0.0", "is-unicode-supported": "^0.1.0", "log-symbols": "^4.1.0", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } }, "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ=="],
"os-tmpdir": ["os-tmpdir@1.0.2", "", {}, "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="],
"p-cancelable": ["p-cancelable@2.1.1", "", {}, "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg=="],
"p-defer": ["p-defer@1.0.0", "", {}, "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw=="],
@ -920,7 +925,7 @@
"plist": ["plist@3.1.1", "", { "dependencies": { "@xmldom/xmldom": "^0.9.10", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA=="],
"postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
"postcss": ["postcss@8.5.15", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A=="],
"postject": ["postject@1.0.0-alpha.6", "", { "dependencies": { "commander": "^9.4.0" }, "bin": { "postject": "dist/cli.js" } }, "sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A=="],
@ -1052,13 +1057,13 @@
"tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="],
"tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="],
"tar": ["tar@7.5.15", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-dzGK0boVlC4W5QFuQN1EFSl3bIDYsk7Tj40U6eIBnK2k/8ml7TZ5agbI5j5+qnoVcAA+rNtBml8SEiLxZpNqRQ=="],
"terser": ["terser@5.47.1", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-tPbLXTI6ohPASb/1YViL428oEHu6/qv1OxqYnfaonVCFHqx4+wCd95pHrQWsL5X4pl90CTyW9piSAsS2L0VoMw=="],
"terser-webpack-plugin": ["terser-webpack-plugin@5.6.0", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", "terser": "^5.31.1" }, "peerDependencies": { "webpack": "^5.1.0" } }, "sha512-Eum+5ajkaOhf5KbM26osvv21kLD7BaGqQ1UA4Ami4arYwylmGUQTgHFpHDdmJod1q4QXa66p0to/FBKID+J1vA=="],
"tmp": ["tmp@0.0.33", "", { "dependencies": { "os-tmpdir": "~1.0.2" } }, "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw=="],
"tmp": ["tmp@0.2.5", "", {}, "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow=="],
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
@ -1110,13 +1115,13 @@
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
"ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
"ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="],
"xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="],
"y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
"yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
"yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
"yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
@ -1184,6 +1189,8 @@
"ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
"cacache/chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="],
"cacache/glob": ["glob@8.1.0", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^5.0.1", "once": "^1.3.0" } }, "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ=="],
"cacache/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
@ -1224,14 +1231,14 @@
"minipass-fetch/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
"minipass-fetch/minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="],
"minipass-flush/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
"minipass-pipeline/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
"minipass-sized/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
"minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
"normalize-package-data/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="],
"npm-run-path/path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="],
@ -1272,6 +1279,8 @@
"cacache/glob/minimatch": ["minimatch@5.1.9", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw=="],
"cacache/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
"cliui/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"cliui/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
@ -1292,16 +1301,34 @@
"execa/cross-spawn/which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="],
"fs-minipass/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
"get-package-info/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
"log-update/ansi-escapes/type-fest": ["type-fest@1.4.0", "", {}, "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA=="],
"make-fetch-happen/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
"minipass-collect/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
"minipass-fetch/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
"minipass-fetch/minizlib/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
"minipass-flush/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
"minipass-pipeline/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
"minipass-sized/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
"ora/cli-cursor/restore-cursor": ["restore-cursor@3.1.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="],
"ora/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"read-pkg-up/find-up/locate-path": ["locate-path@2.0.0", "", { "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" } }, "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA=="],
"ssri/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
"yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"yargs/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],

View file

@ -0,0 +1,169 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>2026-05-22 - Forgejo Primary Agent Workflow</title>
<style>
:root {
--bg: #f6f7fb;
--panel: #ffffff;
--text: #19202a;
--muted: #516074;
--border: #d7dfeb;
--accent: #3559e0;
--code-bg: #0f172a;
--code-text: #e2e8f0;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: "Inter", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background: radial-gradient(circle at top, #eef2ff 0%, var(--bg) 48%);
color: var(--text);
line-height: 1.6;
}
main {
max-width: 960px;
margin: 2rem auto;
padding: 0 1rem 2rem;
}
.card {
background: var(--panel);
border: 1px solid var(--border);
border-radius: 14px;
padding: 1.25rem;
margin-bottom: 1rem;
box-shadow: 0 8px 26px rgba(22, 34, 60, 0.06);
}
h1, h2 { line-height: 1.25; margin: 0 0 0.65rem; }
h1 { font-size: 1.5rem; }
h2 { font-size: 1.1rem; color: var(--accent); }
p { margin: 0.35rem 0; }
ul { margin: 0.4rem 0 0.4rem 1.1rem; padding: 0; }
li { margin: 0.25rem 0; }
.meta { color: var(--muted); font-size: 0.92rem; }
pre {
margin: 0.6rem 0 0;
background: var(--code-bg);
color: var(--code-text);
border-radius: 10px;
border: 1px solid #1e293b;
padding: 0.9rem;
overflow-x: auto;
}
code { font-family: "JetBrains Mono", "SFMono-Regular", Menlo, Consolas, monospace; }
a { color: var(--accent); }
</style>
</head>
<body>
<main>
<section class="card">
<h1>Turn Documentation: Forgejo-First Agent Workflow in AGENTS.md</h1>
<p class="meta"><strong>Date:</strong> 2026-05-22 22:53 EDT</p>
<p class="meta"><strong>Beads Issue:</strong> islandflow-2cj</p>
</section>
<section class="card">
<h2>Summary</h2>
<p>
Updated <code>AGENTS.md</code> so agents explicitly treat Forgejo as the canonical home for this repository,
prioritize the <code>forgejo</code> git remote for pushes, and use the <code>fj</code> CLI for pull request workflows.
</p>
</section>
<section class="card">
<h2>Changes Made</h2>
<ul>
<li>Added a new <code>Forgejo Is Canonical</code> section to <code>AGENTS.md</code>.</li>
<li>Documented canonical repo URL, preferred remote name, and push target.</li>
<li>Added explicit expectations to use <code>fj</code> for PR create/view/update workflows.</li>
<li>Updated session completion and completion-rule text to require <code>git push forgejo &lt;branch&gt;</code>.</li>
</ul>
</section>
<section class="card">
<h2>Context</h2>
<p>
The repository is primarily hosted on Forgejo (<code>git.deltaisland.io</code>) with GitHub also configured.
Without explicit guidance, agents may default to GitHub tooling or ambiguous <code>git push</code> behavior.
This change removes that ambiguity so automation and handoffs consistently target Forgejo first.
</p>
</section>
<section class="card">
<h2>Important Implementation Details</h2>
<ul>
<li>The existing Beads integration block was preserved; only Forgejo preference guidance was added/clarified.</li>
<li>Push instructions now name the remote directly to prevent accidental mirror-only pushes.</li>
<li>PR tooling guidance now references <code>fj</code> to align with the primary Forgejo workflow.</li>
</ul>
</section>
<section class="card">
<h2>Relevant Diff Snippets</h2>
<p>
Snippets below use standard unified diff formatting compatible with tools like
<a href="https://diffs.com/docs">diffs.com</a>.
</p>
<pre><code class="language-diff">+## Forgejo Is Canonical
+
+This repository's primary home is Forgejo:
+
+- URL: `https://git.deltaisland.io/dirtydishes/islandflow`
+- Git remote: `forgejo`
+- Push target: `forgejo` (not GitHub)
+
+Agent expectations:
+
+- Prefer `git push forgejo &lt;branch&gt;` when publishing work.
+- Treat GitHub as a mirror unless explicitly instructed otherwise.
+- Use `fj` for Forgejo pull request workflows (create/view/update PRs).
+- When sharing PR links in handoff, use the Forgejo PR URL.
@@
- git push
- git status # MUST show "up to date with origin"
+ git push forgejo &lt;branch&gt;
+ git status # MUST show "up to date with forgejo/&lt;branch&gt;"
@@
-6. `git push` succeeds
-7. `git status` shows the branch is up to date with origin
+6. `git push forgejo &lt;branch&gt;` succeeds
+7. `git status` shows the branch is up to date with `forgejo/&lt;branch&gt;`</code></pre>
</section>
<section class="card">
<h2>Expected Impact for End-Users</h2>
<p>
End-users should see more consistent agent behavior around publish and review workflows: branches and PRs will be
created against Forgejo by default, reducing mistakes caused by mixed-remote assumptions.
</p>
</section>
<section class="card">
<h2>Validation</h2>
<ul>
<li>Manually reviewed <code>AGENTS.md</code> to confirm Forgejo guidance is explicit and internally consistent.</li>
<li>Confirmed completion-rule steps now specify <code>git push forgejo &lt;branch&gt;</code>.</li>
<li>No runtime/test suite changes were required because this is a documentation/process-only update.</li>
</ul>
</section>
<section class="card">
<h2>Issues, Limitations, and Mitigations</h2>
<ul>
<li>This change relies on agents having <code>fj</code> installed and authenticated; if unavailable, users may need to use web UI fallback.</li>
<li>Existing user habits around GitHub-first workflows may persist; explicit checklist wording mitigates this over time.</li>
</ul>
</section>
<section class="card">
<h2>Follow-up Work</h2>
<ul>
<li>Optionally add a short Forgejo contribution section in <code>README.md</code> with <code>fj</code> quickstart commands.</li>
<li>Optionally add a pre-push script check that warns when pushing to non-Forgejo remotes from feature branches.</li>
</ul>
</section>
</main>
</body>
</html>

View file

@ -0,0 +1,315 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Turn Report: Forgejo Issue #10 Security CVE Remediation</title>
<style>
:root {
color-scheme: dark;
--bg: #0c1220;
--panel: #121a2a;
--panel-2: #162238;
--text: #e8eefb;
--muted: #a7b5d6;
--accent: #76d3ff;
--accent-2: #9ecbff;
--border: #27344f;
--ok: #85e1b4;
--warn: #ffd599;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: "IBM Plex Sans", system-ui, -apple-system, Segoe UI, sans-serif;
background: radial-gradient(1200px 900px at 10% -10%, #1f2e4d 0%, var(--bg) 55%);
color: var(--text);
line-height: 1.6;
}
main {
max-width: 1100px;
margin: 0 auto;
padding: 2rem 1.2rem 3rem;
}
header {
background: linear-gradient(145deg, #1a2741, #121a2a);
border: 1px solid var(--border);
border-radius: 16px;
padding: 1.3rem 1.2rem;
margin-bottom: 1rem;
}
h1 {
margin: 0 0 0.35rem 0;
font-size: clamp(1.4rem, 2.6vw, 2rem);
letter-spacing: 0.02em;
color: #f1f6ff;
}
.meta {
color: var(--muted);
font-size: 0.95rem;
}
.chips {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
margin-top: 0.7rem;
}
.chip {
font-size: 0.82rem;
color: #d8e6ff;
border: 1px solid #355286;
background: #172443;
border-radius: 999px;
padding: 0.25rem 0.6rem;
}
.grid {
display: grid;
gap: 1rem;
}
section {
background: color-mix(in oklab, var(--panel) 86%, black);
border: 1px solid var(--border);
border-radius: 14px;
padding: 1rem;
}
h2 {
margin: 0 0 0.7rem 0;
font-size: 1.02rem;
color: #dbe8ff;
letter-spacing: 0.01em;
}
p { margin: 0.35rem 0; }
ul {
margin: 0.4rem 0 0;
padding-left: 1.15rem;
}
li + li { margin-top: 0.3rem; }
code {
font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
background: #0f1728;
color: #d7e7ff;
padding: 0.08rem 0.3rem;
border-radius: 4px;
border: 1px solid #2b3e63;
}
.callout {
margin-top: 0.7rem;
border: 1px solid #3b5178;
background: #13223a;
border-radius: 10px;
padding: 0.7rem 0.85rem;
color: #cfe1ff;
}
.good { color: var(--ok); }
.diff-grid {
display: grid;
gap: 0.85rem;
}
.diff-shell {
border: 1px solid #334c78;
border-radius: 10px;
overflow: hidden;
background: #0f1a2f;
}
.diff-title {
margin: 0;
padding: 0.55rem 0.7rem;
border-bottom: 1px solid #334c78;
color: #cfe2ff;
font-size: 0.9rem;
font-family: "IBM Plex Mono", ui-monospace, monospace;
background: #13223b;
}
.diff-view { padding: 0.3rem; }
.diff-fallback {
margin: 0;
padding: 0.75rem;
white-space: pre-wrap;
overflow-x: auto;
color: #d4e4ff;
font-family: "IBM Plex Mono", ui-monospace, monospace;
font-size: 0.84rem;
background: #0f1a2f;
border-top: 1px solid #253a60;
}
.diff-shell.rendered .diff-fallback { display: none; }
.note {
margin-top: 0.65rem;
color: var(--muted);
font-size: 0.9rem;
}
</style>
</head>
<body>
<main>
<header>
<h1>Forgejo Issue #10 Security CVE Remediation</h1>
<p class="meta">Created: 2026-05-23 13:08 America/New_York · Repo: <code>islandflow</code></p>
<div class="chips">
<span class="chip">Issue: Forgejo #10</span>
<span class="chip">Beads: islandflow-3o0</span>
<span class="chip">Scope: dependency security updates</span>
</div>
</header>
<div class="grid">
<section>
<h2>Summary</h2>
<p>Addressed Forgejo issue <code>#10</code> by remediating the active dependency CVEs called out in the report. This update moved direct WebSocket dependencies to patched versions and added workspace-level dependency overrides for vulnerable transitive packages. <code>bun audit</code> now reports <span class="good">No vulnerabilities found</span>.</p>
</section>
<section>
<h2>Changes Made</h2>
<ul>
<li>Upgraded <code>ws</code> in ingest services to <code>^8.21.0</code> in:
<code>services/ingest-equities/package.json</code>,
<code>services/ingest-news/package.json</code>, and
<code>services/ingest-options/package.json</code>.</li>
<li>Added workspace-level <code>overrides</code> in root <code>package.json</code> for patched transitive packages:
<code>postcss</code> <code>^8.5.15</code>,
<code>tar</code> <code>^7.5.15</code>, and
<code>tmp</code> <code>^0.2.5</code>.</li>
<li>Regenerated <code>bun.lock</code> via <code>bun install</code> to enforce the resolved secure graph.</li>
</ul>
</section>
<section>
<h2>Context</h2>
<p>Issue #10 documented 9 active advisories across runtime and build-time dependencies: six high-severity <code>tar</code> CVEs in the Electron Forge chain, one <code>ws</code> memory-disclosure advisory affecting ingest services, one <code>postcss</code> advisory in the web toolchain, and one <code>tmp</code> advisory in desktop packaging transitive dependencies.</p>
<div class="callout">This fix intentionally focused on targeted version remediation, not broad framework upgrades, to reduce behavior risk while closing the known CVE set.</div>
</section>
<section>
<h2>Important Implementation Details</h2>
<ul>
<li><code>next@16.2.6</code> still declares <code>postcss@8.4.31</code>, so override pinning was required to force a patched resolver result.</li>
<li>The Electron Forge chain currently references <code>tar@^6.x</code> transitively, so override pinning was used to pull patched <code>tar@7.5.15</code> and clear advisories without waiting for upstream major migration.</li>
<li>Direct <code>ws</code> bumps were applied at each ingest service manifest for explicit runtime dependency hygiene.</li>
</ul>
</section>
<section>
<h2>Relevant Diff Snippets</h2>
<div class="diff-grid">
<div class="diff-shell" id="diff-shell-1">
<p class="diff-title">package.json · security overrides</p>
<div class="diff-view" id="diff-1"></div>
<pre class="diff-fallback"><code>+ "overrides": {
+ "postcss": "^8.5.15",
+ "tar": "^7.5.15",
+ "tmp": "^0.2.5"
+ }</code></pre>
</div>
<div class="diff-shell" id="diff-shell-2">
<p class="diff-title">services/ingest-*/package.json · ws bump</p>
<div class="diff-view" id="diff-2"></div>
<pre class="diff-fallback"><code>- "ws": "^8.18.3"
+ "ws": "^8.21.0"</code></pre>
</div>
</div>
<p class="note">Snippets are rendered client-side with Diffs (diffs.com project) and include inline fallback text for offline viewing.</p>
</section>
<section>
<h2>Expected Impact for End-Users</h2>
<p>No user-facing behavior changes are expected. The impact is operational and security-focused: cleaner dependency posture and reduced known vulnerability exposure across ingest runtime and desktop/web toolchain surfaces.</p>
</section>
<section>
<h2>Validation</h2>
<ul>
<li><code>bun install</code> completed and regenerated <code>bun.lock</code>.</li>
<li><code>bun audit</code> passed with <code>No vulnerabilities found</code>.</li>
<li><code>bun test</code> passed: 246 tests, 0 failures.</li>
<li><code>bun --cwd=apps/web run build</code> passed (Next.js production build).</li>
<li><code>bun --cwd=apps/desktop run typecheck</code> passed.</li>
</ul>
</section>
<section>
<h2>Issues, Limitations, and Mitigations</h2>
<ul>
<li>This remediation relies partly on dependency overrides for transitive CVEs rather than upstream package-chain updates. Mitigation: lockfile is now pinned and validated via audit in CI/local runs.</li>
<li>Override-based mitigation can drift if upstream manifests change unexpectedly. Mitigation: keep <code>bun audit</code> in regular release checks.</li>
<li>This pass did not perform container image package CVE expansion, matching the issue's own stated scope limitation.</li>
</ul>
</section>
<section>
<h2>Follow-up Work</h2>
<ul>
<li>Track Electron Forge and rebuild-chain updates to remove the <code>tar/tmp</code> overrides once upstream dependencies natively resolve patched versions.</li>
<li>If additional image-level CVE coverage is required, run a dedicated Docker image scan in a daemon-enabled environment and file any new issues separately.</li>
<li>No additional Beads issue was created in this turn beyond <code>islandflow-3o0</code>.</li>
</ul>
</section>
</div>
</main>
<script type="module">
const snippets = [
{
shellId: "diff-shell-1",
containerId: "diff-1",
name: "package.json",
oldContents: `{
"devDependencies": {
"typescript-language-server": "^5.1.3"
}
}`,
newContents: `{
"devDependencies": {
"typescript-language-server": "^5.1.3"
},
"overrides": {
"postcss": "^8.5.15",
"tar": "^7.5.15",
"tmp": "^0.2.5"
}
}`
},
{
shellId: "diff-shell-2",
containerId: "diff-2",
name: "services/ingest-news/package.json",
oldContents: `"ws": "^8.18.3"`,
newContents: `"ws": "^8.21.0"`
}
];
try {
const { FileDiff } = await import("https://esm.sh/@pierre/diffs");
for (const snippet of snippets) {
const container = document.getElementById(snippet.containerId);
const shell = document.getElementById(snippet.shellId);
if (!container || !shell) {
continue;
}
const instance = new FileDiff({
theme: { dark: "pierre-dark", light: "pierre-light" },
diffStyle: "split"
});
instance.render({
oldFile: {
name: snippet.name,
contents: snippet.oldContents
},
newFile: {
name: snippet.name,
contents: snippet.newContents
},
containerWrapper: container
});
shell.classList.add("rendered");
}
} catch (error) {
console.warn("Failed to render diff snippets with Diffs.", error);
}
</script>
</body>
</html>

View file

@ -26,5 +26,10 @@
},
"devDependencies": {
"typescript-language-server": "^5.1.3"
},
"overrides": {
"postcss": "^8.5.15",
"tar": "^7.5.15",
"tmp": "^0.2.5"
}
}

View file

@ -11,7 +11,7 @@
"@islandflow/observability": "workspace:*",
"@islandflow/storage": "workspace:*",
"@islandflow/types": "workspace:*",
"ws": "^8.18.3",
"ws": "^8.21.0",
"zod": "^3.23.8"
}
}

View file

@ -10,7 +10,7 @@
"@islandflow/config": "workspace:*",
"@islandflow/observability": "workspace:*",
"@islandflow/types": "workspace:*",
"ws": "^8.18.3",
"ws": "^8.21.0",
"zod": "^3.23.8"
}
}

View file

@ -12,7 +12,7 @@
"@islandflow/storage": "workspace:*",
"@islandflow/types": "workspace:*",
"@msgpack/msgpack": "^3.1.3",
"ws": "^8.18.3",
"ws": "^8.21.0",
"zod": "^3.23.8"
}
}