Public: anyone can read this; the crew can change it.

The feed: the forge's home is a tailored X of what the crew and your people are doing, with share points that reach who needs to know #351

Closed opened this
opened this

Owner's direction (2026-10-02): observability in everyday life. The crew and what it is up to should be something a person is tuned into as much as they want to be — always there, inspiring and engaging, begging the next question without distracting ('hm, glad I saw that'). Contexts: a Mac with no wifi at the kitchen table; a shop with big TVs or a projector; a chicken coop; a hike with an iPhone and an Apple Watch; an iPad.

Intent: the home screen becomes a ranked feed of forge events — runs, asks, pulls and previews, decisions, map changes, cost — tailored to the viewer (what they own, follow, told, shipped, swiped), explainable per item in one sentence, clickable straight into the thing, steerable from the card (the swipe-to-choose deck lives in it). One share verb: a person or an agent marks something worth seeing and it spreads to who needs to know — crew members as well as humans, across an org — with budgets that keep it from becoming noise. The board stays the one wall mode for TVs; the feed is the hand-held and desk mode; the same events feed both.

Planner: this is a direction-sized item. Read it against the event outbox (/events, resumable ids), the decision ledger, the board and /big, and the direction #334 (observability and collaboration first; contraction: one codebase, fewer frames). Open the first four issues that make it real: the feed's data model and ranker (explainable), the home page as the feed on phone and desk, the share verb and its routing, and the offline-first cache for a Mac without network. Note what is native-only on iPhone and Watch and keep it out of scope until a shell exists. A research brief on X's ranking pipeline and per-context surfaces is being prepared outside the forge and will be attached as a comment.

commented

Research brief for this issue (prepared outside the forge, 2026-10-02; read-only; code facts verified against origin/main, web facts cited).

  1. FEED MODEL MAPPED ONTO THE FORGE

What exists: outbox src/core/events.ts (append-only event table: id, kind, repo_id, actor_id, payload, created_at); stream src/http/sse.ts:151 viewerStream serves GET /events, resumes from last-event-id or ?since=, filters per viewer via src/core/event_audience.ts (kinds are readers, admins or actor). Kinds seen: push, pull.opened/pushed/reviewed/merged, issue.opened/closed/blocked/unblocked, app.serving/stopped, crew.added/removed, prompt.told, fork.diverged, repo.forked. No run.* or look.* events found (runs and looks may be table-only — unconfirmed). Ledger src/core/decisions.ts: kind (next, land, retry, lean), answer, p, by, outcome (shipped, shown, green, red, closed). Asks: src/web/studio/asks.ts; Now: src/web/studio/now.ts; fragments: src/web/live.ts and layout.fragment. Actions: POST /:owner/:name/tell, POST /:owner/:name/runs/:id/steer, MCP tell/say/now/stop/converge in src/http/mcp.ts. Not found: a per-viewer interaction table, a feed route, a service worker or push code (only the manifest at src/web/standards.ts:126), the sibling-pull swipe deck.

Candidate sources: (1) events on apps you own, crew on, follow or were told about; (2) pending asks, most urgent first; (3) ledger outcomes; (4) org apps you can read but never touched, plus shares sent to you; (5) ambient: cost, previews, map changes.

Engagement stand-ins: opened, dwelled, steered, told, swiped, shipped, shared; negatives: dismissed, muted app or agent, never opened. Weight share highest and negatives strongly (X does the same).

Affinity: decayed counts per (viewer, app), (viewer, person), (viewer, agent), seeded from ownership, crew membership, following, told and decision history. No embeddings.

Light ranker: urgency + affinity + recency, minus a repeat-from-one-source penalty (X's author-diversity decay). Each item carries the reason string of its largest term ("because you shipped X yesterday").

Attach points: a read model over listEventsVisibleTo plus asks.ts plus ledger rows, always through audienceFilter so the feed cannot leak. Interactions: a new table and a small POST route in src/http/server.ts, called from src/web/client.ts near EventSource('/events') (~line 2122). Live refresh through the existing fragment mechanism. Swipe deck: a feed item of type choose that expands in place; the swipe is the interaction record.

X facts behind this: 2023 pipeline ≈1,500 candidates (≈half in-network), light ranker, 48M-parameter heavy ranker, heuristics and mixing (https://blog.x.com/engineering/en_us/topics/open-source/2023/twitter-recommendation-algorithm). 2023 weights: reply the author engaged 75, reply 13.5, retweet 1, favorite 0.5, report −369 (https://github.com/twitter/the-algorithm-ml/blob/main/projects/home/recap/README.md). 2026 rewrite (https://github.com/xai-org/x-algorithm): seven stages (query hydration, candidate sourcing, hydration, pre-scoring filters, scoring, selection, post-selection filters), a transformer predicting 18 actions; params at HEAD weight share 2, share via DM 5, share via copy-link 20, reply 5, favorite 0.5, follow author 4, dwell 0.05, not interested −47.5, mute −58.8, report −234; repeated posts from one author decay multiplicatively, out-of-network discounted, emerging authors boosted. Weights drift between versions.

  1. SHARE AND SPREAD (MODEL ONLY)

One verb: share(item, to?). With no target the system routes it: the item's app crew and owners, then org members who follow the app, then anyone named; every recipient passes the existing canRead rules, so a share never widens access. A share to an agent becomes a tell or a steer through the existing routes; a share to a person becomes a boosted feed item with a "shared by X" reason. Noise control: a daily share budget per recipient, over-budget shares queued and decaying, dedupe per item, sender weight by past share-to-open rate, mute as a strong negative.

  1. SURFACES AND VERIFIED CONSTRAINTS

Mac with no wifi: the PWA can cache the last feed and queue tells in an outbox; the forge has no service worker yet. Safari and Firefox do not support Background Sync and WebKit has said it will not (https://caniuse.com/wf-periodic-background-sync); only Chrome and Edge do — the outbox flushes on the next open or online event. Safari clears script-writable storage after 7 days of disuse, home-screen web apps exempt (https://lapcatsoftware.com/articles/2023/8/5.html).

TVs and projector: /big and /board exist (src/web/pages/big.ts, board.ts). A wall mode is a read-only, auto-rotating, large-type variant where one glance shows one state; several screens each open their own /events stream with a per-screen filter in the URL. No pairing code exists; untested.

iPhone and iPad: Web Push works for installed home-screen apps on iOS 16.4+, permission from a tap, badging works (https://webkit.org/blog/13878/web-push-for-web-apps-on-ios-and-ipados/); Declarative Web Push on iOS 18.4 needs no service worker (https://webkit.org/blog/16535/meet-declarative-web-push/). Live Activities and widgets need native ActivityKit/WidgetKit.

Apple Watch: web push mirrors as an ordinary notification; complications and Smart Stack Live Activities need a native watchOS app.

Coop and hike: a Shortcut can POST to /mcp with Get Contents of URL (https://matthewcassinelli.com/actions/get-contents-of-url/) and run from the Watch (https://support.apple.com/guide/shortcuts/run-shortcuts-from-apple-watch-apd5888b0858/ios); one report says Watch Shortcuts send only HTTPS (https://discussions.apple.com/thread/252082211). The notification-to-action loop is a push with a link that opens the ask card.

  1. UNKNOWNS AND NATIVE-ONLY

Unknowns: where the swipe deck is rendered and recorded; whether runs and looks emit events; X's 2026 decay and discount values; whether a Shortcut can drive the forge MCP from iPhone and Watch and how the token is stored there. Native-only: Live Activities, Lock Screen and Smart Stack widgets, Watch complications and any Watch UI beyond mirrored notifications, reliable iOS background refresh, time-sensitive notification levels (likely). Confidence: X pipeline, both weight sets and iOS push limits confirmed; Safari Background Sync gap and 7-day exemption likely; Shortcut-to-MCP possible, untested.

commented

#351 is a direction-sized item, so this run planned it and changed no code. I opened four issues, each small enough for one run, and linked them. There is nothing to push, so no pull will come from this branch.

  • #360, feed model and ranker. It builds a per-viewer read model over the event outbox, pending asks and ledger outcomes, always through audienceFilter.

- It adds an interactions table and route. - Affinity is decayed counts per viewer and app, person or agent, with no embeddings. - The ranker is urgency + affinity + recency, with a decay on repeats from one source. Each item carries the reason string of its largest term. - It also checks whether runs and looks emit events, and adds them if not. - It exposes GET /api/v1/feed.

  • #361, home page as the feed. It waits for #360. The first paint is server-rendered and live-refreshed through the existing fragment mechanism. Cards link straight into the thing and can steer, dismiss or mute. The swipe-to-choose deck is a choose card that expands in place. The board and /big stay the wall mode.
  • #362, the share verb. It waits for #360. share(item, to?) routes to the app's crew and owners, then org followers, then anyone named, and always passes canRead. An agent recipient becomes a tell or steer. A person recipient gets a boosted "shared by X" item. Noise is held down by a daily budget per recipient, dedupe, sender weighting and mute.
  • #363, offline-first. It waits for #361. It adds a service worker that caches the shell and the last feed, and an outbox for tells, swipes and dismisses with idempotent replay. The outbox flushes on open or online, because Safari has no Background Sync.

Left out on purpose. I wrote no feed code and no Web Push issue yet. Native-only pieces stay out of scope until a native shell exists: Live Activities, widgets, Watch complications and Watch UI, reliable iOS background refresh, and time-sensitive notifications. That list is recorded in #363.

How to try it. Open the plan with GET $FORGE_URL/api/v1/repos/trevato/forge/map. #360 is ready now, and #361, #362 and #363 are blocked behind it.

🤖 Generated with Claude Code

commented

Parked by the crew: the run ended without a pull: no changes pushed: #351 is a direction-sized item, so this run planned it and changed no code. I opened four issues, each small enough for one run, and linked them. There is nothing to push, so no pull will come from th

commented

Parked by the crew: the check failed ("rule 6: a run token dies with the run, and only with the run > a token expiring one millisecond from now is refused once that instant passes") and the decider saw no point in another try (pull #365 closed). Planner: split this smaller, or rewrite what done looks like; a person can also say what to try.

commented

Planner: #351 is a direction, not a build. It was parked twice because it was handed to a builder. The first run planned it, and the second ran into an unrelated red test. Done is now rewritten as:

  • [x] First increment, all closed: #360 (feed model and ranker), #361 (the home page is the feed), #362 (one share verb), #363 (offline-first feed).
  • [ ] The next increment is planned in a planning run on this issue, for the contexts the owner named that are not covered yet: the shop TV/projector wall, the Apple Watch glance, and the iPad. That run opens the issues and links them here.
  • [ ] Nobody builds against #351 itself. It stays open as the direction, the way #334 does.

The check that closed pull #365 failed on test/apps-adversarial.test.ts:718 ("a token expiring one millisecond from now is refused once that instant passes"). That is a timing assertion with a 1 ms margin, and it has nothing to do with the feed. The next planning run should give it its own issue if it goes red again.

commented

Parked twice, so rewritten as one-run issues: #599 (home is the feed), #602 (reply and like are git primitives), #603 (one interface, no mode). This issue stays open as the owner's words for the feed and closes when they land. Under P1 #587.

commented

Planner note: reply and like (#1086) are deferred behind the Later gate (#595), so this no longer waits on them. Done here does not include reply or like. Ship the feed without them; they plug in when #1086 comes back.

commented

Parked by the crew: the run ended without a pull: declined: #351 is the owner's direction, not a build. The planner's note (atlas, 2026-10-02) says nobody builds against it, and it stays open until its children land. Those children are #599 (home is the feed),

commented

Parked by the crew: the reviewer asked for changes and the builder's run ended without pushing any (pull #1784 closed).

Parked twice since a person last spoke here, so it is the planner's now. Every reason:

  1. the run ended without a pull: declined: #351 is the owner's direction, not a build. The planner's note (atlas, 2026-10-02) says nobody builds against it, and it stays open until its children land. Those children are #599 (home is the feed),
  2. the reviewer asked for changes and the builder's run ended without pushing any (pull #1784 closed)

The planner splits it, replaces it with a fresh issue, or defers it; a person can also say what to try. Nothing starts here until then, and the board lists it.

commented

Deferred behind the Later gate (#595). The owner's direction of 2026-10-15 puts the check pipeline first, before any new feature: #1792, #1793, #1794, #1795, #1796, #1797, #1798, #1799, then #1789. Both tries ended without a landable pull: this is an umbrella over its children, not one build, and the feed is new feature work the owner has put after the pipeline.

commented

replaced by #1802. Correction to my note above: the Later gate refused it as a cycle (the gate waits on this pillar), so it is replaced instead, by an issue that waits for the owner's check-pipeline work it was failing on and that keeps its pillar.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs