No feature matches this filter.
AThe spatial core
Identity, the map, presence, trails, assets, geofences, notes, search, export, attachments, offline. The command center the login page promises. It renders and records; its quality machinery and half its privacy walls are missing.
WorksAuth and identity
routes/auth.ts (6) · routes/users.ts (11) · lib/auth.ts, lib/oauth.ts · users, sessions · authStore, LoginPage, ProfilePage
“JWT-based authentication with Google OAuth 2.0.” The frontend exchanges an httpOnly cookie for a 30-day token; a session row backs every token; platform role is “user” or “admin.”
- Flow
- Google with PKCE, or the dev login the archive exposes as “Enter the demo,” creates or links a user, inserts a session and signs a token stored in local storage; every request and the socket handshake verify token, session and user. Rate limits on OAuth, dev login and session exchange.
- Multiplies
- Every route and the socket. The user's last location, written here and by the socket, anchors the map, search bounds, live streamers, products and splats.
- Evidence
- Live archive: demo login lands as Alice and
/auth/me answers · profile save posts to /users/me and the only route is /users/:id, which parses “me” as an invalid id and answers 400 (ProfilePage.tsx:98, users.ts:147-152) · “Delete account” has no handler · “Sign out everywhere” signs out one session · nothing can set the admin role except the database · port defaults disagree across five files · 13 auth and 17 user route tests
- Needs
- A
/users/me route, persistence for the profile toggles, a logout-all route over the function that exists, and one place for port defaults.
WorksMap and presence
routes/map.ts (5) · lib/socket.ts · MapViewGL (1,167 lines) and ten GL layers · mapStore, useGeolocation, useSocket, useEntities
“Your map-based command center for team and asset tracking.” Viewport entity queries up to 5,000, a density heatmap, live streamers, products, nearby. “Persist to DB first, then broadcast.”
- Flow
- MapLibre over OpenFreeMap tiles; every move debounces a bounds query refreshed every thirty seconds and on socket events; layers for team members, agents, assets by type, notes, geofences, own trail, a client-side heatmap, live streamers, products and splats; clustering above fifty entities. Browser geolocation sends a location update when moved ten metres, the server stores it, records history past fifty metres, broadcasts to team rooms and runs geofence checks. Time-travel mode replaces positions with interpolated history. Sharing off hides your marker and stops sending.
- Multiplies
- The socket is the transport for every realtime feature: tasks, notifications, streaming relay, geofences. Presence anchors four other layers.
- Evidence
- Live archive:
/map/entities answers Bob's seeded position to Alice · the socket hook is mounted by both the app shell and the map, and its cleanup disconnects the shared singleton unconditionally, so leaving the map kills realtime for the rest of the session and while both are mounted every handler fires twice (useSocket.ts:211-223, socket.ts:79-84) · the users query in entities, heatmap, nearby and the users list has no team filter, so every authenticated user sees every other user's last position, while assets in the same endpoint are own-only · sharing off never tells the server, and “set my location here” bypasses the toggle · location payloads are unvalidated · the server heatmap has no client caller · three date and owner filters in the sidebar do nothing in the GL engine · no map or socket test
- Needs
- Reference-count the socket and connect it once; scope user visibility to shared teams or state the policy explicitly; a server-side sharing-off; validate location updates; wire or delete the dead filters and the server heatmap.
WorksLocation history and time travel
routes/locationHistory.ts (7) · location_history · TimeSlider, LocationHistoryLayerGL · three orphaned playback services
“User movement tracking.” A trail for the map, and “interpolated positions for multiple users at a target time… to show where everyone was at a specific moment.”
- Flow
- Points enter through the socket; the trail layer draws your own points; the time slider scrubs a window and asks the server to interpolate every team member's position at that instant, dropping anyone whose nearest record is more than thirty minutes away, and filters agents, assets, notes, geofences, products and splats by time.
- Multiplies
- The temporal map. Nothing else reads the table.
- Evidence
- Live archive: Alice's trail holds two points at 50.09° N 14.43° E recorded on 31 August, a visitor's real location in Prague · the time-range and bulk endpoints accept any team id without a membership check, so any user can replay any team's movements (
locationHistory.ts:240-248,286-294) · bulk loads unbounded history per scrub · trajectory, historical playback and playback services, 1,951 lines, have zero importers; saved trajectories and playback sessions tables have no reachable writer · three history queries fire even with the trail off · no test
- Needs
- Membership checks and a windowed query; a decision on the three orphaned services and two dead tables.
PartialAssets
routes/assets.ts (7) · assets, asset_changes · entitiesStore, EntityDetail, EntityPopup
“Physical or virtual assets owned by the user”: locations, people, objects, financial. An audit trail that keeps history after deletion. The login page's third promise, “Asset Tracking.”
- Flow
- Create, update and delete write before-and-after snapshots and dispatch webhook and workflow events; the map reads own assets for the viewport and own-plus-team assets for auto-fit. No screen creates, edits or deletes an asset: the detail panel's buttons have no handler, and the only writers are bulk import and an offline queue nothing fills.
- Multiplies
- Map layers, search, export and import, attachments, evaluation access, AI suggestions, the public API. The audit trail has one reader, which nothing calls.
- Evidence
- Live archive: three seeded assets answer on the visible endpoint ·
EntityDetail.tsx:180-189,256-265 inert buttons · REST changes emit no socket event, so other clients wait for the thirty-second poll · 15 route tests
- Needs
- An asset editor at a map point with edit and delete from the popup, a history panel, and a socket emit on REST changes.
PartialGeofences
routes/geofences.ts (7) · lib/geofence.ts · geofences, geofence_events · GeofenceEditor, GeofenceLayerGL, GeofenceAlertToast
Circle or polygon, monitoring users, agents and assets, with entered, exited and dwell events.
- Flow
- Draw on the map, save to a team; every location update is tested for containment against the team's active fences and a transition records an event, emits to the team room, creates an alert notification and dispatches a workflow and webhook event. A toast opens the event history.
- Multiplies
- Notifications, workflows and webhooks, the map layer, the alert toast.
- Evidence
- Works end to end for users in the GL engine · containment state lives in process memory, so every restart re-fires “entered” for everyone · the agent and asset flags are stored and never evaluated · dwell is declared and never produced · in the default engine a fence cannot be selected, edited, toggled or deleted, the layer has no click handler · no test
- Needs
- Persist containment, run checks for agents and assets or drop the flags, click-to-select wired to the existing mutations, a dwell timer.
WorksNotes, the geo-observation
routes/notes.ts (10) · routes/normalization.ts (3) · lib/spatial.ts, dedupService.ts, normalizationService.ts, geocodingClient.ts, backgroundWorker.ts · notes, places, dedup_groups, normalization_jobs, view_history · NoteEditor, NotesPage, NotePopup
“Geo-tagged observations - 4D coordinates: lat, lng, altitude, time.” The unit of the thesis: the thing you draw on the map of the world.
- Flow
- Right-click or press N, write content, tags and up to five photos; the server resolves timezone offline, defaults altitude, inserts, links duplicates by a location-and-time hash, detects collisions, scores weight, then fires reputation, a webhook event and team memory. A worker geocodes pending notes through Nominatim into a places cache. PostGIS answers nearby queries. The notes page lists, filters and assigns to projects.
- Multiplies
- The most-consumed table in the codebase: collisions, weight, reputation, velocity, confidence, packages, memory, suggestions, search, the Garden.
- Evidence
- Live archive: zero notes, so the map opens empty · the editor never sends a template id, so completeness scoring, contradiction detection and structured agreement never engage outside the Garden · photos are uploaded against note id 0 and never re-linked, so the notes page can never show them · unknown altitude is stored as sea level · no observed-at picker · the geocode worker has no retry cap, so ten un-geocodable notes starve every later note forever · normalization routes are unscoped · the 4D migration file is not journaled, its index never exists · view history is a dead table, normalization jobs are write-only, dedup groups have no reader · no notes route test
- Needs
- Templates in the editor, re-link photos after create, null for unknown altitude and a date control, retry and backoff in the worker, scoped normalization routes.
PartialSearch
routes/search.ts (2) · SearchDialog (Cmd-K), SearchTab · useSearch
“Search across all entities,” with an option to filter to the visible map area, and lightweight autocomplete.
- Flow
- Substring match over own assets, team tasks, projects, conversations, users and visible notes, five each, with optional bounds; the sidebar tab flies the map to a result.
- Multiplies
- Consumes geocoded place names and last positions; feeds the viewport.
- Evidence
- Live archive: “survey” finds the seeded task and project · the global dialog tests and navigates to
/map, a route that does not exist, so “In View” can never be enabled and asset, user and note results point at pages that do not exist (SearchDialog.tsx:25,76 vs App.tsx:130) · suggestions are fetched per keystroke and discarded · unescaped wildcard characters · no test
- Needs
- One route constant, real destinations for spatial results, drop or use suggestions, trigram indexes when volume matters.
WorksExport and import
routes/export.ts (4) · routes/import.ts (4) · ExportMenu, BulkImport
CSV, JSON and GeoJSON exports of assets, tasks, activity and a project report; CSV and GeoJSON asset import with preview and rollback.
- Flow
- Export buttons on the project data tab download with the bearer token; import parses client-side, maps columns, previews server-side, inserts row by row and remembers a batch id for rollback.
- Multiplies
- Imported assets appear on the map, in search and in exports immediately.
- Evidence
- Live archive: task export answers CSV · rollback batches live in process memory · imports skip the audit trail · the assets export ignores the project it is asked for · the notes GeoJSON export has no UI and cannot round-trip because import rejects three-element coordinates · no test
- Needs
- A batch table, audit rows on import, a notes export in the UI and 3-D import.
WorksAttachments and storage
routes/attachments.ts (8) · lib/storageProvider.ts (local or S3) · lib/attachmentCleanup.ts · attachments · photoUpload, FileUpload
Polymorphic files on any entity, local disk or any S3-compatible store, quota by plan.
- Flow
- Images are compressed client-side, posted with progress, checked for entity access, quota, size and type, stored, and served by redirect or stream. Cleanup runs on project and team delete and half-hourly for orphaned splat inputs.
- Multiplies
- Note photos, task and project files, products, splat inputs and outputs, recorded streams. The only place a plan touches the spatial core.
- Evidence
- Live archive: usage answers 0 of 100 MB · thumbnails are never generated, the thumbnail route streams the original inline and SVG is allowed, a stored script surface · because every note photo lives at note id 0 and that id is open to any user, all note photos are listable and downloadable by anyone · conversation message and splat input access checks are open · attachments of deleted notes and assets are never cleaned · no test
- Needs
- Re-link photos and close the id-0 read path, serve SVG as attachment only, real thumbnails or no endpoint, cascade cleanup.
PartialOffline and mobile
offlineStore, offlineDb (Dexie), useOffline, OfflineIndicator · lib/mobileService.ts · mobile_devices, push_notifications, offline_sync_queue
“Stores cached data and pending sync queue,” auto-sync on reconnect, and “mobile app foundations” for device registration and push.
- Flow
- An online flag with toast and panel; dashboards write tasks, projects and teams into IndexedDB; a queue would replay note, task, asset and message actions. No page reads the cache and no component enqueues anything, so the count is always zero. The server's mobile service and three tables have no importer; push delivery is a TODO.
- Multiplies
- Nothing yet.
- Evidence
queueAction callers = 0 · cache readers = 0 · mobileService.ts importers = 0 · service-worker registration is unverifiable, the archive copy lacks the Vite config · six store tests
- Needs
- A decision on the offline contract, then route note creation through the queue and serve nearby notes and entities from cache; implement push or remove the subscribe UI; delete the mobile service unless a native app is planned.
UnusedCustom domain layers
lib/layerService.ts (901 lines) · custom_layers, layer_subscriptions
Eight system domain layers, from commercial real estate to environment, each a set of observation templates; team-made custom layers with subscriptions and stats.
- Flow
- None. No route, no UI, no importer; the map's “layers” are fixed toggles. Because system templates are never seeded, the domain layers would resolve to nothing even if mounted.
- Multiplies
- Nothing reads it.
- Evidence
- importer grep = 0 · the only inserts are inside the service
- Needs
- Mount layer routes and a domain section in the layers tab that filters notes by template set, which depends on templates existing; or delete.
BKnowledge, quality and AI
The layer the thesis rests on: observations get a weight, weights make a reputation, agreement between observers makes them true. Thirteen features; one stub function severs the chain.
UnusedConfidence scoring
lib/confidenceService.ts · confidence_cache, confidence_areas · docs/CONFIDENCE_SCORING.md
“Confidence is HERE's core value proposition. Every piece of data in the system has a transparent, multi-factor confidence score.” The doc describes a per-observation calculator with source, correlation, aggregation and morphism factors and a badge and slider in the UI.
- Flow
- None. The 687-line service has no importer and no route mounts it, so both tables have no reachable writer. The only live “confidence” is a column on activity events that defaults to 0.8 and is never set by any caller, rendered as a constant 80% badge. The map has no confidence filter.
- Multiplies
- Nothing reads it. Even inside the orphan, the “collision rate” factor derives from a verification score that is a constant, so it would be 1.0 for every populated cell.
- Evidence
confidenceService.ts importer grep = 0 · index.ts:264-331 no mount · activityService.ts:30 · doc promises lib/confidence.ts which does not exist
- Needs
- A decision: the doc's per-observation model or the code's per-area aggregate. Then one route, a cache-refresh worker, a real verification input and a map layer with a minimum-confidence filter.
PartialCollisions
routes/collisions.ts (7) · lib/collisionDetector.ts · observation_collisions, collision_observations
“When two observers independently report on the same location and time. This is GRF's structural quality mechanism for verified data.”
- Flow
- Creating a note runs detection over other users' notes within 50 m and 24 h, joins or creates a collision group with centroid, template, domain and an agreement score, and stamps every member note. Seven read endpoints; the Garden's “collision stories” panel is the one UI consumer. Garden notes run the same detection.
- Multiplies
- A badge and a narrative, never a number: the weight calculator's verification factor ignores the collision and returns a constant 10 with a TODO, two lines after detection ran in the same route. Velocity hard-codes collision count to zero. Reputation reads only weight.
- Evidence
notes.ts:578-612 detection · weightCalculator.ts:277-285 constant with “TODO: Update this when collision detection is implemented” · Garden card multiplies a 0–100 score by 100 (GardenCollisionStory.tsx:75-77) · activity type mislabelled conversation_message
- Needs
- Implement verification from the collision id and agreement score, re-weight every note in a group after it forms, fix the Garden ×100. One function lights up weight, reputation, velocity and confidence at once.
WorksWeight and reputation
lib/weightCalculator.ts · lib/reputationService.ts · routes/reputation.ts (4) · reputation_snapshots
“Weight is the currency of credibility. It's earned through consistently high-quality contribution. Never purchased.” Four factors of 25 points; a rolling 20-observation average becomes an A to D grade with “economic consequences.”
- Flow
- A note written through the notes route gets completeness, novelty, verification and recency scored and stored, then a fire-and-forget reputation update writes a snapshot, caches score, grade and trend on the user, and demotes tier to “observer” on a D. Profile, dashboard and team member lists render it. Streaming hours add up to 0.15.
- Multiplies
- Velocity sums weight; the marketplace reads weight tier; listings show a team's average reputation. The tier demotion is written and read by nothing that branches on it.
- Evidence
notes.ts:621,627 · reputationService.ts:136-171 · live archive: /reputation/me answers tier contributor, in grace period · four other note writers skip scoring (publicApi.ts:110, facilitator.ts:355, aiFacilitator.ts:638, workflowEngine.ts:209) and their weight-0 rows count in the rolling window · tests cover the pure functions only
- Needs
- One after-note-written hook that every writer calls, a real verification factor, and a consequence for “observer” tier or drop the claim. Reputation leaderboard hooks exist with nothing rendering them.
BrokenVelocity
lib/velocityCalculator.ts · routes/velocity.ts (8) · velocity_snapshots · VelocityGauge
“Velocity measures the rate of high-quality observations per unit of time. Formula: V = (Noise × Weight) / Time.”
- Flow
- The live endpoint sums note weight over seven days and compares with the previous window. Snapshots feed history, leaderboard and ascension, but the only writer is a manual POST that any user may call for any entity, and no job calls it.
- Multiplies
- Ascension reads cycle snapshots. Nothing else.
- Evidence
- Every client hook unwraps a
.data envelope the API never sends (useVelocity.ts:70-72 and siblings vs api.ts:59), so the profile always says “No velocity data yet” although /velocity/me answers 200 on the archive · velocityCalculator.ts:193-194 collision count hard-coded 0 · no test
- Needs
- Delete the unwrap in seven hooks, add a weekly snapshot job, scope the manual snapshot endpoint.
PartialAscension
lib/ascensionCalculator.ts · routes/ascension.ts (9) · ascension_records · LevelBadge
“Ascension measures sustained improvement in velocity over time. Formula: A = ΔV / ΔCycle.” Ten levels, Observer to Transcendent; the platform's “Win” is the sum of all positive accelerations.
- Flow
- Read path works: status, history, leaderboard, rising stars, levels. The only writer is a POST with a user-supplied cycle number that no UI calls, so every user is Observer level 1 forever.
- Multiplies
- Nothing reads the records outside the module.
- Evidence
ascensionCalculator.ts:291-302 default · useCreateAscensionRecord no consumer · cycle lookup orders newest first and subtracts older from newer, inverting the sign for anyone improving (:192-212, :148-154) · AscensionIndicator.tsx orphaned with a second divergent LevelBadge
- Needs
- Time-derived cycles inside the same worker that writes velocity snapshots; drop the user-supplied cycle; fix the offset direction; keep one LevelBadge.
BrokenEdge taxonomy
lib/edgeTaxonomy.ts (server and client copies) · EdgeDeclaration · users.edge
“The edge system allows players to declare their unique combination of access, expertise, and geography that lets them see things others cannot.”
- Flow
- Profile's edge tab posts domains, geographies, access types and industries to a self-only PUT validated against the server taxonomy.
- Multiplies
- Nothing reads the declared edge for logic. Collisions derive domain from templates, not edges; suggestions, facilitator and marketplace never consult it.
- Evidence
- Hooks unwrap a non-existent
.data (useEdge.ts:26,41): the display always says “No edge declared yet” and a successful save shows “Failed to save edge” · the client taxonomy adds eight Garden domains the server rejects with 400 (edgeTaxonomy.ts:57-105 vs users.ts:296-306)
- Needs
- Remove the unwraps, make the server taxonomy the single source, then give edge a reader such as a weight bonus when a note's domain matches the observer's declared edge.
PartialAI suggestions
routes/suggestions.ts (12) · lib/aiSuggestionService.ts · ai_suggestions, ai_suggestion_feedback, ai_models
Heuristic suggestion generation, feedback collection, anomaly detection, location clustering and model management, “with a placeholder for future ML integration.”
- Flow
- Twelve endpoints generate up to five heuristic rows per team (asset-type mode, similar assets, tasks due within three days, popular tags, 500 m clusters), record feedback, flag anomalous days. No language model is called. The page at /suggestions is a “Coming Soon” placeholder; the built four-tab panel is imported by nothing.
- Multiplies
- Feedback is written and never read; the models table has no insert anywhere so its endpoints always 404.
- Evidence
SuggestionsPage.tsx:18-27 · SuggestionPanel.tsx importer grep = 0 · response shapes and type vocabularies differ between panel and API · no team-membership check on generate or list · live archive: /suggestions?teamId=1 answers an empty list
- Needs
- Decide whether this is a product surface. If so, mount the panel, align shapes, seed models, add membership checks and a daily job. If the facilitator is the real AI, fold the useful heuristics into it and retire these tables.
PartialWorkflows and automation
routes/workflows.ts (11) · lib/workflowEngine.ts · lib/eventDispatcher.ts · workflows, workflow_executions · WorkflowBuilder
“Executes workflow definitions triggered by events, schedules, or manual invocation. Supports action steps, condition branching, and delays.”
- Flow
- Seven route files and the geofence socket dispatch sixteen event kinds; the engine loads every active workflow, matches the event, records an execution and walks action, condition and delay steps. Actions create tasks, notes, notifications, assignments and outbound webhook calls. Seven templates ship. The page at /workflows is “Coming Soon” and the 1,600-line builder is imported by nothing.
- Multiplies
- Consumes the whole app's events; its own notes re-enter nothing, since the create-note action skips weight, collision, reputation and memory.
- Evidence
- Trigger matching ignores tenancy (
workflowEngine.ts:652-669): user A's active template fires on user B's note and renders B's content into A's notification · schedule triggers are stored and never scheduled · delay steps only log · send_email is a placeholder · no test
- Needs
- Scope triggers to the workflow's team before anything else, a scheduler tick, a job table for delays, and route created notes through the note pipeline. Then mount the builder.
Worksarchive: off, no keyAI facilitator for conversations
lib/aiFacilitator.ts · routes/ai.ts (10) · routes/facilitator.ts (9) · extracted_observations, suggested_tasks
“You are a facilitator helping a team capture observations through natural conversation.” Four phases: explore, crystallize, commit, complete. Crystallize extracts template-shaped observations and follow-up tasks as JSON.
- Flow
- With an Anthropic key the conversation page sends each message to Claude Sonnet, stores the reply as an insight message, and saves extractions and suggested tasks for a review panel where approving an extraction inserts a note and accepting a task inserts a task. Without the key the reply is a canned sentence and the status endpoint says so.
- Multiplies
- Approved extractions become notes and tasks, which feed memory, activity and projects. But those notes bypass weight, collision, reputation, memory and dispatch, and default to latitude 0, longitude 0 when the model gives no coordinates.
- Evidence
- Live archive:
/ai/status answers “AI facilitation requires ANTHROPIC_API_KEY” · team lookup compares a team id to a project id (aiFacilitator.ts:185-194) · two API surfaces write the same tables, one with access checks on eight of ten routes missing (ai.ts) · extraction needs a conversation template no UI sets · no test
- Needs
- Keep the checked surface, persist the AI reply there, fix the team lookup, require coordinates or a place before approval, and route approvals through the same pipeline as a hand-written note.
Worksarchive: off, no keyMemory digests
lib/memoryDigestService.ts · lib/memoryDigestWorker.ts · mutual_memory_logs (source ai_digest)
“AI-powered weekly digest of team mutual memory. Synthesizes recent learnings, decisions, and observations into a concise summary.”
- Flow
- A worker runs every six hours and once after boot; for each team without a digest in the last seven days it sends the last hundred memory rows and the charter to Claude and stores the answer as a high-importance insight tagged weekly-digest. Owners and admins can trigger it by hand. The team memory tab lists it.
- Multiplies
- Feeds the memory list and the onboarding payload, whose client hook is imported by nothing.
- Evidence
index.ts:418 start · memoryDigestService.ts:114-118 silent no-op without key while the worker still iterates every team · tests cover prompt building and parsing
- Needs
- Render the latest digest for new members, skip the loop when no key is set, and notify the team when a digest lands.
WorksMutual memory and charter
lib/mutualMemoryService.ts · routes/teams.ts memory and charter endpoints (8) · mutual_memory_logs, teams.charter
“Auto-populates team mutual memory logs from observations, evaluations, and task completions.” The charter holds mission, values, norms and goals; “Context of a team is the management of mutual memory.”
- Flow
- Members add memories by hand; evaluations, completed tasks and charter edits write rows automatically; the digest worker adds a weekly synthesis. The team detail page has a memory tab with filters and a charter tab for owners and admins.
- Multiplies
- The digest reads it. The observation edge is dormant: it fires only for templated notes, and only the Garden sets a template, whose route does not call it.
- Evidence
evaluations.ts:211, tasks.ts:692, teams.ts:890 writers · mutualMemoryService.ts:126 template guard · builder tests exist, no route test for memory or charter
- Needs
- Let untemplated notes create low-importance memories, or give the note editor real templates; render the onboarding payload.
UnusedCustom fields and entity types
lib/customFieldsService.ts (909 lines, 17 exports) · custom_field_definitions, custom_field_values, entity_type_definitions
“Manages custom field definitions, entity types, value storage, and validation for team-specific fields.” Fourteen field types, per-team slugs, validation rules, conditional visibility.
- Flow
- None. No route, no UI, no importer anywhere on either side.
- Multiplies
- Nothing reads it.
- Evidence
- importer grep = 0 ·
index.ts:264-331 mounts no route · the only inserts are inside the service
- Needs
- A route file and a field renderer inside the asset, task and note editors, or delete the service and three tables.
PartialObservation templates
lib/templateService.ts · scripts/seedTemplates.ts · observation_templates · NoteTemplateManager
Structured, typed fields per template with an “aiPrompt” per field “for AI to extract this field.” System templates such as “Storefront Observation” for commercial real estate.
- Flow
- The table is read by eight modules: completeness scoring, collision agreement and domain, AI extraction, observation memory, buyer exports, packages, playback and layers. The only running writer is the Garden bootstrap at boot. The service and the seed script are orphaned, diverging copies, and the note editor's “templates” are a browser-local quick-fill that never sends a template id.
- Multiplies
- This is the pivot of the whole knowledge layer, and every edge that keys on it is live only for Garden notes.
- Evidence
templateService.ts callers = 0 · index.ts:421 Garden template only · NoteEditor.tsx:35-46 local fill · live archive: /garden/template answers the seeded Garden Profile
- Needs
- A templates route over the service, seed system templates at boot beside the Garden one, delete the stray script, and let the note editor pick a server template and send id plus data. This single change activates completeness, agreement, extraction and memory for ordinary notes.
CThe workspace loop
Teams, projects, conversations, tasks, sessions, evaluations, credits. The February roadmap's “full collaborative workspace.” Most of it works; the credit budget that was meant to make it an economy is columns without writers.
WorksPermission model
lib/access.ts · team_members.role owner, admin, member · users.role user, admin
Every project, task, conversation, session and evaluation permission walks the entity to a team and reads the caller's team role. Notes and assets are user-owned.
- Flow
- Four helpers resolve team, project, task and polymorphic entity access. The teams route inlines the same query instead of using them.
- Multiplies
- Root of every check in the loop.
- Evidence
access.test.ts covers all four helpers · the owner-sentinel returns team id 0 for notes and assets, which later breaks a memory insert on asset evaluations
- Needs
- Nothing structural. A per-project role does not exist and may be wanted later.
WorksTeams and invites
routes/teams.ts (22) · routes/invites.ts (3) · teams, team_members, team_invites
“Teams (Mutual Memory Layer).” “Teams let you collaborate with others on projects and tasks.”
- Flow
- Create, list, detail with members, projects, memory, charter and settings tabs; add, re-role and remove members with last-owner protection; invite by token with a seven-day expiry, copy link or WhatsApp share, public accept page, and an in-app notification carrying the token for existing users. Membership puts a user into the team's socket room, which is what delivers every live event.
- Multiplies
- Root of permissions, socket fan-out, mutual memory, and the webhook and workflow events for member joined and left.
- Evidence
- Live archive lists Alpha Team and Data Collectors · the runbook's “undefined existingMember at line 581” is refuted for this tree: line 581 dispatches with a variable declared at 544 · plan member cap is applied on direct add but bypassed by both invite acceptance paths (
invites.ts:130-137, teams.ts:1351-1358) · invite e-mail is a TODO, the link is only logged (teams.ts:1231-1234) · onboarding endpoint has no consumer · 727-line route test with mocked database
- Needs
- Apply the cap in both accept paths, an e-mail provider behind the TODO, and a “start here” panel that renders the onboarding payload.
PartialProjects and budgets
routes/projects.ts (8) · projects.creditsAllocated, creditsSpent · ProjectDetailPage (1,884 lines, 7 tabs)
Status lifecycle draft, planning, active, paused, completed, archived. “Projects help you organize work within a team.” A project carries a credit budget.
- Flow
- Dashboard tab with stats, stacked status bar, burndown, contributors and activity; overview, conversations, tasks, budget, data with uploads, notes, export and import, and settings. Creation is capped per plan per team.
- Multiplies
- Every permission in the loop walks through the project's team. Credit fields feed the return ceiling, export and velocity.
- Evidence
- Live archive shows 250 of 1,000 and 800 of 2,000 spent, from seed data ·
projects.creditsSpent has no writer anywhere · creditsAllocated is written only by an API-only PATCH and the return approval; the settings tab has no field although the budget tab tells you to use it (ProjectDetailPage.tsx:780) · project activity is team-wide, not project-filtered · tests cover CRUD, not stats
- Needs
- Pick the budget model: make allocation write the project and task completion write spend, or drop the two columns and the tab. Add the settings field or fix the copy.
WorksConversations
routes/conversations.ts (7) · conversations, conversation_messages · ConversationPage (762 lines) · typing sockets
“Conversations (Dialog).” Message types message, observation, question, insight, decision. Phases explore, crystallize, commit, complete are the facilitator's.
- Flow
- Created inside a project; the page joins a socket room, relays typing with a three-second auto-stop, sends optimistically, dedupes incoming, edits extracted insights, and defaults to facilitated mode with the extraction review panel. Every post notifies every other team member with mention detection.
- Multiplies
- Suggested tasks link back by conversation id; evaluations may target a conversation; a phase reaching complete triggers an evaluation prompt.
- Evidence
- Seeded “Feature Prioritization” and “Survey Progress Update” answer on the archive · notification fan-out is awaited per member before the response returns (
conversations.ts:425-442) · AI turns posted through the /ai route skip the socket emit · 685-line route test
- Needs
- Fire-and-forget notifications, or notify mentioned users only; route AI inserts through the room emit.
WorksTasks
routes/tasks.ts (8) · tasks · TaskDetailPage, TaskKanban, TaskCalendar
Assignee is a user or an agent; each task carries a credit cost, a due date and an optional source conversation.
- Flow
- Calendar, kanban with optimistic drag and rollback, and list views; detail page with status menu, assignee select, attachments with plan quota, evaluation history and work sessions. Completion writes an activity event, a team memory row, a webhook and workflow event, a notification and a socket update: the densest fan-out in the codebase.
- Multiplies
- Project stats, burndown and contributors; work sessions; evaluations; integration imports from GitHub, Jira and Linear.
- Evidence
- Live archive lists five seeded tasks ·
creditsCost is stored and shown and never charged · dashboard “Add Task” links to /tasks/new, which is not a route, so it renders “Task not found” · reschedule hook never imported · agent assignment is API-only, the selector is disabled · 699-line route test
- Needs
- Charge the cost on completion or remove the field; fix the dead link; wire calendar drag to reschedule.
PartialWork sessions
routes/workSessions.ts (5) · work_sessions · workSessionsStore · useEvaluationPrompt
Timed sessions on a task with notes and artifacts, whose completion asks for an evaluation.
- Flow
- Start flips the task to in progress and refuses a second active session; complete or abandon stamps the end and computes minutes in SQL; completing opens the evaluation prompt. Pause is a status change that never ends the row and resume starts a new one, so every pause leaves an orphan with no duration. The in-session quick notes are local state never sent.
- Multiplies
- Nothing outside its own route reads the table. Hours are not in project stats, velocity, export or reputation.
- Evidence
workSessionsStore.ts:109-118 · TaskDetailPage.tsx:369-378 · seeded active session answers on the archive · 624-line route test; pause and resume untested
- Needs
- A real resume on the same row with duration across pauses, send the notes, and surface hours in project stats and velocity.
PartialEvaluations
routes/evaluations.ts (6) · evaluation_logs · EvaluationPrompt, EvaluationsPage, EvaluationDetailPage
“Evaluation Logs (Long-term Memory).” Outcome, score, insights, hypotheses validated, and “Data produced (feeds back to HERE).”
- Flow
- Three entry points: session completion, a conversation reaching complete, and a manual form that asks for a raw entity id. List, detail and delete work. The one consumer is team memory, which turns each evaluation into an insight row.
- Multiplies
- Memory and the digest. Reputation does not read evaluations; no reward is triggered; data contributions are stored and never read.
- Evidence
- Live archive returns one seeded evaluation, outcome success, score 10 ·
GET /evaluations/search is registered after /:id and always answers 400 · the prompt's slider is 1 to 10 while API and pages treat score as 0 to 100 · asset evaluations pass team id 0 into the memory insert and the FK error is swallowed · “Edit” only closes the menu · 631-line route test
- Needs
- Register search before the id route, one score scale, and make evaluations feed something economic or reputational as the schema promises.
PartialCredits
routes/credits.ts (13) · credit_balances, credit_transactions, credit_return_requests · CreditsPage (887 lines)
A balance per user with a ledger of grants, purchases, transfers, project allocations, rewards and returns. “Credits are spent when tasks are completed.”
- Flow
- Balance and ledger; admin grant and reward; transfer by numeric user id; allocate to a project by numeric id; return requests reviewed by owners and admins; packs bought through Stripe checkout and fulfilled by webhook. Real debits exist only in splats and the marketplace.
- Multiplies
- Splats and marketplace are the sinks; projects read the budget columns; trade stats aggregate flows.
- Evidence
- Live archive: balance 500 from a seed grant, no signup grant exists · allocation debits the user and never writes
projects.creditsAllocated (credits.ts:281-340), so the returnable amount computes to zero and allocated credits are stranded · two read endpoints have no membership check · transfer and approve are non-transactional · 653-line route test, no return-request test
- Needs
- Allocation and ledger in one transaction that writes the project, membership checks on the two reads, and a defined spend so spent and reward mean something.
PartialActivity feed
routes/activity.ts (1) · lib/activityService.ts · activity_events · ActivityFeed, ActivityPage
The schema lists seven core and fifteen build-in-public event types with typed metadata and a confidence column.
- Flow
- Insert, then a socket event to the team room; the feed refetches every minute and prepends live events with an unread counter. Seven types are actually produced: team, project and task created, task completed, stream started and ended, and a note type reusing the conversation-message label.
- Multiplies
- Suggestion heuristics count events; export and the public API expose them; project dashboards show a timeline.
- Evidence
- The feed's filter groups and icon map name twenty types that are never emitted, so the geofence, asset, note and people filters are always empty and the real types render as a generic “Event” (
useActivityFeed.ts:32-39, ActivityFeed.tsx:28-180) · no test
- Needs
- Emit what the UI already draws, or trim the vocabulary to the seven real types.
WorksNotifications and Command Center
routes/notifications.ts (9) · notifications, notification_preferences, push_subscriptions · NotificationCenter, CommandCenterPage
In-app notifications with per-type preferences, push subscriptions, and a Command Center of notifications, messages, activity and preferences.
- Flow
- Task assigned and status, conversation messages with mentions, team invites with the token, team stream started, credit returns: each inserts a row, checks preferences, and emits to the user; the header bell refetches and the count polls every minute. Clicks route to the entity; invites accept inline.
- Multiplies
- The only user-facing signal for assignment, invites, returns and DMs.
- Evidence
- Browser push is a TODO although subscriptions are stored; e-mail is a stored boolean nobody reads · DM and workflow notifications insert directly, bypassing preferences and the socket · credit and DM types have no click route · no route test
- Needs
- Route every producer through the one create function, implement push with VAPID or remove the subscribe UI, add the missing click routes.
PartialMessages and direct messages
routes/messages.ts (5, legacy) · routes/dms.ts (7) · messages · dm_conversations, dm_participants, direct_messages · MessagesPage, MessageButton
Two systems: a Command Center message list from February, and person-to-person threads with read receipts and typing.
- Flow
- Legacy messages can only be posted by a user to themself; nothing else writes them, and the socket helper for them has no callers. DMs find or create a pair thread, page messages, mark read, and count unread; the message button on team members, assignees, leaderboard rows and search opens a thread.
- Multiplies
- DMs dispatch a webhook and workflow event and insert a notification.
- Evidence
- The server emits
dm:message, dm:read and dm:typing and the client registers no listener for any of them, so a recipient sees new messages only after reload · the page's user search calls /users/search, which does not exist, so it always says “No users found” · no route test for either
- Needs
- Subscribe to the three events and call the store handlers that already exist, add a user search route, retire the legacy table and tab.
UnusedAgents
routes/agents.ts (5) · agents · AgentsPage, AgentDetailPage, AgentSelector
An agent has an owner, status, device location, capabilities and a personality. The login page's second promise, “Agent Management.”
- Flow
- Owner-scoped CRUD with a 646-line test. Tasks, sessions and conversation messages accept an agent id with owner checks. The pages say “Coming Soon,” the selector is a disabled select, the store is imported by nothing, and no code reads capabilities or personality or executes anything.
- Multiplies
- Nothing. Execution would be an external client posting as the owner.
- Evidence
AgentsPage.tsx:18-27 · AgentSelector.tsx:19-24 · live archive: two seeded agents exist and /agents answers an empty list for the demo user because they belong to another seed user
- Needs
- Either an agent UI plus an execution surface such as an agent token that can post sessions and messages, or hide the nav entries.
WorksDashboard
DashboardPage.tsx · seven GET endpoints
Teams, projects, pending tasks, credit balance, stream hours, reputation, quick actions and recent activity.
- Flow
- Seven round-trips on load, cached for offline.
- Multiplies
- Reads only.
- Evidence
- Renders on the archive as “Good morning, Alice” with 2, 3, 0 and 500 · “Add Task” targets a route that does not exist · activity icons name types nothing emits
- Needs
- Fix the link; consider one summary endpoint.
UnusedCollaboration sessions and presence
lib/collaborationService.ts (560 lines) · collaboration_sessions, participants, changes · socket presence handlers
“Issue #84 - Real-time Collaboration, CRDT operations.” Sessions, cursors, versioned changes, undo, viewer presence and editing state.
- Flow
- None. The service is imported by nothing, so the tables are never written; the server's presence handlers and the client's presence emitters and event types exist with no callers or subscribers on either side.
- Multiplies
- Nothing.
- Evidence
- importer grep = 0 ·
socket.ts:289-360 handlers without callers · no test
- Needs
- Mount presence in the task and conversation pages, one effect away, and expose session routes; or delete the service, tables and handlers.
DMoney, marketplace and platform
Real money enters through Stripe and becomes credits; nothing converts credits back out. The data marketplace is dark by a flag. The developer surface is the app's outbound nervous system, and it leaks across tenants.
Partialarchive: off, no Stripe keyBilling and subscriptions
routes/billing.ts (7) · lib/stripe.ts · lib/subscriptionConfig.ts · middleware/subscription.ts · subscriptions, subscription_events
“Subscription Configuration — single source of truth for all plan parameters.” Free, Pro at 24 dollars, Business at 49; seven-day trial and grace; credit packs at 10, 40 and 70 dollars.
- Flow
- Pricing page creates a Stripe checkout session; the webhook upserts the subscription and cancels a previous one on upgrade; invoice paid and failed move status; the auth store loads the subscription on login and a feature-gate hook mirrors the limits; the middleware resolves the plan per request and gates streaming destinations, simulcast, scheduling, projects, team size, storage, scene collections and splats.
- Multiplies
- Seven feature areas read the limits; purchased credits are spent by listings, products and splats.
- Evidence
- Live archive:
/billing/plans and /billing/subscription answer the free plan's limits; checkout would throw without a key · the idempotency row is inserted before handlers run, so a handler failure returns 500 and Stripe's retry hits the duplicate branch: the event is lost (billing.ts:341-358,395-398) · invoice handlers read a field the pinned 2026 API version may not carry · Pro copy says six destinations, config says four · requirePlan() is exported and never used · no test
- Needs
- Record the event after processing, read the subscription id with a fallback, a signed-fixture webhook test, and decide which flags beyond numeric limits the server should enforce.
Partialarchive: 503 coming soonData marketplace listings
routes/marketplace.ts (16) · lib/marketplaceService.ts · marketplace_listings, purchases, listing_reviews, saved_listings · MarketplacePage (948 lines)
“Package your team's observations and earn credits when others purchase.” “Revenue Distributions (50/30/20 split tracking).”
- Flow
- Behind a server flag and a client flag: build a package, create a listing that needs ten observations at average weight fifty, publish, buy with credits, download the observations as JSON or CSV, review after access. The listing detail shows the team's average reputation.
- Multiplies
- A purchase triggers the revenue split; the buyer API re-exposes listings. Saved listings are written only by a service nothing imports.
- Evidence
- Live archive: every listing route answers 503 “Data marketplace is coming soon” · purchase performs five writes with no transaction · the purchase row never sets its package id · three status vocabularies on one column · route tests never set the flag, so they would receive the 503 · 1,000-line service test with a mocked database
- Needs
- A transaction, one status enum, the flag in test setup, and the product decision the flag defers: the surface was rebuilt around products instead.
Partialarchive: 503 coming soonData packages
routes/packages.ts (9) · lib/packageService.ts · data_packages, package_observations · PackageBuilder
“Packaged observations for sale.” Criteria of domain, tags, geography, time range, templates, minimum weight and collisions.
- Flow
- Create stores criteria and refreshes the junction table from the team's notes at or above minimum weight, then computes count, average weight, a collision proxy and contributor count, with a preview of samples, weight buckets and per-day counts.
- Multiplies
- Listings, downloads, buyer exports and the contributor split all read the junction table.
- Evidence
- A team with no member rows and no other filters yields an undefined where clause and the package ingests every note in the database (
packageService.ts:246-258,291-293) · rolling refresh has no caller · polygon geography is a bounding box, region is a no-op · collisions filter stored and ignored · no test
- Needs
- Guard the empty team, a scheduled rolling refresh, real PostGIS containment, and honour the collisions filter against the real table.
PartialProducts and escrow
routes/products.ts (14) · products, escrow_transactions · ProductCard, CreateProductPage, ProductDetailPage
“Items built in public for sale — apps, tools, UI kits, etc.” Escrow “holds funds between purchase and delivery confirmation”; linked stream sessions are “building in public proof.”
- Flow
- Upload a file and thumbnail, publish, buy with credits into a seven-day escrow, download while held or released, confirm receipt to pay the seller, dispute within the hold, admin resolve. Exclusive sales become sold; project transfer moves a project to the buyer's team.
- Multiplies
- Attachments, projects, the streaming badge, the credit ledger and a map layer. The revenue split and quality pool apply to data listings only.
- Evidence
- Live archive:
/products answers an empty list · release time is set and read only to reject late disputes, and nothing ever releases: a buyer who never confirms leaves the seller unpaid forever while keeping download access (products.ts:664-665,829-831) · purchase is non-transactional · linked stream ids are never validated · no test
- Needs
- A scheduled release of held escrows past their date, a transaction around purchase, and a decision on whether products join the revenue split.
PartialRevenue and payouts
routes/revenue.ts (7) · lib/revenueService.ts · lib/tradeService.ts · revenue_distributions, team_payouts, member_payouts, quality_pools · EarningsDashboard
“50% to producing team / 30% to platform / 20% goes to quality pool.” The pool pays the top twenty contributors by weight each month.
- Flow
- A listing sale writes a distribution, pays each contributor by their share of package weight, and adds to the monthly pool; an admin endpoint distributes the pool. The earnings tab shows balance and thirty and ninety day breakdowns.
- Multiplies
- Credit balances everywhere. Distributions and team payouts are written and read by no route.
- Evidence
- Live archive:
/revenue/earnings answers zeros with the 500 seed credits as “lifetime earned,” which conflates bought and earned · the platform's 30% is a number on a row, no account is credited · no cash-out exists anywhere: Stripe appears in one file and has no Connect, transfer or payout · tradeService is imported by nothing and joins teams to users by id · no service test
- Needs
- A platform ledger account or an explicit burn, scheduled pool and escrow jobs, and a decision on cash-out or a stated non-redeemable policy. Delete or wire the trade service.
Brokenarchive: 503 coming soonBuyer API
routes/buyerApi.ts (19) · lib/buyerApiService.ts · middleware/apiKeyAuth.ts · api_keys, api_usage_logs, webhooks
“Buyer API (institutional access).” Keys prefixed grf_live with scopes for marketplace read and purchase, data download and query, account and webhooks.
- Flow
- A bearer key with hourly usage limits can search and preview listings, buy with credits, download or query purchased data with bounding box, time and weight filters, and register webhooks.
- Multiplies
- A second door onto listings. Its webhook trigger is called by nothing, so buyer webhooks never fire.
- Evidence
- The router mounts at
/data/v1 while every self-link it returns points at /api/v1, which belongs to the developer API with a different key format: every link 404s or 401s (buyerApi.ts:205,361,497 vs :588) · download and query never check the purchase belongs to the key's user, so any download-scoped key pulls any purchase · no test
- Needs
- One mount prefix, ownership on export and query, call the trigger from purchase and renewal, and merge or namespace the two key systems.
PartialDeveloper portal and public API
routes/developer.ts (15) · routes/publicApi.ts (12, /api/v1) · lib/apiKeyService.ts · lib/eventDispatcher.ts · three key middlewares
“External-facing API endpoints authenticated via X-API-Key header. Mirrors key internal routes.” Webhooks are “HTTP POST with HMAC signatures.” The OpenAPI description: “HERE is a living world model that gets richer with every cycle of play.”
- Flow
- Portal tabs for keys, usage, webhooks, docs and examples; the public API exposes notes, assets, teams and activity; every mutating route in the app dispatches events that deliver signed webhooks and trigger workflows.
- Multiplies
- The outbound nervous system: notes, assets, teams, tasks, DMs, geofences and the public API all feed it.
- Evidence
- Live archive:
/developer/docs answers the endpoint catalogue · delivery selects every active webhook subscribed to an event with no owner or team filter and posts the full payload, so any developer subscribed to note created receives every user's notes (apiKeyService.ts:536-544) · /api/v1/notes/nearby is shadowed by the id route · docs advertise a playback endpoint that does not exist · the “public docs” exception compares a full path to a short one and never matches · per-key rate limits are ignored for a hard-coded 1,000 an hour · single delivery attempt, no retry · one of the three key middlewares is imported by nothing · no test
- Needs
- Filter deliveries by the event's owner, fix route order, scope reads to the key owner, honour per-key limits, retries, and generate docs from the router.
BrokenIntegrations
routes/integrations.ts (17) · routes/integrationAuth.ts (2) · lib/integrationsService.ts · lib/providers/* (9) · four tables · IntegrationsHub (1,274 lines)
“Manages third-party service integrations including OAuth connections, sync operations, webhook management, and provider metadata.” Slack, GitHub, Jira, Linear, Google Calendar, Google Drive, webhook, Zapier and Dialog providers.
- Flow
- As designed: the hub navigates to an OAuth start route carrying the session token, the server redirects to the provider, the callback exchanges the code and stores credentials, and a sync writes tasks and entity mappings from GitHub, Jira or Linear.
- Multiplies
- Mappings link external issues to tasks, notes and projects; syncs write tasks; Slack can send notifications.
- Evidence
- Live archive:
/integrations/providers lists the nine providers · the authenticated router is mounted first on the same prefix and applies the session middleware to every path, so both OAuth routes answer 401 before their handlers run (index.ts:300-302, integrations.ts:71); the authors solved this for streaming with a separate prefix · incoming provider webhooks sit behind the same middleware and skip signature verification · a bare require('crypto') in an ES module throws the first time a secret-bearing webhook fires · the frontend offers Linear OAuth and the server has no Linear case · credentials are stored as plain JSON under a schema comment that says encrypted · the runbook's missing jsonwebtoken claim is false for this tree: the file imports jose, which is a dependency · no test
- Needs
- Mount the OAuth router under its own prefix before the authenticated one, exempt incoming webhooks and verify HMAC on the raw body, fix the require, add Linear, encrypt credentials, move OAuth state to Redis.
PartialSecurity, audit and observability
lib/securityService.ts · lib/auditService.ts · audit_logs, security_events, totp_secrets, ip_allowlists, data_retention_policies · lib/metrics.ts, alerting.ts, sentry.ts · routes/health.ts (3)
“Handles two-factor authentication (TOTP), session management, IP allowlisting, and data retention policies.” “Comprehensive audit logging for all CRUD operations… Audit logs are immutable.”
- Flow
- What runs: request ids, metrics, security headers and CSP, CORS, a global 100-a-minute IP limiter, error capture to Sentry, health with a database probe and a deduplicated critical alert, detailed metrics behind a session. What is table-only: the whole security and audit layer.
- Multiplies
- Alerts and metrics are consumed by the worker, sockets and health.
- Evidence
- Live archive:
/health ok, /health/detailed answers uptime and memory · security and audit services are imported by nothing: no 2FA route, no session revocation, no IP enforcement, no retention job, no audit trail · the limiter keys on a forwarded-for header or the string “unknown,” so direct traffic shares one bucket · TOTP secrets would be stored unencrypted · health, metrics and alerting have tests
- Needs
- Delete the dead layer or wire it: 2FA into login, audit calls in auth, permission, export and key routes, an allowlist check in the middleware, a retention cron, an admin audit view.
EMedia, 3D, The Garden, the CLI and operations
The build-in-public wing, the one feature that shipped clean, and the shell everything runs in. Fourteen tables exist in no migration.
Partialarchive: off, no CloudflareLive streaming, “Build in Public”
routes/streaming.ts (29) · lib/mediaRelay.ts, cloudflareStream.ts, platformOAuth.ts, streamCrypto.ts, vodUpload.ts · five tables · BroadcastSettings (1,782 lines), compositor, scene editor, leaderboard
“Go live to multiple platforms simultaneously.” “Browser sends WebM chunks via Socket.io… we pipe them into ffmpeg's stdin, which transcodes to H.264 and pushes out via RTMP directly to destination platforms.” Leaderboard: “Top builders ranked by hours building in public.”
- Flow
- Destinations by manual key or Twitch and YouTube OAuth, keys encrypted at rest; go live creates a Cloudflare input and simulcast targets and a session row, emits activity, notification and a workflow event; the browser panel records camera or a composited scene and streams chunks to an ffmpeg tee per destination with a local MP4; stop uploads the VOD with quota; clips, scheduling, history, stats, and a public watch link. Live streamers appear on the map with a time slider replay. Encoder mode hands OBS the Cloudflare ingest.
- Multiplies
- Reputation adds up to 0.15 for streaming hours; the dashboard shows stream hours; a VOD can become a splat input; products link sessions as proof; workflows and notifications fire on start and stop.
- Evidence
- Live archive: destinations CRUD answers, go-live would 503 · going live requires Cloudflare even on the direct relay that only needs ffmpeg (
streaming.ts:258 vs socket.ts:386-436) · public VOD links are returned in three inconsistent forms and none resolves (index.ts:315, streaming.ts:1097, BroadcastSettings.tsx:403,1715) · the scenes API has no client caller, scenes live in local storage · the WHIP path is unreachable because the relay flag is hard-coded · without the key secret, stream keys and OAuth tokens are stored in clear · four streaming tables are in no migration · no test
- Needs
- Migrations, a Cloudflare gate conditional on encoder mode, one canonical watch URL, either wire scenes to the API or delete it, and a stated requirement for the key secret.
Partialarchive: off, free plan and no GPU3D Gaussian splats
routes/splats.ts (7) · routes/worker.ts (5) · middleware/workerAuth.ts · splat_jobs · SplatsPage (815 lines), SplatViewer · splat-pipeline/hq-splat-worker/worker.py
“3D Gaussian Splat generation from video.” A GPU VM “polls HERE API for splat jobs and processes them via nerfstudio.” Queued, preprocessing, extracting frames, COLMAP, training, exporting, completed.
- Flow
- Upload a video up to 500 MB or pick a recorded stream, pay 75 or 200 credits into escrow, insert a queued job; the worker claims one with a locked select, downloads, extracts frames, runs COLMAP and splatfacto, exports a PLY and uploads it; progress reaches the page over a socket; the viewer renders with Spark or Reall3D and the map shows cyan markers filtered by time. Boot resets stuck jobs; failures refund.
- Multiplies
- Credits, attachments and storage quota, the map, streaming VODs, and a deploy safety check for active jobs.
- Evidence
- The two sides of the polling contract match line for line · live archive: the page shows “requires the Pro plan” and
/splats answers an empty list · no GPU worker exists for the archive, and a queued job waits forever with no “worker last seen” signal and no timeout refund · the in-process placeholder worker is dead code · the table is in no migration · no test
- Needs
- A worker heartbeat surfaced in health and on the page, a job-age timeout that refunds, a contract test driving the worker's mock mode, and the migration.
WorksThe Garden
routes/garden.ts (13) · routes/gardenPublic.ts (2) · lib/gardenService.ts (980 lines) · app/src/garden/** · no new tables
“Finding, indexing, and mapping wonderful people doing wonderful things. A Garden Profile is a note with templateId pointing to the seeded ‘Garden Profile’ observation template. No new DB tables.” “Alfia's command center.”
- Flow
- Quick add with browser location creates a templated note in discovered state; the workspace lists, searches and filters by domain; a profile page interviews by creating a conversation in an auto-provisioned “Garden Interviews” project, tracks publications, flips status to interviewed then published, and manages production tasks that are real task rows; hubs cluster profiles into emerging cities; collision stories narrate agreement; a public page lists published profiles for anyone.
- Multiplies
- Everything a note gets for free: weight, collisions, geocoded place names, gold map markers, conversations, tasks, projects, teams and reputation. The one feature that inherited the whole substrate.
- Evidence
- Live archive: template seeded, zero profiles, public list answers · collision story cards link to a collision id where a note id is expected, opening the wrong profile · hub links pass coordinates the map page ignores · the collision panel is empty until the map has set the template id · no ownership check on status, publication or task mutations · the complete-interview endpoint has no UI · the repo contains no retro on it · no test
- Needs
- Fix the two link defects, resolve the template id inside the module, add owner checks on mutations, wire complete-interview to the conversation.
BrokenHERE CLI and the build-in-public epic
packages/here-cli (1,206 lines) · BUILD_IN_PUBLIC_EPIC_SUMMARY.md and four sibling docs · migration 0002
“Broadcast your development activity in real-time. Build in public, get discovered, create value.” The epic claimed eight issues complete, an estimated value of 80 to 120 thousand dollars, and “READY TO SHIP.”
- Flow
- Git hooks post every commit and watched file change to an activity endpoint with a confidence score, queue on failure and retry five times.
- Multiplies
- Would feed the activity feed, public API and export.
- Evidence
- The CLI posts to
POST /activity; the activity route defines only GET, so every event 404s and is discarded after five retries · the epic's morphism marketplace, aggregation tiles, broadcast config, vision capture and confidence module are absent from the tree; survivors are seven dead tables in migration 0002, a confidence column defaulting to 0.8, comments, and five documents still describing it as shipped
- Needs
- Add the POST or retire the package; update or delete the five documents; a forward migration dropping the dead tables.
UnusedRust component
rust/ (46 lines)
“Performance-critical components for HERE.” The README's “Rust + Python on GPU VM (Gaussian splatting).”
- Flow
- Prints “HERE Core initialized.” Nothing imports, spawns or builds it; the splat worker is Python.
- Multiplies
- Nothing.
- Evidence
rust/src/lib.rs:5-8 · only referenced by a disabled release workflow and dependabot
- Needs
- Delete it and the README lines, or give it a job.
PartialOperations shell
app/server/src/index.ts · lib/backgroundWorker.ts · db/migrate.ts · drizzle/ · docker-compose.yml · scripts/deploy-gcp.sh · .github/workflows (all disabled)
One Node process: Hono API, Socket.io, in-process workers for normalization, digests, session and job recovery, graceful shutdown, migrations on boot. Deploy validates, builds images, pushes, restarts and health-checks.
- Flow
- Boot validates env, applies middleware in order, mounts 46 routers, bridges Node's server to the app, runs migrations, listens, then starts workers and recovery. Deploy refuses a dirty tree, lints, typechecks and builds, then pulls and restarts on the VM.
- Multiplies
- Everything.
- Evidence
- Fourteen schema tables exist in no migration, including subscriptions, so on a migration-provisioned database the subscription middleware 500s every streaming, scenes and splats request; only a manual push creates them, which the archive runbook had to discover · a stray migration file is on disk but not journaled · the Stripe customer column is in no migration · deploy runs no tests and no migration step · all CI workflows are disabled and the pre-push hook runs no tests · every request body is buffered whole in memory, including 500 MB uploads · the operations doc describes Fly.io while deploy targets GCP
- Needs
- Regenerate migrations from the schema and journal or delete the stray file, run tests in deploy and pre-push, stream bodies with the server adapter already in dependencies, rewrite the operations doc.
PartialTests
27 server files · 20 client files · vitest
Route tests over mocked database chains and mocked auth; service tests over pure functions; store tests over mocked fetch.
- Flow
- No test touches Postgres, a socket, or a side effect. The “integration” tests mount real routers over mocked drizzle chains.
- Multiplies
- Confidence in the loop's contracts: teams, projects, tasks, sessions, evaluations, credits, conversations, agents, assets, users, auth, access, marketplace routes and service.
- Evidence
- Zero tests for streaming, scenes, splats, worker auth, Garden, CLI, billing, integrations, developer and public API, notifications, activity, DMs, collisions, workflows, subscription gating, the boot sequence or migrations · marketplace route tests never set the flag that would gate them
- Needs
- A database-backed test lane, and coverage where the money and the media are.