Informe JSON sin procesar legible por máquina
{
"data": {
"repo": {
"topics": [
"ai",
"antigravity",
"claude-code",
"coding-assistant",
"developer-tools",
"golang",
"multiplexer",
"opencode",
"pty",
"terminal",
"websocket",
"xterm-js"
],
"is_fork": false,
"size_kb": 10425,
"has_wiki": true,
"homepage": null,
"languages": {
"Go": 645412,
"CSS": 193820,
"HTML": 38312,
"Shell": 3311,
"JavaScript": 1125260,
"TypeScript": 286262,
"Vim Script": 57022
},
"pushed_at": "2026-07-27T07:57:27Z",
"created_at": "2026-05-31T09:37:34Z",
"owner_type": "User",
"updated_at": "2026-07-27T07:58:35Z",
"description": "Φ phi — a terminal multiplexer and browser-based control center for AI coding assistants (OpenCode, Claude Code, Antigravity, Pi Coder).",
"is_archived": false,
"is_disabled": false,
"license_spdx": null,
"default_branch": "main",
"license_spdx_raw": null,
"primary_language": "JavaScript",
"significant_languages": [
"JavaScript",
"Go",
"TypeScript"
]
},
"owner": {
"blog": "https://uaasoftware.bitbucket.io/",
"name": "Xi Ma Chen",
"type": "User",
"login": "hypernewbie",
"company": "UAA Software",
"location": "Mountain View, California",
"followers": 37,
"avatar_url": "https://avatars.githubusercontent.com/u/5387547?v=4",
"created_at": "2013-09-05T02:31:30Z",
"is_verified": null,
"public_repos": 43,
"account_age_days": 4708
},
"license": {
"state": "absent",
"spdx_id": null,
"raw_spdx": null,
"file_present": false,
"scorecard_found": false,
"profile_has_license": false
},
"activity": {
"releases": [
{
"tag": "v0.15.1",
"kind": "patch",
"published_at": "2026-07-27T04:47:30Z"
},
{
"tag": "v0.14.4",
"kind": "patch",
"published_at": "2026-07-26T06:34:01Z"
},
{
"tag": "v0.14.3",
"kind": "patch",
"published_at": "2026-07-24T04:05:43Z"
},
{
"tag": "v0.14.2",
"kind": "patch",
"published_at": "2026-07-22T08:12:51Z"
},
{
"tag": "v0.14.1",
"kind": "patch",
"published_at": "2026-07-22T03:34:35Z"
},
{
"tag": "v0.14.0",
"kind": "minor",
"published_at": "2026-07-22T03:22:53Z"
},
{
"tag": "v0.13.0",
"kind": "minor",
"published_at": "2026-07-21T08:58:27Z"
},
{
"tag": "v0.12.1",
"kind": "patch",
"published_at": "2026-07-19T05:14:13Z"
},
{
"tag": "v0.12.0",
"kind": "minor",
"published_at": "2026-07-19T03:50:16Z"
},
{
"tag": "v0.11.0",
"kind": "minor",
"published_at": "2026-07-16T23:43:22Z"
},
{
"tag": "v0.10.1",
"kind": "patch",
"published_at": "2026-07-15T07:02:17Z"
},
{
"tag": "v0.10.0",
"kind": "minor",
"published_at": "2026-07-15T04:13:24Z"
},
{
"tag": "v0.9.2",
"kind": "patch",
"published_at": "2026-07-14T08:55:42Z"
},
{
"tag": "v0.9.1",
"kind": "patch",
"published_at": "2026-07-14T08:55:40Z"
},
{
"tag": "v0.9.0",
"kind": "minor",
"published_at": "2026-07-14T08:55:31Z"
},
{
"tag": "v0.8.4",
"kind": "patch",
"published_at": "2026-07-14T04:39:44Z"
},
{
"tag": "v0.8.3",
"kind": "patch",
"published_at": "2026-07-14T02:58:28Z"
},
{
"tag": "v0.8.2",
"kind": "patch",
"published_at": "2026-07-13T05:26:36Z"
},
{
"tag": "v0.8.1",
"kind": "patch",
"published_at": "2026-07-12T07:59:13Z"
},
{
"tag": "v0.8.0",
"kind": "minor",
"published_at": "2026-07-12T07:18:12Z"
},
{
"tag": "v0.7.15",
"kind": "patch",
"published_at": "2026-07-11T05:56:30Z"
},
{
"tag": "v0.7.14",
"kind": "patch",
"published_at": "2026-07-11T05:02:54Z"
},
{
"tag": "v0.7.13",
"kind": "patch",
"published_at": "2026-07-11T04:40:16Z"
},
{
"tag": "v0.7.12",
"kind": "patch",
"published_at": "2026-07-11T04:03:40Z"
},
{
"tag": "v0.7.11",
"kind": "patch",
"published_at": "2026-07-11T04:01:30Z"
},
{
"tag": "v0.7.8",
"kind": "patch",
"published_at": "2026-07-11T03:58:01Z"
},
{
"tag": "v0.7.7",
"kind": "patch",
"published_at": "2026-07-11T03:54:25Z"
},
{
"tag": "v0.7.6",
"kind": "patch",
"published_at": "2026-07-11T03:50:42Z"
},
{
"tag": "v0.7.5",
"kind": "patch",
"published_at": "2026-07-11T03:47:24Z"
},
{
"tag": "v0.7.4",
"kind": "patch",
"published_at": "2026-07-11T03:43:33Z"
},
{
"tag": "v0.7.2",
"kind": "patch",
"published_at": "2026-07-11T03:40:08Z"
},
{
"tag": "v0.7.1",
"kind": "patch",
"published_at": "2026-07-11T03:36:28Z"
},
{
"tag": "v0.7.0",
"kind": "minor",
"published_at": "2026-07-11T03:32:41Z"
},
{
"tag": "v0.6.5",
"kind": "patch",
"published_at": "2026-07-11T03:29:33Z"
},
{
"tag": "v0.6.3",
"kind": "patch",
"published_at": "2026-07-11T03:25:53Z"
},
{
"tag": "v0.5.6",
"kind": "patch",
"published_at": "2026-07-11T03:18:51Z"
},
{
"tag": "v0.5.5",
"kind": "patch",
"published_at": "2026-07-03T06:46:22Z"
},
{
"tag": "v0.5.4",
"kind": "patch",
"published_at": "2026-07-01T14:46:46Z"
},
{
"tag": "v0.5.3",
"kind": "patch",
"published_at": "2026-07-01T14:42:55Z"
},
{
"tag": "v0.5.2",
"kind": "patch",
"published_at": "2026-07-01T12:27:18Z"
},
{
"tag": "v0.5.0",
"kind": "minor",
"published_at": "2026-06-28T09:06:04Z"
}
],
"recent_commits": [
{
"oid": "f5b0d54dc058bf964c3934e92ac03ef8bfffea4d",
"body": "Two prior commits broke pi's model-dropdown sequence. Both missed\nthat PAUSES and ENTERS are different concepts:\n\n PAUSE = time between sends, during which pi-tui transitions its\n internal state (e.g. command-recognised -> arg-input\n open) without committing. Cannot be imple\n[…]\n first two sends (the picker-routing hallucination).\n\nTest count: 717 (was 716 with mobileKeyboard; +1 net -- removed 4\npicker-routing cases, added 6 new pi 3-send cases including a\nregression guard).",
"is_bot": false,
"headline": "fix(pi): /model [pause]name[pause]<Enter> — pauses are not enters",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-27T07:34:51Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "884cc947ff7e5016a6897529757e15ec6d5368f6",
"body": "…eachable\n\nUser report (2026-07-27): 'edit models is broken and covered by\nsoftware keyboard' on iOS WebKit. Architect audit (mobile-keyboard-audit.md)\nfound the same bug class in 4 surfaces:\n\n 1. .modal-overlay — base uses height: 100vh which on iOS WebKit = full\n window including under the ke\n[…]\nerflow\n ancestors to reveal focused inputs since ~iOS 11. Verified during\n architect review; adding it would just race with visualViewport\n resize.\n\n716 vitest pass (was 706 at v0.15.1; +10).",
"is_bot": false,
"headline": "fix(mobile): keyboard-aware modal sizing — Edit Model + Kanban Save r…",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-27T06:28:41Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "42e108342aacb8fa047cce26c59f68308742efb8",
"body": "Three commits since v0.15.0:\n\n- 51bf080 feat(kanban): add feature portfolio stats\n- 8f06312 feat(kanban): chart project health\n- da6f818 fix(kanban): render shared HTML descriptions\n\nPlus the v0.15.0 follow-up fix:\n\n- fce0ef9 fix(ui): use .hidden class not [hidden] attribute on\n password buttons (C\n[…]\n was rendering in big red\n despite el.hidden=true due to CSS specificity)\n\n706 vitest pass (was 698; +8 across kanban stats + health chart +\nshared-description sanitization + .hidden regression net).",
"is_bot": false,
"headline": "v0.15.1: version bump (patch)",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-26T10:53:39Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "da6f8186996339ddcc6ea1fe1428b9f8c91f09d3",
"body": null,
"is_bot": false,
"headline": "fix(kanban): render shared HTML descriptions",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-26T10:22:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8f0631266fe3e00a4ea5efac7cfb3e9066efce6f",
"body": null,
"is_bot": false,
"headline": "feat(kanban): chart project health",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-26T10:11:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "51bf080f26b7388ee75848290bf898a0be343234",
"body": null,
"is_bot": false,
"headline": "feat(kanban): add feature portfolio stats",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-26T10:01:39Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "fce0ef9902915b4ae2ca4b364914b81d9b8f4caf",
"body": "The Confirm remove button had `hidden=true` set as a DOM property,\nwhich is supposed to apply `display:none` via the user-agent\n`[hidden]` selector. But the .btn rule's `display: flex` has\nhigher specificity (author > user-agent) and wins — so the button\nrendered in big red despite being 'hidden'.\n\n\n[…]\ns that\nthe Confirm button has the .hidden CLASS and not the [hidden]\nATTRIBUTE. Would fail loudly if someone reintroduces `el.hidden =\ntrue` on a button-shaped element.\n\n698 vitest pass (was 697; +1).",
"is_bot": false,
"headline": "fix(ui): use .hidden class not [hidden] attribute on password buttons",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-26T08:13:49Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "57c1b0f55d61db9987180f13bffa85eee655428c",
"body": "Access-password UX rework — 'Sign in to Phi' copy, single primary\nbutton with proper sizing, inline validation, two-step remove\nconfirm replacing window.confirm(). All detail in 003b881 and the\nchangelog. No push per request.",
"is_bot": false,
"headline": "v0.15.0: version bump (minor)",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-26T08:03:27Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "cdb529a5495d0804d8a08708755c36fd77401c43",
"body": null,
"is_bot": false,
"headline": "fix(kanban): preserve bucket states with subtasks",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-26T07:46:38Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "003b8818d3e43d7ecfaeb889104037a90706abe7",
"body": "…on sizing\n\nTwo pieces of slop cleaned up:\n\n1. **Unlock prompt copy** (`web/auth.js`)\n - title 'Phi is locked' → 'Sign in to Phi' (industry convention;\n 'Google is locked' is not a phrase anyone has ever seen)\n - submit button 'Unlock' → 'Sign in'\n - added a subtitle 'Enter your password t\n[…]\ncture\n - 4 new cases: short password blocked, mismatch blocked, typing\n clears the inline error, remove-link two-step Confirm flow\n\n 696 vitest pass (was 692; +4). No version bump per request.",
"is_bot": false,
"headline": "fix(ui): clean up access-password UX — 'Sign in to Phi' + proper butt…",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-26T06:52:02Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0edb576ad0e8a8e756ad2c1cd66f8a43e87279db",
"body": "Captures everything shipped between the v0.14.3 tag and now:\n\n- 9c538aa (Xi): add optional access password (auth.go + WS handshake)\n- dc42546 (Xi): docs: describe safe default binding\n- 522e805 (Xi): kanban feature roll-ups (web-src/kanban-features.ts +\n CSS + 2 new test files)\n- 929d938 (this agen\n[…]\ndown through pi's\n picker (3-step: open / type filter / select) since the\n /model <name> exact-match path is flaky in pi 0.81.x\n\nFull notes in web/changelog.md. 692 vitest pass (was 657 at v0.14.3).",
"is_bot": false,
"headline": "v0.14.4: version bump",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-26T06:30:53Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "522e805185b18fc44cb057dc363fbef4a7dec25f",
"body": null,
"is_bot": false,
"headline": "feat(kanban): add native feature roll-ups",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-26T01:16:43Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "de9562e13e40f4853ec974da533d5db3b38d4938",
"body": "…atch\n\nThe `/model <name>` exact-match path in pi 0.81.x is flaky: sometimes\nswitches, sometimes opens the picker prefiltered, sometimes filters\nto nothing. Manual finger-typed `/model <name>\\r` exhibits the same\nflakiness; the picker (search + arrows + Enter) is reliable per user\nreport.\n\nDefensive\n[…]\nserting cross-tab pin survives the picker chain\n- filter text assertion is shape-based (model name matches a\n sanitized pattern) so the test is robust to fixture edits\n\n681 vitest pass (was 680; +1).",
"is_bot": false,
"headline": "fix(pi): route model-dropdown through pi's picker, not /model exact-m…",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-26T01:00:21Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "29c414a0c0ea175c247e74f5506dcf048af36814",
"body": "Collapse the three split sites (paste + setTimeout('\\r', 200)) into\nsingle sendSlashCommand calls. The helper sends\n${'\\x1b[200~<cmd>\\x1b[201~\\r'} as one write.\n\nReplaces:\n- terminal.js:4023 desktop coder presets\n- terminal.js:4155 mobile renderSlashDropup\n- terminal.js:4454 model dropup pi path\n\nTh\n[…]\nnyone reintroduces sendRawInput inside a setTimeout). sendToTab\nremains in place for future use; the opencode picker chain still\nuses it for its 4-send puppet sequence.\n\n680 vitest pass (was 676; +4).",
"is_bot": false,
"headline": "refactor(input): atomic paste+Enter for slash-command presets",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-26T00:55:37Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3cd9f3a5e8c0dbe94d0a956a92c93867034d6747",
"body": "Four sites in web/terminal.js send a bracketed paste and a delayed \\r\nacross two setTimeout-separated sendRawInput calls. sendRawInput calls\ngetActiveTab() at fire time, so each call in the delayed chain\nre-resolves the active tab. Two real bugs:\n\n- HIGH: switch tabs within 200ms and the delayed \\r \n[…]\nso getActiveTab /\nsendInput / sendToTab are real prototype methods — no stubbing of\nthe methods under test. Mock only ws.sendInput, showToast, scroll\nfollow-up, focus.\n\n676 vitest pass (was 660; +16).",
"is_bot": false,
"headline": "refactor(input): pin sendRawInput-in-setTimeout to the click-time tab",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-26T00:53:19Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9c538aadcf649b9c09d5171f3d2d4e3256d89501",
"body": null,
"is_bot": false,
"headline": "feat: add optional access password",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-26T00:48:02Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "dc425463d25e12626c77cacea708a859da845389",
"body": null,
"is_bot": false,
"headline": "docs: describe safe default binding",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-26T00:19:39Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "929d938a85efede1b35d77046d1417b0f44f7ada",
"body": "`web/kanban.js` `initTabContainer` overwrote the termContainer's\nclassName with `'term-container kanban-panel'`. createTab → switchTab\nhad already added `.active` to make the panel visible (`display:flex`\nfrom `.kanban-panel.active`); the overwrite silently dropped it. Result:\nevery first click on t\n[…]\nontainer has .active AND children\n- second openBoard (BUG-4 path): .active survives re-init\n- clicking the kanban tab element does not lose .active\n\n660 vitest pass (was 657; +3). 15 Go packages pass.",
"is_bot": false,
"headline": "fix(kanban): preserve .active on the kanban-panel after init",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-25T23:49:57Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "540ac337416e6bdd605421733e283f3b92292fcd",
"body": "Cherry-picked since v0.14.2:\n\n- #14 (n0mad-awx): ci(frontend) build UI before release + advisory\n pre-commit hook at .githooks/pre-commit (opt-in via\n `git config core.hooksPath .githooks`).\n- #12 (n0mad-awx): TerminalFontSize config (8-32, clamped, 0 is\n responsive-default sentinel), curated ter\n[…]\n)\n + wheel-down escape hatch for stale-clamped viewports.\n\nAll three authors preserved (Franklin He / franklin.he@airwallex.com\nwith Claude Opus / Claude Fable 5 trailers) per cherry-pick convention.",
"is_bot": false,
"headline": "v0.14.3: version bump",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-24T04:02:04Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c6a0310cc4ff85c76ddd13bff2032c53903421e0",
"body": "…ont upload (#12)\n\n- Terminal font size (8–32): new TerminalFontSize config field, clamped\n server-side with 0 as the \"responsive default\" sentinel. fitActiveTerminal\n no longer clobbers the size on resize; new applyTerminalFontSizeToAll also\n resizes the backing PTY (cols/rows change with font s\n[…]\nt,\nnode --check, plus a live browser smoke test (controls render, settings\nload/persist, family migration + dropdown change work).\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(ui): customizable terminal font (size + family) + local custom-f…",
"author_name": "n0mad-awx",
"author_login": "n0mad-awx",
"committed_at": "2026-07-24T02:11:37Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "df7a89c0a64eccb02f04422c30027b5addce6177",
"body": "… (#13)\n\nTwo desyncs in the vendored xterm: (1) the DOM scroll area goes stale\nduring PTY streaming, so wheel-up jumped to a stale coordinate and\nwheel-down clamped before the real bottom; (2) public onScroll is\nsuppressed for user wheel/scrollbar input, so the jump-to-bottom button\nand follow re-en\n[…]\nape hatch\nfor a stale-clamped viewport. Also updates terminalActivityChrome.test.js's\nwrite assertions for the new completion-callback argument.\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(term): sync xterm scroll area during streaming; hear user scrolls…",
"author_name": "n0mad-awx",
"author_login": "n0mad-awx",
"committed_at": "2026-07-24T02:11:26Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "22801356083cbbc18f2cb8cd357ca2a246b2192e",
"body": "…k (#14)\n\n- release.yml: run npm ci + build:web before GoReleaser so the embedded\n web/ reflects current web-src/*.ts, not stale committed JS.\n- .githooks/pre-commit: advisory local mirror of the CI frontend checks —\n node --check on staged JS; typecheck + build:web drift guard on .ts\n changes; g\n[…]\n Enable once per clone: git config core.hooksPath .githooks\n- README: document the hook + enable step in the Frontend dev section.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "ci(frontend): build UI before release + add pre-commit drift/lint hoo…",
"author_name": "n0mad-awx",
"author_login": "n0mad-awx",
"committed_at": "2026-07-24T02:11:11Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "80e56642e0eb150f9800d292b6a4a5cd31154165",
"body": "Captures everything shipped between the v0.14.1 tag and now:\n\n- #10 (n0mad-awx): attention-toast 'Go to tab' action\n- #11 (n0mad-awx): fsnotify markdown watcher + same-context tab-click refresh\n- 0d1a434: restore the config pill (span + click-on-parent) + settings modal layout\n- 531867c: restore the\n[…]\nd73efe: sync board 'Clear all' button\n- 7e6c308: ctrl+shift+x chip is now a strict subset of preset-btn\n- 1f05b9f: suppress git fatal-stderr spam in non-git workspaces\n\nFull notes in web/changelog.md.",
"is_bot": false,
"headline": "v0.14.2: version bump",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-22T08:09:03Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1f05b9f4f9efeac0848d9702669fbefbb3983fc6",
"body": "When the diff panel was opened against a workspace that wasn't a git\nrepo (a common case — the user switches worktrees often), the handlers\nhit one of three bad outcomes:\n\n /api/git/raw-diff -> 500 + raw stderr (\"fatal: not a git\n repository (or any of the parent\n \n[…]\nepo.test.js: 4 cases (raw-diff sentinel,\n raw-status sentinel, JSON streaming sentinel, regression guard\n on non-sentinel content).\n\nLint clean, vet clean, 646 vitest pass, full go test ./... green.",
"is_bot": false,
"headline": "fix(git): suppress fatal-stderr spam in non-git workspaces",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-22T07:58:15Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7ec562ea9b4de63532b2c117422a0d6d38713d05",
"body": "…unchanged)\n\nba8a290 set the pill as a static elevated container with no hover\neffect at all. Commit 0d1a434 added a hover + cursor + transition\non top, then 531867c reverted those because the hover looked too\nloud for the surface (a box-shadow + accent border out of nowhere).\n\nAdd a real glassmorph\n[…]\ntic, recognizable elevated container; the hover is a bonus,\nnot the affordance.\n\nVerified: `diff` of the unhovered .header-config-pill rule block\nagainst ba8a290 is empty; 642 vitest pass; lint clean.",
"is_bot": false,
"headline": "style(ui): glassmorphism hover lift on header-config-pill (unhovered …",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-22T07:47:37Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "531867cbbdb2b4faa9c8c910a856f6d48d07ee3d",
"body": "Commit 0d1a434 added a `.header-config-pill:hover` glow + transition\n+ `cursor: pointer` to the pill. That overlay-style isn't how the\npill read originally — the v0.2.2 commit ba8a290 (feat: Replace\nseparate header config buttons with a compact Config Pill widget)\nset the look as a static elevated c\n[…]\nill block. The click\nhandler in app.js still triggers openSettingsModal on the parent\ndiv, so the pill is still fully clickable — the styling just no\nlonger competes visually with the chip's contents.",
"is_bot": false,
"headline": "style(ui): restore the original header-config-pill CSS (pre-hover-glow)",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-22T07:44:51Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7e6c30829acd33e4c1ba30cff8ff47e44e7feb51",
"body": "The chip carried extras that no other preset-btn in the row has:\n- an id (`pi-shortcut-send-btn`)\n- a title attribute (`Send staged input (Ctrl+Shift+X)`)\n- a verbose label (`Ctrl+Shift+X `b7 send`) with mixed casing and a separator.\n\nThat made it the only chip in the presets row that was findable b\n[…]\ns the chip by\n its preset-btn class + lowercase label. New case locks in the\n strict-subset invariant: chip.id === '', no title attribute,\n className === 'preset-btn', innerText matches /^[a-z+]+$/",
"is_bot": false,
"headline": "refactor(presets): make the ctrl+shift+x chip a strict preset-btn member",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-22T07:39:06Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2d73efe705c128ce6364b4b0abd57c1f4e9a0356",
"body": "The sync board tab on the right panel had per-card delete (one round-\ntrip per key) and a single-row Add form, but no bulk delete. Adds a\n'Clear all' secondary button next to 'Add' in the panel header that\nasks for confirmation, then DELETEs every key on the current coordinator\none by one.\n\nBackend \n[…]\nail toast).\n\nURL matching in tests goes via buildProxyUrl() so the matched target\nis the encoded inner path (`/api/sync/messages/...`), not the literal\n`/api/proxy?url=...` that fetch() actually sees.",
"is_bot": false,
"headline": "feat(sync): 'Clear all' button sweeps every sync message",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-22T07:00:18Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0d1a4344b43757bdeb4ec8a96d4e137c58180bbc",
"body": "The v0.13.0 settings-modal commit replaced the <span class='pill-label'>\nwith a <button> carrying .pill-btn, which forced 22x22 icon sizing on\na text label. That commit lived only in 71cb99e and was lost during the\npr5 reset to eede55c9, so main still has the squished Config button.\nA second visual \n[…]\nhout\n children escaping the modal's rounded border\n- test-js/settingsModal.test.js: rewrite makeAppDom to match the new\n span-on-parent markup + add 'export/import sub-btn doesn't open\n modal' case",
"is_bot": false,
"headline": "fix(ui): restore pill UX + settings modal layout",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-22T06:57:18Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "13254748bbb3113b122aae83d47e68e623316c73",
"body": "…sh fix (#11)\n\n* feat(mdwatch): add fsnotify-based markdown directory watcher\n\nNew pkg/mdwatch.Watcher wraps fsnotify to watch a caller-supplied set of\ndirectories (non-recursive, matching the /api/markdown/files listing)\nand fires a debounced onChange(dir) callback when a .md file is\ncreated, remov\n[…]\n covers the generic\ndefault; the .md tests now exercise the filter mechanism.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(md): live-updating markdown panel via fsnotify + tab-click refre…",
"author_name": "n0mad-awx",
"author_login": "n0mad-awx",
"committed_at": "2026-07-22T06:16:00Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "fd9d19f7ccb67fc3ad2c2c0a0826806fcfd93673",
"body": "The idle-attention toast (\"Session X is waiting at a prompt.\" /\n\"completed execution.\") now carries a Go to tab action button that\nswitches to the originating pane, mirroring what the OS-level\nnotification onclick already does. Reuses the existing showToast\nopts.action mechanism (same idiom as the soft-close Undo toast).\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(notifications): add Go to tab action to the attention toast (#10)",
"author_name": "n0mad-awx",
"author_login": "n0mad-awx",
"committed_at": "2026-07-22T05:22:28Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "0557418c688d94f1691f018c85676d69503d508b",
"body": "Patch batch from n0mad-awx (Franklin He <franklin.he@airwallex.com>)'s\nPR #6 (air-updates-2026-07). The PR contained 7 commits; we already\nhad 2 of them in v0.14.0 (gofmt + rename-tabs) so those were skipped\nduring cherry-pick. The 5 new commits:\n\n- 73d3fe94 fix(tabs): stop hiero preview replaying o\n[…]\nreaking changes. 626 vitest tests pass (was 614 + 12 new in\ntest-js/{tabHieroPreview,nonDirectKeyRedirect}.test.js). Author\npreserved on the 5 cherry-picked commits per the same convention as\nv0.14.0.",
"is_bot": false,
"headline": "v0.14.1: version bump",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-22T03:31:18Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "849c860b3575621ecf4c1e7b442e2f0fe173dd66",
"body": null,
"is_bot": false,
"headline": "docs(readme): document frontend dev live-reload workflow",
"author_name": "Franklin He",
"author_login": "n0mad-awx",
"committed_at": "2026-07-22T03:29:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5eed172ed5f9c6e8d95f2beb2b6bafc7b094851e",
"body": null,
"is_bot": false,
"headline": "feat(dev): add Vite dev server for frontend live reload",
"author_name": "Franklin He",
"author_login": "n0mad-awx",
"committed_at": "2026-07-22T03:29:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0bc4fc8e0d16bbb1e2303e9fac46daef7697d057",
"body": "…e terminal\n\nIn non-direct mode, the custom key handler redirects printable keydowns\nfrom xterm's helper textarea into the staged input bar: it appends e.key\nmanually and moves focus mid-keydown. Without preventDefault the\nbrowser's default text insertion follows the newly-focused textarea and\ninser\n[…]\ns input listeners (spam-scroll, lastInputValue, autosize,\nprompt-history cursor reset) running; it replaces the direct\nadjustInputHeight() call.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(terminal): prevent double character when typing after clicking th…",
"author_name": "Franklin He",
"author_login": "n0mad-awx",
"committed_at": "2026-07-22T03:29:06Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "312ceb460dc356e97308791084a5f851b2004da8",
"body": "The tab strip clips titles at 240px, and the old native title attribute\nwas written once in createTab - it went stale on rename and doubled up\nwith the hover card. The hiero hover card is now the tab's tooltip:\n\n- a title row read from the tabs Map at hover-time (never stashed on\n the DOM), so rena\n[…]\n worktree-header hovers leave\n both rows empty; :empty CSS collapses them.\n\nformatDurationMin is now exported from util.ts for the status line.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(tabs): show full title + busy/idle status in the tab hover card",
"author_name": "Franklin He",
"author_login": "n0mad-awx",
"committed_at": "2026-07-22T03:29:06Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "e95b2fd504dc7e68d1ed268a034dd7942d81cc41",
"body": "The delegated mouseover/mouseout handlers fire on every child-boundary\ncrossing inside a tab (.tab-title, .tab-close), hiding + repopulating\nthe preview card and force-restarting the shimmer keyframe - visible\nas the glyph re-rendering while the mouse moves within one tab.\n\nGuard both handlers (tabs\n[…]\ns) with\nrelatedTarget so they only react when the pointer actually enters or\nleaves the element, i.e. delegated mouseenter/mouseleave semantics.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(tabs): stop hiero preview replaying on intra-tab mouse movement",
"author_name": "Franklin He",
"author_login": "n0mad-awx",
"committed_at": "2026-07-22T03:29:06Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "39e36c80b57ad432edd9988b5bcf86b9774726d7",
"body": "Five PRs from n0madsky cherry-picked:\n- #2 k8s-friendly liveness/readiness + graceful shutdown\n- #3 rename live tabs by double-clicking the title\n- #4 Claude session discovery (forward-encoding cwd, not lossy decode)\n- #5 structured logging + opt-in OpenTelemetry (12 commits)\n- #1 gofmt + go vet CI \n[…]\n .gitattributes)\n\nFollow-up integration commit re-added PR #2's BeginDrain/Shutdown +\nPR #3's SetTitle + /livez/healthz/readyz route registration that\neach of pr5's 12 commits had clobbered wholesale.",
"is_bot": false,
"headline": "v0.14.0: version bump",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-22T03:18:16Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "4fce32c1d3a8c525c47882deea5753312c94c144",
"body": null,
"is_bot": false,
"headline": "style: gofmt main.go and pty/manager_test.go (post-integration)",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-22T03:16:02Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "17d86391c0278fdecfdfad4c0dcc38563c17b2da",
"body": "PR #2 (k8s-friendly liveness/readiness + graceful shutdown) added a\nManager.BeginDrain/Manager.Shutdown pair plus ErrShuttingDown so Spawn\nrejects during the drain window. The earlier cherry-pick of pr2 onto\nclean eede55c9 worked, but when each of pr5's 12 commits subsequently\nclobbered main.go + pk\n[…]\nUTDOWN_GRACE), default drain delay 0\n so Ctrl-C UX is unchanged for local dev\n - sync/atomic import added\n\n main_test.go\n - TestHandleFallback_Rename's Spawn call gets context.Background()",
"is_bot": false,
"headline": "feat(pty): BeginDrain + Shutdown + per-PTY cleanup (PR #2 integration)",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-22T03:15:01Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1cf7e8399b6598bf253baa0bf1aa5c9f00f73b28",
"body": "…level\n\nThe four startup log.Fatal* sites in main.go were routing through the\nstdlib-log→slog bridge and thus logging at Info. Convert them to\nslog.Error + os.Exit(1) per the plan, so fatal startup errors carry the\nError level (behavior otherwise unchanged — still aborts with exit 1).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(M1): log.Fatal* → slog.Error + os.Exit(1) so fatals log at Error …",
"author_name": "n0mad",
"author_login": null,
"committed_at": "2026-07-22T03:02:52Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "2ca04ddf54a1afc6fccb2ec4d8813006c95b96bd",
"body": "…t Info\n\nBenchmarkFrameDebugGuard_AtInfoLevel confirms the\nslog.Default().Enabled(ctx, LevelDebug) check ReadPump/WritePump/\nStartPTYReadLoop all use before building their \"frame\" trace line costs\n0 B/op, 0 allocs/op at the default Info level — a regression (e.g.\nsomeone building the Debug args unconditionally) would show up here.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "test(L8): benchmark the WS frame-trace debug guard stays alloc-free a…",
"author_name": "n0mad",
"author_login": null,
"committed_at": "2026-07-22T03:02:52Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "250f50337e6dcd5f2e41d395437fa47cdc8c3351",
"body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: document --log-level and --otel-endpoint in README flags table",
"author_name": "n0mad",
"author_login": null,
"committed_at": "2026-07-22T03:02:52Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "70f5d5f5fb40a57ebf311ce5bf43677a256b6b8a",
"body": "…an wrap\n\nAdds go.opentelemetry.io/otel{,/sdk,/trace}, the OTLP/gRPC exporter,\ngo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp, and\ngithub.com/XSAM/otelsql — all //go:build otel only, downloaded and\nrecorded in go.mod/go.sum via `go get` + `go mod tidy` (network access\nworked; no vendo\n[…]\nilsClosed,\nTestHandleWS_DiedInPlaceReportsRealExitCode — unrelated to this change,\nreproduced on the pre-tracing base commit too).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "M5c: real OTel backend behind -tags otel, --otel-endpoint flag, DB sp…",
"author_name": "n0mad",
"author_login": null,
"committed_at": "2026-07-22T03:02:52Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "62f673e6d831546a7c866c4bddbfcda98b7b92d4",
"body": "…aths\n\nOne obs.Span(ctx, name, attrs...) call site per traced subprocess, per\nplan's \"trace EVERY subprocess\" table — works today as a timed\nslog.Debug line (default build), and will carry a real OTel span once\nobs's otel backend lands:\n\n git.diff / git.show api_git.go handleRawDiff\n git.status \n[…]\ntrumentation is driver-wrapped\n(otelsql), landing with the OTel backend, per plan's \"wrap the driver,\ndon't hand-instrument\" call.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "M5b: wire obs.Span into the git/worktree/clipboard/pty-spawn traced p…",
"author_name": "n0mad",
"author_login": null,
"committed_at": "2026-07-22T03:02:52Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "7bf95d3d5abb4fb794f83f14d2e3e61ea04fb979",
"body": "…ree, PTY-spawn)\n\nIts own commit before wiring any spans, so the signature churn is\nreviewable in isolation (plan §D). New signatures:\n\n session.ListOpenCodeSessions(ctx, cwd)\n session.GetOpenCodeSessionTranscript(ctx, sessionID)\n session.getOpenCodeSessionTranscriptFromDB(ctx, db, sessionID)\n s\n[…]\ntest.go)\npass context.Background() or r.Context() as appropriate. No behavior\nchange to PTY-spawn call sites beyond the signature.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "M5a: thread ctx.Context through the four traced paths (DB, git, workt…",
"author_name": "n0mad",
"author_login": null,
"committed_at": "2026-07-22T03:02:51Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "32200e4b029b3f9687a707831bac272a1474dff2",
"body": "Add four additive fields to DiagResponse: go_version, gomaxprocs,\nnum_cpu, num_gc. No pprof, no /metrics, no new flag — just a bit more\nof the runtime state already surfaced for debugging. UI panel wiring\nskipped per plan (optional/cuttable); the front-end diag panel keeps\nworking untouched since the new fields are purely additive JSON.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "M4: richer /api/diag runtime snapshot",
"author_name": "n0mad",
"author_login": null,
"committed_at": "2026-07-22T03:02:51Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "0fc187f83217e333ceaaeee8daf6f541f084645c",
"body": "… span\n\nTwo coordinator corrections applied together:\n\n1. Component tag. pkg/ws's per-connection/per-pane loggers now derive\n from componentLogger() (\"comp\"=\"ws\") instead of bare slog.Default(),\n so every converted line — upgrade/PTY write/resize errors, ring\n overflow, frame traces — carries \n[…]\nids\" premise no\nlonger applies without a hand-minted id); TestHub_BroadcastOverflow now\nasserts comp=ws+pane instead of conn+pane.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(M3): drop hand-minted WS conn id, tag comp=ws, wire ws.connection…",
"author_name": "n0mad",
"author_login": null,
"committed_at": "2026-07-22T03:02:51Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "22308757cecb5199bc25756b9fabf9438ce06d46",
"body": "pkg/ws: HandleWS reuses the M2 upgrade request's X-Request-Id as the\nconn id (falls back to a fresh crypto/rand id if absent), attaches it\nplus the pane id to a per-Client *slog.Logger. ReadPump, WritePump and\nStartPTYReadLoop thread that logger through so PTY write/resize errors,\nupgrade errors, an\n[…]\nough a shared store, since the naive \"return h\" version silently\ndrops exactly the conn/pane fields these tests need to assert on.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "M3: WebSocket connection tracing",
"author_name": "n0mad",
"author_login": null,
"committed_at": "2026-07-22T03:02:51Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "a96b95537ff5005e7a4fe1f840915f9d560adec0",
"body": "…lhttp\n\nCoordinator correction: no hand-rolled HTTP tracing middleware. Delete\ntraceMiddleware, ridKey, RequestID, newTraceID, statusWriter and the\npoll-spam Debug-path map from logging.go — M1's slog init/bridge is all\nthat remains there.\n\nAdd pkg/obs, the tracing façade M5 will give a real OTel ba\n[…]\nult\nbuild has no per-request access log or X-Request-Id; full HTTP request\ntracing is otel-build-only via otelhttp, landing in M5.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(M2): remove custom request middleware, add pkg/obs façade for ote…",
"author_name": "n0mad",
"author_login": null,
"committed_at": "2026-07-22T03:02:51Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "bcd6c856c35027dd870429110618a10bd3f80867",
"body": "Add traceMiddleware to logging.go: mints a 16-hex-char crypto/rand\ntrace id per request, stores it in the request context (RequestID),\nsets X-Request-Id on the response, wraps ResponseWriter to capture\nstatus/bytes, and logs one summary line (method, path, status, bytes,\ndur_ms) at Info — Debug for \n[…]\ns.\n\nmain.go serveAll: http.Serve(l, nil) -> http.Serve(l, traceMiddleware(\nhttp.DefaultServeMux)). One seam, no per-handler edits.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "M2: HTTP request tracing middleware (single seam)",
"author_name": "n0mad",
"author_login": null,
"committed_at": "2026-07-22T03:02:50Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "34372f50aa0bfec3b06a8b3ea2d1f2e33f17f52a",
"body": "Add logging.go: initLogging builds a slog.TextHandler on os.Stderr\n(JSON via PHI_LOG_FORMAT=json), level resolved from --log-level flag\n-> PHI_LOG env -> \"info\" default. Bridges the stdlib log package\nthrough slog once (log.SetOutput) so the existing ~47 log.Printf\ncall sites keep working without a mechanical rewrite.\n\nmain.go: new --log-level flag, initLogging called immediately after\nflag.Parse().\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "M1: structured leveled logging via log/slog",
"author_name": "n0mad",
"author_login": null,
"committed_at": "2026-07-22T03:02:50Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "36282eb23964f5d00dbb001dbffa97d9b496bfb5",
"body": "PR #1's cherry-pick took pr1's whole-file version of api_handlers.go,\noverwriting the /title endpoint that PR #3 had just added (and the\nencodeClaudeProjectDir/loadClaudeRegistry/etc helpers that PR #4 had\nadded in claude.go). The claude.go loss was caught and reverted by\nrestoring HEAD~'s claude.go\n[…]\nror PR #3's hunk: a /title endpoint that calls SetTitle, sitting\nbetween the /mark block and the DELETE block in handleFallback. Same\nshape (path parse, JSON decode, SetTitle err→404, 200 on success).",
"is_bot": false,
"headline": "fix(api): re-add /title endpoint after pr1 gofmt took wholesale version",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-22T01:55:50Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6c7b7ffb6c436b59ece34ca51f640b542e87e120",
"body": "No formatter was enforced in this repo. Run `gofmt -w` across the tree\n(fixes CRLF line endings on 4 files and struct-tag alignment drift on\nthe rest), pin `*.go` to `eol=lf` in .gitattributes so CRLF cannot\nreturn, and add \"Check gofmt\" + \"Go Vet\" steps to the test-go CI job\nso formatting stays cle\n[…]\no new dependencies — both tools ship with the Go toolchain. Diff is\ncosmetic only (whitespace, import sort, doc-comment reformat).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore: gofmt all Go sources + add gofmt/vet CI gate",
"author_name": "n0mad",
"author_login": null,
"committed_at": "2026-07-22T01:53:02Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "397d556f0787c7e2d497c4cfb191e0d53e7efd69",
"body": "Cherry-picked from PR #4 (n0madsky/claude-session-detect, cfd163f).\nThe PR's diff had a single conflict on the title-resolution block in\npkg/session/claude.go (HEAD had an inline priority chain, pr4 refactored\nto use extractClaudeMeta + resolveClaudeTitle helpers). Replaced the\ninline chain with the\n[…]\nderived live-session names\n- pkg/session/claude_detection_test.go (new): hermetic + property + fuzz\n cases for the encoder and matcher\n- pkg/session/parsers_test.go / session_test.go: call-site smoke",
"is_bot": false,
"headline": "fix(session): detect Claude sessions by forward-encoding cwd",
"author_name": "n0mad",
"author_login": null,
"committed_at": "2026-07-22T01:49:19Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "101a1820f5c8d51fb0f70ae9d5f4e31543733594",
"body": "Cherry-picked from PR #3 (n0madsky/rename-tabs, 64959fe5). The PR's\ndiff conflicted wholesale with PR #2 (k8s-health) on api_handlers.go\nbecause both modified adjacent endpoint blocks. Reapplied as four\nfocused hunks on top of the k8s-health commit:\n\n- api_handlers.go: insert /title endpoint after /\n[…]\nr + syncBackendTitle in TabManager,\n double-click on .tab-title, Enter/blur commits, Escape/empty reverts,\n escapeHtml at both render sites\n\nSkip PR #3's gofmt-sweep parent (30ebbcb); it lands last.",
"is_bot": false,
"headline": "feat(tabs): rename live tabs by double-clicking the title",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-22T01:48:13Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "29028a141ef8f4490fb924fe3ad52946c5c46a06",
"body": "Make Phi a well-behaved container/Kubernetes workload without disturbing\nthe local-first flow (Ctrl-C stays instant; drain defaults to 0).\n\nEndpoints (root-level, GET-only, dependency-free, outside /api):\n- GET /livez (+ /healthz alias): always-200 liveness probe\n- GET /readyz: 503 while draining so\n[…]\nly; go.mod untouched. Tests: api_health_test.go (probes +\nin-flight HTTP drain) and pkg/pty shutdown/straggler/spawn-during-drain.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: k8s-friendly liveness/readiness probes + graceful shutdown",
"author_name": "n0mad",
"author_login": null,
"committed_at": "2026-07-22T01:46:21Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "eede55c9f0d7db6759d4a1d041b8aa587b0f97df",
"body": "The existing ~/.claude/skills/phi-sync-board/SKILL.md hardcoded one\nuser's Tailscale IP (100.70.164.85:7070). Move it to bonus/phi-skills/\nwith:\n\n- $PHI_COORDINATOR env var instead of a literal address — each user\n sets it to whatever phi address is reachable from their claude machine\n (loopback, \n[…]\n.\n\nSkill description in the frontmatter updated to mention the unset-env\nbehavior so Claude recognises it without re-reading the body.\n\nInstall: cp -r bonus/phi-skills/phi-sync-board ~/.claude/skills/",
"is_bot": false,
"headline": "bonus/phi-skills: generalize phi-sync-board skill for any phi customer",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-21T10:06:48Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "38f3ca91b5dae3f82d91415c2d48090f457c6ae8",
"body": "…ullscreen)\n\nClarifies that phi launches 'claude' with no extra args, so Claude's\ninline (non-alt-screen) TUI stays inline with phi's terminal scrolling\nand the Alt+Up/Down prompt history works against it normally. If a user\nwants alt-screen, run claude in a system terminal and Reconnect.",
"is_bot": false,
"headline": "docs(help): note Claude Code runs in default /tui mode (inline, not f…",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-21T09:21:21Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1c437401ee98dd7c44be0e9bd75dd545df397432",
"body": null,
"is_bot": false,
"headline": "v0.13.0: version bump",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-21T08:56:10Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d99f2ea2b5b7ba09a8c903e39401bf9f565c772f",
"body": "sessions.ts loadConfig now reads ui_font_family/ui_font_size/\nterminal_font_family from the config response and applies them via\napp.applyUIFont(). The old (this.app).accentColorSelect.value\nassignment is removed since the select no longer exists; applyAccentTheme\nsets data-theme-color on <html>, which is what the Settings modal reads\non open. Regenerated web/sessions.js from the TS source.",
"is_bot": false,
"headline": "Ingest appearance settings from /api/config + drop accentColorSelect",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-21T07:46:55Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1b0bd3670310778d3d28c8873e7efdb695344194",
"body": "The header 'Config' pill label becomes a button (#header-settings-btn)\nthat opens a centered modal with: a 22-swatch accent grid sourced from\nACCENT_COLORS (replaces the old #accent-color-select), UI font\nselect/size input, terminal font input, 'reuse shell tab' toggle, and\nan About group showing Φ \n[…]\nes via inline style on\ndocument.body (no new CSS tokens per AGENTS.md).\n\nDead DOM removed: .theme-area div + select + both CSS blocks.\nAbout block reads from cached app.versionInfo — no fetch on open.",
"is_bot": false,
"headline": "Settings modal: highlight color + UI/terminal fonts + behavior + about",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-21T07:44:22Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "880d479f4485fcfdd746898c93b694404543b22b",
"body": "…pearance\n\nNew Config fields (UIFontFamily, UIFontSize, TerminalFontFamily) wired\nthrough handleConfig response and a new handleAppearanceUpdate POST\nendpoint. Size is clamped server-side to 10..24 to prevent rendering\nbreakage. Partial updates leave untouched fields alone. 6 tests cover\npersistence, partial update, clamp boundaries, method enforcement,\ngarbage-body rejection, and config-response surfacing.",
"is_bot": false,
"headline": "Backend: add ui_font_* / terminal_font_family config + /api/config/ap…",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-21T07:33:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "81e7997f5c5a5af90457487c805ba1946178fa80",
"body": "New pkg/bindaddr.Detect() walks net.InterfaceAddrs and returns every\nIPv4 address in 10/8, 172.16/12, 192.168/16, or 100.64/10\n(Tailscale CGNAT), plus 127.0.0.1 always. main.go binds one listener\nper detected address in parallel via serveAll; --ip retains the\nsingle-bind behavior for explicit opt-in\n[…]\nr binds complete.\n\nPublic IP exposure is the user's choice now: default = LAN + Tailnet\nonly, --ip 0.0.0.0 to opt back into the internet. 10 bindaddr tests,\n4 main-package tests for serveAll + banner.",
"is_bot": false,
"headline": "Default bind: loopback + LAN (RFC 1918) + Tailscale, not 0.0.0.0",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-21T06:56:22Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "116fb05fc4c05942f9b8998723c484ba1715d207",
"body": "Stores sent prompts in ~/.phi/prompt_history.json, FIFO-capped at 100,\nfiltered by cwd on recall. Alt+Up/Down on the staged input textarea\ncycles through recent entries for the active project; typing resets\nthe cursor back to free-form. New pkg/prompt_history package plus\n/api/prompt-history/append and /recent handlers. Tests: 7 store tests,\n5 handler tests, 12 frontend cycling tests.",
"is_bot": false,
"headline": "Add prompt history: Alt+Up/Down cycles previously-sent prompts",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-19T11:13:25Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f287017bdc55a5a2a18cb53d6e031de14d9b749c",
"body": null,
"is_bot": false,
"headline": "v0.12.1: version bump",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-19T05:12:03Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "061562d94f3ec722489c3d678d375cf830f1c6c8",
"body": "v0.12.0 default-to-direct applied to every tab including AI coders\n(pi/claude/agy/opencode). For AI coders that breaks the staged flow\n— the whole phi workflow — since the input bar, attachment strip,\npresets row, and Ctrl+Shift+X chip all hide in direct mode.\n\nNarrow it: bash + pwsh (which btop als\n[…]\nd-without-thinking defaults to\n the right thing, and pins the btop-via-bash path explicitly.\n\nVerification: 586/586 JS tests pass (was 566, +20 new), all Go\npackages pass, typecheck ✓, build:web ✓.",
"is_bot": false,
"headline": "fix(focus): per-coder direct default; prove session+tab restore",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-19T05:11:47Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ec9d8d94f432504d886bf1b82a3886fec5ea3651",
"body": null,
"is_bot": false,
"headline": "v0.12.0: version bump",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-19T03:46:41Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "45e0711650a57b63df2458f48b5b4a89e1df1053",
"body": "Adds an 'Export' / 'Import' pair to the markdown panel so the user can\nshare a workspace's full markdown directory between machines (or to\na backup) without having to manually copy each file.\n\nWire format mirrors the existing PHICONFIG/PHIMODELS clipboard-blob\nfamily with one extension: the markdown\n[…]\nhe wild should keep\nworking unchanged. The new helpers live alongside the markdown\nhandler and follow the same shape (prefix:sha256(b64+salt):b64),\nmaking future extraction a small refactor if needed.",
"is_bot": false,
"headline": "feat(markdown): clipboard export/import with gzip+signature blob",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-19T03:43:32Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "8cdee662d98d682c0e4dfd752b298e8a88cbb696",
"body": "The right-panel markdown file list previously rendered each row icon\nas the raw hieroglyph character 𓏛 (U+133DB). On systems without an\nEgyptian-Hieroglyphs font installed, that renders as a tofu box —\nthe symbol that should signal 'document' instead looks like the\nglyph didn't load. Replaced with a\n[…]\nNTS.md.\n\nThe new SVG carries the Greek/Egyptian motif where it actually makes\nsense (the viewer), and a clean standard icon where it doesn't\n(a 14-character list one would otherwise scan for quickly).",
"is_bot": false,
"headline": "style(markdown): scroll icon is SVG, viewer gets the stylized scroll",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-19T03:34:04Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "df32044ed23e69fa32d7067fc7035ecd31220131",
"body": "All new tabs open in focused/direct mode: typing routes to the\nterminal directly, no separate input bar visible, no presets panel.\nClick the direct-mode toggle in the header to opt into the staged\ninput flow (queue prompts, attach files, Ctrl+Shift+X chip).\n\nSame default for btop — the TUI system mo\n[…]\n the toggle treatment via updateDirectModeUI on\ntheir first activation. Inline CSS already styles\n.direct-mode-btn.active, so the toggle button visibly reflects the\nfocused state without further work.",
"is_bot": false,
"headline": "feat(focus): default to direct-mode (keyboard goes to terminal)",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-19T03:15:42Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "de64b2dc3a08041419e77eb1a01a935d16fc164e",
"body": "PTY output was leaving the native scrollbar stale at whatever\npercentage it had when output started, then snapping back the next\ntime anything caused a layout reflow (e.g. adjustInputHeight when\nthe user types). The user-facing symptom: scrollbar thumb at 70%\nwhile content clearly sits below the vis\n[…]\ngs.test.js).\nNo 'baseY - 1' slack — that would re-introduce the original rounding\nbug. Tests assert the four state combinations (at/not-at-bottom x\nfollow/no-follow) plus the cancel-handler flag flip.",
"is_bot": false,
"headline": "fix(scroll): track user-follow intent + force scroll-to-bottom on writes",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-19T03:05:04Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "325596edb88af6c3b23585e67cc00f2a6d8494fe",
"body": "The chip was styled as .kbd-shortcut-btn with kbd-key cap blocks, an\naccent halo, and an uppercase 'send' label. Heavier than every other\npill in the presets row (/quit, /resume, /model, /compact, etc.),\nwhich all use the flat .preset-btn surface.\n\nMatch the row's visual weight:\n - className: 'pres\n[…]\n: 'pi-shortcut-send-btn' for test selector stability\n\nDrop the now-unused .kbd-shortcut-btn CSS (~70 lines including the\n.presets-container .kbd-shortcut-btn override that sized it to fit\nin the row).",
"is_bot": false,
"headline": "style(shortcut-chip): pi Ctrl+Shift+X chip uses preset-btn shape",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-18T21:56:41Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c88fb4ebec101ceebb806fc15c5c3495bb7b97df",
"body": "The attachment strip was a sibling of #input-textarea inside a\nflex-row container. When empty and hidden (display:none) the row\ncontained just textarea + actions — fine. The moment a paste made\nthe strip un-hide, three flex items competed for the same row\nwidth; align-items:flex-end placed the strip\n[…]\nstill bottom-align with the textarea's last line\n - Drop-target glow on the container still applies to the whole bar\n - Pasting/dropping only changes the strip's height, never the\n textarea width",
"is_bot": false,
"headline": "fix(input-bar): paste no longer reflows the textarea row",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-18T06:14:36Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "08b275140e9323828b5b31222784198e429f118f",
"body": "50 was generous — most sessions don't paste/drop more than 5-10\nimages, so anything older than the last few minutes of activity is\nalmost certainly stale. 20 covers a generous session's worth of\nattachments while keeping disk usage bounded, and matches the\ntypical chip-strip depth a user might stage before sending.\n\nSweep test renamed + retriggered at 30 pre-existing files to\nexercise the new drop-10-oldest-fresh-upload-finishes-at-cap-20\npath explicitly.",
"is_bot": false,
"headline": "tune(attachments): sweep retains 20 most-recent files (was 50)",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-18T06:13:01Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1beb115e046f3f5275bb7f3671e23986e297f754",
"body": "Two bugs:\n\n1. Race. Brand click toggle, focus handlers from clicks, and timing-\n adjacent mouseenter events all collided to produce 'click it, it\n goes away, comes back up' flicker. Tighten the state machine:\n - Click toggle on brand is now gated to touch-only via\n '(hover: none)' matc\n[…]\nviously-broken light themes.\n\nTests: 546/546. Three new: outside-click closes (mouse-driven), click\ndoesn't toggle on mouse-driven, cooldown blocks reopen within ~200ms,\nhostname click closes the HUD.",
"is_bot": false,
"headline": "fix(brand): HUD race + white theme popover",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-18T05:12:34Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "776d62b432fcd4b27fa1ab5e1d51d67c53fcc8d6",
"body": "Hovering the brand opened the HUD, but the hostname element is also\ninside .brand and has its own click behavior (toggles the tab-selector\ndropdown). When the HUD was already open and the cursor moved onto\nthe hostname, clicking would surface both popovers at once — a visual\nclash.\n\nAdd a mouseenter\n[…]\nand via the logo, then drifts to the hostname\n (HUD closes on hostname entry)\n\nThe hostname's own click handler is unchanged: clicking it toggles\nthe tab-selector dropdown, with no HUD involvement.",
"is_bot": false,
"headline": "fix(brand): close HUD when cursor enters hostname area",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-17T09:47:08Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9361273fd45a4e5cc52284f3b2af68c9a1991e18",
"body": "The HUD popover lived inside .app-header (which has z-index:100 and\nposition:relative, creating its own stacking context). The popover's\nown z-index:1100 was local to that context — sibling surfaces like\n.diff-panel (z-index:1200) and .modal-overlay (z-index:10000) covered\nthe popover visually AND i\n[…]\nentRect on\n every open + scroll + resize, so the popover tracks the brand\n\nUser symptom: 'it draws BELOW things it doesnt hover it gets hovered\nby other stuff' — exactly the stacking-context issue.",
"is_bot": false,
"headline": "fix(brand): escape .app-header stacking context for self-state HUD",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-17T09:34:31Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c4e78ca4bab1b3f2ffbf5115827ee6cf316dc40f",
"body": "The drop listener was attached only to .input-bar-container — a thin\nstrip at the bottom of the screen. Users drop where their cursor is,\nwhich is the terminal pane taking up most of the viewport. Drops on the\nterminal pane's DOM tree never reached the input bar handler, so files\nsilently disappeare\n[…]\nfile landed on the terminal pane, browser navigation was prevented\n(thanks to the guard), but the upload never happened. Regression test\ndispatches on a synthetic .term-container element to reproduce.",
"is_bot": false,
"headline": "fix(attachments): drop zone is page-wide, not just the input bar",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-17T04:52:42Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1abf14f1c3f3f5fd91ea0d5edb79386526cf17ed",
"body": null,
"is_bot": false,
"headline": "v0.11.0: version bump",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-16T23:26:02Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f81a34f822be1f8b37608c39eec9c57983b2abe1",
"body": "Hover (or focus) the Φ logo in the top-left to reveal a compact\nself-state summary: hostname, version, session count, busy count,\nattention count, CPU%, and last activity. No network is touched on\nopen or close — every field is computed from local state phi already\nmaintains (tab map, hostname confi\n[…]\nformatHudLine, formatHudCpu) live in web-src/util.ts so they're\nunit-testable without DOM. The DOM wiring in terminal.js is ~170\nlines. CSS is the bulk (~200 lines) because the aesthetic is the point.",
"is_bot": false,
"headline": "feat(brand): self-state HUD popover on hover",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-16T23:14:28Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3ee616418e50954b19806a0ab0bf688b0541344b",
"body": "Drop a file (or paste a screenshot) onto the input bar to attach it to\nthe next Send. The chip strip above the textarea shows what's queued;\nhit Send and the coder receives the path in its preferred syntax\n(claude/opencode/agy → @path, pi/bash/pwsh → raw path, unknown coders\nfall back to raw path).\n\n[…]\nhip management /\n send integration wired through a real TabManager instance\n - f7InputBypass.test.js — ctx() now includes stagedAttachments +\n attachmentStrip so the partial mock stays accurate",
"is_bot": false,
"headline": "feat(attachments): drag-drop + clipboard-image into staged input",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-16T21:16:44Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "5e52d28807254f29a77055964005b0d96a673e68",
"body": "New endpoint for staged-input attachments (drag-drop + clipboard image\npaste). Multipart upload with image/* allowlist, 25 MB MaxBytesReader\ncap, server-generated unique filenames (clip-<unixnano>-<rand>.<ext>) so\nrapid paste events don't collide, and a sweep that keeps the last 50\nfiles in ~/.phi/c\n[…]\n\nTests use t.Setenv to redirect HOME/USERPROFILE so runs don't litter\nthe developer's real ~/.phi/clipboard/. Six cases: happy path,\ndisallowed MIME, oversize, wrong method, missing file field, sweep.",
"is_bot": false,
"headline": "feat(attachments): POST /api/attachments backend",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-16T21:16:36Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e374437fffc302f28fe44d74fd2d40d55586a78b",
"body": "btop redraws the screen at high frequency, so its tab isBusy stays true\nforever. That pinned hasActivity=true through getTerminalActivityState,\nwhich kept the curly-Phi glyph ϕ in the browser title and the ▍\nindicator in the header lit forever while btop was running — the user\nread this as 'shows as\n[…]\nsession when activeCoder='bash'.\n\nOnly coding-agent tabs (pi, claude, agy, opencode) drive the global\n'working' indicator now. Six new tests in terminalActivityTitle.test.js\ncover the exclusion rules.",
"is_bot": false,
"headline": "fix(activity): exclude btop and shell tabs from global working indicator",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-16T10:34:17Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0b0dcd4f5012855e8fbc83c791b113e7551757d3",
"body": "The Ctrl+Shift+X chip was placed inside .input-actions immediately to\nthe right of the primary Send ↵ button. That makes the chip visually\ncompete with the action it shortcuts, and reads as 'next to Send' rather\nthan 'a shortcut chip in the row of utility shortcuts'.\n\nMove the chip into #presets-con\n[…]\nr; the chip is additive\ndiscoverability, never a substitute. Behavioral DOM tests in\npiShortcutChip.test.js assert both sides — chip presence for pi, absence\nfor bash/claude, and Send ↵ never touched.",
"is_bot": false,
"headline": "refactor(send): move pi shortcut chip into presets row",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-16T10:33:43Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "deaeec0ffb4e6daf18b85d83645d8a237bad71f7",
"body": "The rich diff viewer is already forced to line-by-line layout for mobile\nvia diff.ts:renderRichDiff (outputFormat: 'line-by-line'), but each code\ncell used `pre` whitespace so long lines ran off-screen with only an\nendless horizontal scrollbar to find the right edge. On a 360px phone\nthis reads as '\n[…]\nnd pin the line-number column to vertical-align:\ntop so wrapped rows line up under their numbers.\n\nDesktop CSS and JS untouched by construction — the wrap lives entirely\ninside the mobile media block.",
"is_bot": false,
"headline": "style(mobile): wrap long diff lines on phones",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-16T10:33:00Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3783e8ccf2fc8f03bebf4bdc2f5b1db7bee1e12c",
"body": null,
"is_bot": false,
"headline": "ci(release): use project Go toolchain",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-15T07:00:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7c2cd1f00b7dbea8bea393205f2c56f19a3ec89f",
"body": null,
"is_bot": false,
"headline": "v0.10.1: version bump",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-15T06:58:21Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "00fdd9e5c8cb016fb3e3658ffff7cec1556e6aa4",
"body": null,
"is_bot": false,
"headline": "fix(scroll): let user input cancel stale restore",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-15T06:57:59Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1e2b1aec70d47e9c107e1949251dd0d405b0c791",
"body": null,
"is_bot": false,
"headline": "tune(tabs): shorten close undo grace",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-15T06:03:53Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "389f0ea0005da8148befd7d44ca3c77de14f0367",
"body": null,
"is_bot": false,
"headline": "fix(scroll): preserve page and bottom state",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-15T05:42:58Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "60ed76a1e0c289f511e34bfdaef601884409c7f4",
"body": "This reverts commit b94aee067dcb2758b48a592892b36101e9651472.",
"is_bot": false,
"headline": "Revert \"fix(scroll): stop coercing terminal viewport\"",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-15T05:29:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b94aee067dcb2758b48a592892b36101e9651472",
"body": null,
"is_bot": false,
"headline": "fix(scroll): stop coercing terminal viewport",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-15T05:22:02Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3f996541937bf24542bf3ac2158c0ebc1a2d8e35",
"body": null,
"is_bot": false,
"headline": "fix(input): keep Send beside pi shortcut",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-15T05:04:39Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "212d8be07882bba99dfb6d8246f14aba2da210d2",
"body": null,
"is_bot": false,
"headline": "fix(tabs): silence intentional close disconnect",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-15T04:36:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "878eca9fa6819a0ca6c967e00625f74874701af6",
"body": null,
"is_bot": false,
"headline": "ci: move actions to Node 24",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-15T04:25:37Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9f911d8d25d87ee773a4f3252faa861ea5a261a6",
"body": null,
"is_bot": false,
"headline": "v0.10.0: version bump",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-15T04:09:41Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b50b86d4f305c52a87d2e78ba0a5457e9ad37559",
"body": "Use Φ/ϕ in the title and favicon, retain ● for attention, and turn the hostname separator into a quiet/live terminal cursor.",
"is_bot": false,
"headline": "feat(chrome): show terminal output activity",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-15T03:59:52Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "66a0d26c527c87d2ced1720f1f0a40344aca3896",
"body": "…4 step 3)\n\nArchitect review recommended (Phase 4 step 2 'audit escapes' + step F 'phase 5\ncandidates') a runtime surface smoke test for AppLike drift. The 7 converted\nmodules consume nested manager handles through 'any' on AppLike, so a typo like\n'tabManager.swicthTab' (vs 'switchTab') compiles sil\n[…]\no-op safety net\nrather than a maintenance burden.\n\nVerified:\n- npm test 461/461 pass (433 prior + 28 new in this file)\n- typecheck/build:web clean\n- ~70 source lines including the table; ~85ms runtime",
"is_bot": false,
"headline": "test(ts): managerSurfaceSmoke - AppLike drift gate at CI time (Phase …",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-15T03:08:40Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "a4a05308a5dcf835d4dadf71ea63fd0eb2101af2",
"body": "Phase 4 step 2 (audit type escapes, fix phi-owned boundaries).\n\nWhen converting diff.ts to .ts the local cmdEl / syncEl vars\n(queried via document.getElementById, so HTMLElement | null) and\nthe class fields actionBar / commitSelect / richDiffBtn\n(typed as nullable) were unconditionally accessed via \n[…]\nt assertion that elides\nin the emit, restoring the original throw-on-null behaviour.\n\nVerified:\n web/diff.js: 15 -> 0 '?.' inside _setPanel\n 433/433 JS tests still pass\n typecheck + build:web clean",
"is_bot": false,
"headline": "refactor(ts): remove 15 '?.' leaks in diff.ts _setPanel (Phase 4 audit)",
"author_name": "Xi Ma Chen",
"author_login": "hypernewbie",
"committed_at": "2026-07-15T02:55:27Z",
"body_truncated": true,
"is_coding_agent": false
}
],
"releases_count": 41,
"commits_last_year": 530,
"latest_release_at": "2026-07-27T04:47:30Z",
"latest_release_tag": "v0.15.1",
"releases_from_tags": false,
"days_since_last_push": 0,
"active_weeks_last_year": 9,
"days_since_latest_release": 0,
"mean_days_between_releases": 1.1
},
"community": {
"has_readme": true,
"has_license": false,
"has_description": true,
"has_contributing": false,
"health_percentage": 28,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"ecosystem": {
"packages": [
{
"name": "github.com/hypernewbie/phi",
"exists": true,
"license": null,
"keywords": [],
"ecosystem": "go",
"matches_repo": true,
"registry_url": "https://pkg.go.dev/github.com/hypernewbie/phi",
"is_deprecated": false,
"latest_version": "v0.15.1",
"repository_url": "https://github.com/hypernewbie/phi",
"versions_count": 42,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": null,
"monthly_downloads": null,
"first_published_at": null,
"latest_published_at": "2026-07-26T10:53:39Z",
"latest_version_yanked": null,
"days_since_latest_publish": 1
},
{
"name": "@hypernewbie/phi-code",
"exists": true,
"license": "MIT",
"keywords": [
"terminal",
"multiplexer",
"ai",
"opencode",
"claude",
"antigravity"
],
"ecosystem": "npm",
"matches_repo": true,
"registry_url": "https://www.npmjs.com/package/@hypernewbie/phi-code",
"is_deprecated": false,
"latest_version": "0.15.1",
"repository_url": "https://github.com/hypernewbie/phi",
"versions_count": 38,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": 1,
"monthly_downloads": 7125,
"first_published_at": "2026-07-01T14:47:21.455000Z",
"latest_published_at": "2026-07-27T04:47:44.483000Z",
"latest_version_yanked": null,
"days_since_latest_publish": 0
}
]
},
"popularity": {
"forks": 2,
"stars": 4,
"watchers": 0,
"fork_history": {
"days": [
{
"date": "2026-07-21",
"count": 1
},
{
"date": "2026-07-22",
"count": 1
}
],
"complete": true,
"collected": 2,
"total_forks": 2
},
"star_history": null,
"open_issues_and_prs": 0
},
"ai_readiness": {
"has_nix": false,
"example_dirs": [],
"has_llms_txt": false,
"has_dockerfile": false,
"has_mcp_signal": false,
"bootstrap_files": [],
"api_schema_files": [],
"has_devcontainer": false,
"typecheck_configs": [
"tsconfig.json"
],
"toolchain_manifests": [
"go.mod"
],
"largest_source_bytes": 223079,
"source_files_sampled": 192,
"oversized_source_files": 5,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"dependencies": {
"manifests": [
"go.mod",
"npm/package.json",
"package.json"
],
"advisories": {
"error": null,
"scope": null,
"source": null,
"findings": [],
"collected": false,
"malicious": [],
"truncated": false,
"by_severity": {},
"advisory_count": 0,
"affected_count": 0,
"assessed_count": 0,
"malicious_count": 0,
"assessed_package": null,
"unassessed_count": 0,
"direct_affected_count": 0
},
"ecosystems": [
"go",
"npm"
],
"dependencies": [
{
"name": "github.com/XSAM/otelsql",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.43.0"
},
{
"name": "github.com/aymanbagabas/go-pty",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.2.3"
},
{
"name": "github.com/fsnotify/fsnotify",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.10.1"
},
{
"name": "github.com/gorilla/websocket",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.5.3"
},
{
"name": "github.com/shirou/gopsutil/v4",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v4.26.5"
},
{
"name": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.69.0"
},
{
"name": "go.opentelemetry.io/otel",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.44.0"
},
{
"name": "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.44.0"
},
{
"name": "go.opentelemetry.io/otel/sdk",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.44.0"
},
{
"name": "go.opentelemetry.io/otel/trace",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.44.0"
},
{
"name": "modernc.org/sqlite",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.51.0"
}
],
"all_dependencies": {
"error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
"source": null,
"packages": [],
"collected": false,
"truncated": false,
"total_count": null,
"direct_count": null,
"indirect_count": null
}
},
"maintainership": {
"issues": {
"open_prs": 0,
"merged_prs": 5,
"open_issues": 0,
"closed_ratio": null,
"closed_issues": 0,
"closed_unmerged_prs": 9
},
"bus_factor": 1,
"bot_contributors": 0,
"top_contributors": [
{
"type": "User",
"login": "hypernewbie",
"commits": 507,
"avatar_url": "https://avatars.githubusercontent.com/u/5387547?v=4"
},
{
"type": "User",
"login": "n0mad-awx",
"commits": 10,
"avatar_url": "https://avatars.githubusercontent.com/u/307825858?v=4"
}
],
"contributors_sampled": 2,
"top_contributor_share": 0.981
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"fix-dist-tag.yml",
"release.yml",
"test.yml"
],
"has_docs_dir": false,
"linter_configs": [],
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"security_signals": {
"lockfiles": [
"go.sum",
"package-lock.json"
],
"scorecard": {
"checks": [
{
"name": "Binary-Artifacts",
"score": 9,
"reason": "binaries present in source code",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
},
{
"name": "Branch-Protection",
"score": 0,
"reason": "branch protection not enabled on development/release branches",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
},
{
"name": "CI-Tests",
"score": 10,
"reason": "4 out of 4 merged PRs checked by a CI test -- score normalized to 10",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
},
{
"name": "CII-Best-Practices",
"score": 0,
"reason": "no effort to earn an OpenSSF best practices badge detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
},
{
"name": "Code-Review",
"score": 1,
"reason": "Found 4/30 approved changesets -- score normalized to 1",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
},
{
"name": "Contributors",
"score": 3,
"reason": "project has 1 contributing companies or organizations -- score normalized to 3",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
},
{
"name": "Dangerous-Workflow",
"score": 10,
"reason": "no dangerous workflow patterns detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
},
{
"name": "Dependency-Update-Tool",
"score": 0,
"reason": "no update tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
},
{
"name": "Fuzzing",
"score": 10,
"reason": "project is fuzzed",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
},
{
"name": "License",
"score": 0,
"reason": "license file not detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
},
{
"name": "Maintained",
"score": 0,
"reason": "project was created within the last 90 days. Please review its contents carefully",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
},
{
"name": "Packaging",
"score": 10,
"reason": "packaging workflow detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
},
{
"name": "Pinned-Dependencies",
"score": 5,
"reason": "dependency not pinned by hash detected -- score normalized to 5",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
},
{
"name": "SAST",
"score": 0,
"reason": "SAST tool is not run on all commits -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
},
{
"name": "Security-Policy",
"score": 0,
"reason": "security policy file not detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
},
{
"name": "Signed-Releases",
"score": 0,
"reason": "Project has not signed or included provenance with any releases.",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
},
{
"name": "Token-Permissions",
"score": 0,
"reason": "detected GitHub workflow tokens with excessive permissions",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
},
{
"name": "Vulnerabilities",
"score": 0,
"reason": "24 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "f5b0d54dc058bf964c3934e92ac03ef8bfffea4d",
"ran_at": "2026-07-27T17:05:52Z",
"aggregate_score": 3.2,
"scorecard_version": "v5.5.0"
},
"has_codeql_workflow": false,
"has_security_policy": false,
"has_dependabot_config": false
},
"contribution_flow": {
"collected": true,
"ci_last_run_at": "2026-07-27T07:58:54Z",
"oldest_open_prs": [],
"last_merged_pr_at": "2026-07-24T02:11:38Z",
"ci_last_conclusion": "SUCCESS",
"oldest_open_issues": []
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/hypernewbie/phi",
"host": "github.com",
"name": "phi",
"owner": "hypernewbie"
},
"metrics": {
"overall": {
"key": "overall",
"band": "moderate",
"name": "Overall health",
"note": null,
"notes": [],
"value": 50,
"inputs": {
"security": 32,
"vitality": 72,
"community": 28,
"governance": 46,
"engineering": 65
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "good",
"name": "Vitality",
"value": 72,
"weight": 0.22,
"metrics": [
{
"key": "development_activity",
"band": "moderate",
"name": "Development activity",
"note": null,
"notes": [],
"value": 60,
"inputs": {
"commits_last_year": 530,
"human_commit_share": 1,
"days_since_last_push": 0,
"active_weeks_last_year": 9
},
"components": [
{
"key": "push_recency",
"name": "Push recency",
"detail": "last push 0 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "push_recency",
"params": {
"days": 0
}
}
],
"max_points": 36
},
{
"key": "commit_cadence",
"name": "Commit cadence",
"detail": "9/52 weeks with commits",
"points": 6.2,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 9
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "530 commits in the last year",
"points": 18,
"status": "met",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 530
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "project was created within the last 90 days. Please review its contents carefully",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "release_discipline",
"band": "excellent",
"name": "Release discipline",
"note": null,
"notes": [],
"value": 90,
"inputs": {
"releases_count": 41,
"latest_release_tag": "v0.15.1",
"releases_from_tags": false,
"days_since_latest_release": 0,
"mean_days_between_releases": 1.1
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "41 releases published",
"points": 27,
"status": "met",
"details": [
{
"code": "releases_published",
"params": {
"count": 41
}
}
],
"max_points": 27
},
{
"key": "release_recency",
"name": "Release recency",
"detail": "latest release 0 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "release_recency",
"params": {
"days": 0
}
}
],
"max_points": 36
},
{
"key": "release_cadence",
"name": "Release cadence",
"detail": "a release every ~1.1 days",
"points": 27,
"status": "met",
"details": [
{
"code": "release_cadence",
"params": {
"gap": 1.1
}
}
],
"max_points": 27
},
{
"key": "openssf_scorecard_signed_releases",
"name": "OpenSSF Scorecard: Signed-Releases",
"detail": "Project has not signed or included provenance with any releases.",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "abandonment",
"band": "excellent",
"name": "Abandonment",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"cap": null,
"state": "unverified",
"guards": [],
"signals": [],
"red_flag": false,
"multiplier_pct": 100,
"declared_reason": null,
"unverified_reason": "repository_too_young",
"unanswered_open_prs": null,
"unanswered_open_issues": null,
"days_since_last_merged_pr": null,
"days_since_last_human_commit": null,
"days_since_last_human_commit_is_floor": false
},
"components": [
{
"key": "project_is_still_maintained",
"name": "Project is still maintained",
"detail": "maintenance record not established from the collected data",
"points": 100,
"status": "met",
"details": [
{
"code": "abandonment_unverified",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Is the project alive — is code being written and are releases shipping?"
},
{
"key": "community",
"band": "critical",
"name": "Community & Adoption",
"value": 28,
"weight": 0.18,
"metrics": [
{
"key": "popularity",
"band": "critical",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 8,
"inputs": {
"forks": 2,
"stars": 4,
"watchers": 0,
"growth_state": "unverified",
"growth_factor_pct": 100,
"growth_unverified_reason": "no_history"
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "4 stars",
"points": 7.7,
"status": "partial",
"details": [
{
"code": "stars",
"params": {
"count": 4
}
}
],
"max_points": 60
},
{
"key": "forks",
"name": "Forks",
"detail": "2 forks",
"points": 0,
"status": "missed",
"details": [
{
"code": "forks",
"params": {
"count": 2
}
}
],
"max_points": 25
},
{
"key": "watchers",
"name": "Watchers",
"detail": "0 watchers",
"points": 0,
"status": "missed",
"details": [
{
"code": "watchers",
"params": {
"count": 0
}
}
],
"max_points": 15
}
]
},
{
"key": "community_health",
"band": "critical",
"name": "Community health",
"note": null,
"notes": [],
"value": 25,
"inputs": {
"has_readme": true,
"has_license": false,
"has_contributing": false,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 22.5,
"status": "met",
"details": [],
"max_points": 22.5
},
{
"key": "license",
"name": "License",
"detail": "no license file detected",
"points": 0,
"status": "missed",
"details": [
{
"code": "license_absent",
"params": {}
}
],
"max_points": 22.5
},
{
"key": "contributing_guide",
"name": "CONTRIBUTING guide",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 18
},
{
"key": "code_of_conduct",
"name": "Code of conduct",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 13.5
},
{
"key": "issue_template",
"name": "Issue template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.2
},
{
"key": "pr_template",
"name": "PR template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.3
}
]
},
{
"key": "ecosystem_adoption",
"band": "moderate",
"name": "Ecosystem adoption (downloads)",
"note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"registry_dependents"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 64,
"inputs": {
"packages": [
"github.com/hypernewbie/phi",
"@hypernewbie/phi-code"
],
"dependents": null,
"ecosystems": "go, npm",
"total_downloads": null,
"monthly_downloads": 7125
},
"components": [
{
"key": "monthly_downloads",
"name": "Monthly downloads",
"detail": "7,125 downloads/month across go, npm",
"points": 51.4,
"status": "partial",
"details": [
{
"code": "downloads_monthly",
"params": {
"count": 7125,
"ecosystems": "go, npm"
}
}
],
"max_points": 80
},
{
"key": "registry_dependents",
"name": "Registry dependents",
"detail": "not reported by this ecosystem",
"points": 0,
"status": "excluded",
"details": [
{
"code": "not_reported_by_this_ecosystem",
"params": {}
}
],
"max_points": 20
}
]
}
],
"description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
},
{
"key": "governance",
"band": "at_risk",
"name": "Sustainability & Governance",
"value": 46,
"weight": 0.24,
"metrics": [
{
"key": "maintainer_resilience",
"band": "critical",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 15,
"inputs": {
"bus_factor": 1,
"contributors_sampled": 2,
"top_contributor_share": 0.981
},
"components": [
{
"key": "bus_factor",
"name": "Bus factor",
"detail": "1 contributor(s) cover half of all commits",
"points": 9,
"status": "partial",
"details": [
{
"code": "bus_factor",
"params": {
"count": 1
}
}
],
"max_points": 54
},
{
"key": "commit_distribution",
"name": "Commit distribution",
"detail": "top contributor authored 98% of commits",
"points": 0.4,
"status": "partial",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 98
}
}
],
"max_points": 22.5
},
{
"key": "contributor_breadth",
"name": "Contributor breadth",
"detail": "2 contributors",
"points": 2.7,
"status": "partial",
"details": [
{
"code": "contributors_sampled",
"params": {
"count": 2
}
}
],
"max_points": 13.5
},
{
"key": "openssf_scorecard_contributors",
"name": "OpenSSF Scorecard: Contributors",
"detail": "project has 1 contributing companies or organizations -- score normalized to 3",
"points": 3,
"status": "partial",
"details": [],
"max_points": 10
}
]
},
{
"key": "responsiveness",
"band": "critical",
"name": "Issue & PR responsiveness",
"note": "Excluded from scoring (no data or not applicable): Issue resolution. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"issue_resolution"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 29,
"inputs": {
"merged_prs": 5,
"open_issues": 0,
"closed_issues": 0,
"issue_closed_ratio": null,
"closed_unmerged_prs": 9
},
"components": [
{
"key": "issue_resolution",
"name": "Issue resolution",
"detail": "no issues or no data",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_issues_or_data",
"params": {}
}
],
"max_points": 46.75
},
{
"key": "pr_acceptance",
"name": "PR acceptance",
"detail": "5/14 decided PRs merged",
"points": 13.7,
"status": "partial",
"details": [
{
"code": "decided_prs_merged",
"params": {
"merged": 5,
"decided": 14
}
}
],
"max_points": 38.25
},
{
"key": "openssf_scorecard_code_review",
"name": "OpenSSF Scorecard: Code-Review",
"detail": "Found 4/30 approved changesets -- score normalized to 1",
"points": 1.5,
"status": "partial",
"details": [],
"max_points": 15
}
]
},
{
"key": "stewardship",
"band": "moderate",
"name": "Ownership & stewardship",
"note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"verified_domain"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 57,
"inputs": {
"followers": 37,
"owner_type": "User",
"is_verified": null,
"owner_login": "hypernewbie",
"public_repos": 43,
"account_age_days": 4708
},
"components": [
{
"key": "ownership_backing",
"name": "Ownership backing",
"detail": "personal (user) account",
"points": 10,
"status": "partial",
"details": [
{
"code": "owner_personal",
"params": {}
}
],
"max_points": 30
},
{
"key": "verified_domain",
"name": "Verified domain",
"detail": "not applicable to user accounts",
"points": 0,
"status": "excluded",
"details": [
{
"code": "not_applicable_to_user_accounts",
"params": {}
}
],
"max_points": 20
},
{
"key": "owner_reach",
"name": "Owner reach",
"detail": "37 followers of hypernewbie",
"points": 11.4,
"status": "partial",
"details": [
{
"code": "owner_followers",
"params": {
"count": 37,
"login": "hypernewbie"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "43 public repos, account ~12 yr old",
"points": 24,
"status": "partial",
"details": [
{
"code": "public_repos",
"params": {
"count": 43
}
},
{
"code": "account_age_years",
"params": {
"years": 12
}
}
],
"max_points": 25
}
]
},
{
"key": "package_maintenance",
"band": "excellent",
"name": "Package maintenance",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"packages": [
"github.com/hypernewbie/phi",
"@hypernewbie/phi-code"
],
"ecosystems": "go, npm",
"any_deprecated": false,
"min_days_since_publish": 0
},
"components": [
{
"key": "published_resolvable",
"name": "Published & resolvable",
"detail": "2 package(s) on go, npm",
"points": 25,
"status": "met",
"details": [
{
"code": "packages_published",
"params": {
"count": 2,
"ecosystems": "go, npm"
}
}
],
"max_points": 25
},
{
"key": "publish_recency",
"name": "Publish recency",
"detail": "latest publish 0 days ago",
"points": 35,
"status": "met",
"details": [
{
"code": "publish_recency",
"params": {
"days": 0
}
}
],
"max_points": 35
},
{
"key": "version_history",
"name": "Version history",
"detail": "42 published versions",
"points": 20,
"status": "met",
"details": [
{
"code": "published_versions",
"params": {
"count": 42
}
}
],
"max_points": 20
},
{
"key": "not_deprecated",
"name": "Not deprecated",
"detail": "active, not deprecated or yanked",
"points": 20,
"status": "met",
"details": [
{
"code": "package_not_deprecated",
"params": {}
}
],
"max_points": 20
}
]
}
],
"description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
},
{
"key": "engineering",
"band": "moderate",
"name": "Engineering Quality",
"value": 65,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "moderate",
"name": "Engineering practices",
"note": null,
"notes": [],
"value": 68,
"inputs": {
"has_ci": true,
"has_tests": true,
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"components": [
{
"key": "ci_workflows",
"name": "CI workflows",
"detail": "3 workflow(s)",
"points": 24,
"status": "met",
"details": [
{
"code": "ci_workflows",
"params": {
"count": 3
}
}
],
"max_points": 24
},
{
"key": "tests_present",
"name": "Tests present",
"detail": null,
"points": 24,
"status": "met",
"details": [],
"max_points": 24
},
{
"key": "linter_config",
"name": "Linter config",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 16
},
{
"key": "pre_commit_hooks",
"name": "Pre-commit hooks",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 9.6
},
{
"key": "editorconfig",
"name": ".editorconfig",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.4
},
{
"key": "openssf_scorecard_ci_tests",
"name": "OpenSSF Scorecard: CI-Tests",
"detail": "4 out of 4 merged PRs checked by a CI test -- score normalized to 10",
"points": 20,
"status": "met",
"details": [],
"max_points": 20
}
]
},
{
"key": "documentation",
"band": "moderate",
"name": "Documentation",
"note": null,
"notes": [],
"value": 60,
"inputs": {
"topics": [
"ai",
"antigravity",
"claude-code",
"coding-assistant",
"developer-tools",
"golang",
"multiplexer",
"opencode",
"pty",
"terminal",
"websocket",
"xterm-js"
],
"has_wiki": true,
"homepage": null,
"has_readme": true,
"has_docs_dir": false,
"has_description": true
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 30,
"status": "met",
"details": [],
"max_points": 30
},
{
"key": "documentation_directory",
"name": "Documentation directory",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 25
},
{
"key": "documentation_homepage_site",
"name": "Documentation / homepage site",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "repository_description",
"name": "Repository description",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "topics",
"name": "Topics",
"detail": "12 topics",
"points": 10,
"status": "met",
"details": [
{
"code": "topics_count",
"params": {
"count": 12
}
}
],
"max_points": 10
},
{
"key": "wiki",
"name": "Wiki",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
}
],
"description": "Are baseline engineering and documentation practices in place?"
},
{
"key": "security",
"band": "at_risk",
"name": "Security",
"value": 32,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "at_risk",
"name": "Security posture",
"note": null,
"notes": [],
"value": 32,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 18,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 0,
"scorecard_aggregate": 3.2
},
"components": [
{
"key": "binary_artifacts",
"name": "Binary-Artifacts",
"detail": "binaries present in source code",
"points": 6.8,
"status": "partial",
"details": [],
"max_points": 7.5
},
{
"key": "branch_protection",
"name": "Branch-Protection",
"detail": "branch protection not enabled on development/release branches",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "ci_tests",
"name": "CI-Tests",
"detail": "4 out of 4 merged PRs checked by a CI test -- score normalized to 10",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "cii_best_practices",
"name": "CII-Best-Practices",
"detail": "no effort to earn an OpenSSF best practices badge detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "code_review",
"name": "Code-Review",
"detail": "Found 4/30 approved changesets -- score normalized to 1",
"points": 0.8,
"status": "partial",
"details": [],
"max_points": 7.5
},
{
"key": "contributors",
"name": "Contributors",
"detail": "project has 1 contributing companies or organizations -- score normalized to 3",
"points": 0.8,
"status": "partial",
"details": [],
"max_points": 2.5
},
{
"key": "dangerous_workflow",
"name": "Dangerous-Workflow",
"detail": "no dangerous workflow patterns detected",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "dependency_update_tool",
"name": "Dependency-Update-Tool",
"detail": "no update tool detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "fuzzing",
"name": "Fuzzing",
"detail": "project is fuzzed",
"points": 5,
"status": "met",
"details": [],
"max_points": 5
},
{
"key": "license",
"name": "License",
"detail": "license file not detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "maintained",
"name": "Maintained",
"detail": "project was created within the last 90 days. Please review its contents carefully",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "packaging",
"name": "Packaging",
"detail": "packaging workflow detected",
"points": 5,
"status": "met",
"details": [],
"max_points": 5
},
{
"key": "pinned_dependencies",
"name": "Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 5",
"points": 2.5,
"status": "partial",
"details": [],
"max_points": 5
},
{
"key": "sast",
"name": "SAST",
"detail": "SAST tool is not run on all commits -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "security_policy",
"name": "Security-Policy",
"detail": "security policy file not detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "signed_releases",
"name": "Signed-Releases",
"detail": "Project has not signed or included provenance with any releases.",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "token_permissions",
"name": "Token-Permissions",
"detail": "detected GitHub workflow tokens with excessive permissions",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "vulnerabilities",
"name": "Vulnerabilities",
"detail": "24 existing vulnerabilities detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
}
]
},
{
"key": "high_risk_jurisdiction_exposure",
"band": "excellent",
"name": "High-Risk Jurisdiction Exposure",
"note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
"notes": [
{
"code": "jurisdiction_evidence_limits",
"params": {}
}
],
"value": 100,
"inputs": {
"meaning": "self-published location evidence; not nationality or citizenship",
"red_flag": false,
"exposures": [],
"policy_countries": [
"Russia",
"Iran",
"North Korea"
],
"review_only_matches": 0,
"assessed_self_published_locations": 2
},
"components": [
{
"key": "policy_exposure_multiplier",
"name": "Policy exposure multiplier",
"detail": "no confirmed policy-scope location match",
"points": 100,
"status": "met",
"details": [
{
"code": "jurisdiction_no_match",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
},
{
"key": "ai_readiness",
"band": "moderate",
"name": "AI Readiness",
"value": 62,
"weight": 0,
"metrics": [
{
"key": "ai_agent_context",
"band": "at_risk",
"name": "Agent context & guidance",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"has_llms_txt": false,
"legible_history_share": 0.93,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"components": [
{
"key": "agent_instructions",
"name": "Agent instructions",
"detail": "no CLAUDE.md / AGENTS.md / editor rules",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_agent_instructions",
"params": {}
}
],
"max_points": 45
},
{
"key": "machine_readable_docs_llms_txt",
"name": "Machine-readable docs (llms.txt)",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "legible_commit_history",
"name": "Legible commit history",
"detail": "93 of 100 human commits state their intent (structured subject or explanatory body)",
"points": 40,
"status": "met",
"details": [
{
"code": "legible_history",
"params": {
"legible": 93,
"sampled": 100
}
}
],
"max_points": 40
}
]
},
{
"key": "ai_verify_loop",
"band": "good",
"name": "Verify loop (build / test / typecheck)",
"note": null,
"notes": [],
"value": 71,
"inputs": {
"has_nix": false,
"has_tests": true,
"lockfiles": [
"go.sum",
"package-lock.json"
],
"has_dockerfile": false,
"typed_language": false,
"bootstrap_files": [],
"has_devcontainer": false,
"has_linter_config": false,
"typecheck_configs": [
"tsconfig.json"
],
"agent_commit_share": 0.22,
"toolchain_manifests": [
"go.mod"
],
"dependency_bot_commit_share": 0
},
"components": [
{
"key": "one_command_bootstrap",
"name": "One-command bootstrap",
"detail": "go.mod (toolchain convention, no task runner)",
"points": 12.6,
"status": "partial",
"details": [
{
"code": "toolchain_convention",
"params": {
"files": "go.mod"
}
}
],
"max_points": 18
},
{
"key": "automated_tests",
"name": "Automated tests",
"detail": null,
"points": 22,
"status": "met",
"details": [],
"max_points": 22
},
{
"key": "lint_format_config",
"name": "Lint / format config",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 11
},
{
"key": "static_type_checking",
"name": "Static type checking",
"detail": "tsconfig.json",
"points": 11,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "tsconfig.json"
}
}
],
"max_points": 11
},
{
"key": "reproducible_environment",
"name": "Reproducible environment",
"detail": "lockfile",
"points": 10,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "lockfile"
}
}
],
"max_points": 10
},
{
"key": "demonstrated_agent_practice",
"name": "Demonstrated agent practice",
"detail": "22 of the last 100 commits agent-authored or agent-credited",
"points": 10,
"status": "met",
"details": [
{
"code": "agent_authored_commits",
"params": {
"count": 22,
"sampled": 100
}
}
],
"max_points": 10
},
{
"key": "automated_maintenance",
"name": "Automated maintenance",
"detail": "no automated dependency updates observed",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_dependency_automation",
"params": {}
}
],
"max_points": 8
},
{
"key": "openssf_scorecard_pinned_dependencies",
"name": "OpenSSF Scorecard: Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 5",
"points": 5,
"status": "partial",
"details": [],
"max_points": 10
}
]
},
{
"key": "ai_code_legibility",
"band": "good",
"name": "Code legibility for models",
"note": null,
"notes": [],
"value": 81,
"inputs": {
"primary_language": "JavaScript",
"largest_source_bytes": 223079,
"source_files_sampled": 192,
"oversized_source_files": 5
},
"components": [
{
"key": "type_checkable_code",
"name": "Type-checkable code",
"detail": "JavaScript with type-check config (tsconfig.json)",
"points": 27,
"status": "partial",
"details": [
{
"code": "typecheck_config_language",
"params": {
"files": "tsconfig.json",
"language": "JavaScript"
}
}
],
"max_points": 45
},
{
"key": "manageable_file_sizes",
"name": "Manageable file sizes",
"detail": "5/192 source files over 60KB",
"points": 53.6,
"status": "partial",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 192,
"oversized": 5
}
}
],
"max_points": 55
}
]
}
],
"description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
}
],
"metrics_version": "1.13.0"
},
"warnings": [
"Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
"GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
"deps.dev does not index npm:@hypernewbie/phi-code@0.15.1; advisories assessed against the repository dependency graph instead"
],
"report_type": "repository",
"generated_at": "2026-07-27T17:06:03.272611Z",
"schema_version": "0.27.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/h/hypernewbie/phi.svg",
"full_name": "hypernewbie/phi",
"license_state": "absent",
"license_spdx": null
}