Destination
A spec for a Resources component in the Context Graph family, ready to hand to /to-prd: what counts as a Resource, how harness activity reveals that one was touched, its graph model (GitHub first), cache/freshness semantics, and how it connects to recall and the Chunk/Entity layer — so that an agent re-reading e.g. 500 Memgraph issues is served from memory instead of re-fetching.
Notes
- Domain: Context Graph family (
context-graph/). Read CONTEXT-MAP.md → Sessions Graph, Actions Graph, Agent Context Graph and unstructured2graph CONTEXT.md files before resolving a ticket.
- Skills:
/grilling + /domain-modeling for grilling tickets (new terms like Resource go into a CONTEXT.md), /research for research tickets, /prototype for the graph-model ticket.
- v1 scope: public GitHub resources (repos, issues, PRs, comments) that the agent fetches itself or that the user hands it directly (pasted URL / text).
- Today a GitHub read only survives as a ToolResult Action (Collection-Tier Data) and, after Session Reconciliation, as Chunks/Entities; unstructured2graph persists no Source node. Nothing gives "the thing that was read" a durable identity — that is the gap.
- Public resources are shared, not user-owned — relevant to the multiplayer framing; Memories stay user-owned.
- Planning only: produce decisions, not code.
- Hook config rule applies: hook subprocesses read config values only from the config file, never env vars.
- External reference systems shared for research are described by process, never by name.
Decisions so far
- Research: how GitHub resource reads appear in harness hook payloads — tool input reliably identifies the resource (URL,
gh/curl argv, MCP args, prompt URLs) in all harnesses but Antigravity; tool output is not usable as content (WebFetch is often a model summary, shell/MCP truncates, some harnesses send none); user-handed URLs arrive only via the prompt hook, so handed vs fetched is distinguishable.
- Research: GitHub identity and freshness signals for public resources — key Resources on GraphQL
node_id (URL / owner/repo#n are mutable address props; issue/PR share numbering); freshness = source updated_at + our fetched_at; unauthenticated = 60 REST calls/h, no GraphQL, 304s still cost — a 500-issue re-read is only cheap with a token.
- Grilling: Resource capture model — passive, active, or hybrid — hybrid: hooks record an address-only Touch (FETCHED/PROMPTED, linked to Session/Action/Agent; a listing = one Touch on the repo with its filters); an out-of-band Sweep fetches canonical, public-only content (issues/PRs with comments, repo + README, listing members at full depth), resolves addresses to
node_id, and leaves failures as unresolved Touches with a reason.
- Grilling: Resources component placement and Resource ownership — new
context-graph/resources-graph package (connector → Touches, core, CLI Sweep, read Tool); name Resource chosen to generalise beyond GitHub; Resources belong to no user (shared, public), Touches are private to their user via HAD_SESSION, read side fails closed; soft joins only — Sweep links Touch→Action/Agent on tool_use_id, no sibling imports.
- Grilling: what a Resource cache hit means — address-keyed
resource(address) MCP tool (not recall) + a non-blocking PreToolUse nudge, never a block; tool never calls GitHub, returns facts (fetched_at, updated_at) and the model judges staleness; refresh is touch-driven by real re-fetches only; listings return a paged index, members read one at a time; exact match plus subsumption for structured filters on fully expanded listings; cache reads are Touches with hit/subsumed/miss.
- Prototype: GitHub Resource graph model — validated on all 686 open memgraph/memgraph issues:
(:Repository)->(:Issue|:PullRequest)->(:Comment), Touch→shared (:Listing) (not a Resource, members replaced on refetch); Sweep fetches only what was asked or explored; comments are nodes but not Resources; REFERENCES/CLOSES only between stored Resources; metadata stays properties; resolve items by issueOrPullRequest(number); reactions don't bump updatedAt (accepted).
Not yet specified
- How Resource content feeds Chunks/Entities — chunk once per Resource (dedup across sessions/users) rather than per session reconciliation?
- Generalising beyond GitHub: arbitrary URLs, PDFs, pasted text — does the GitHub model generalise into a platform-adapter shape?
- Retention/eviction for large resource sets (hundreds of issues per sweep).
- Eval: how to show caching actually helps (fetch avoided, answer quality unchanged). Live served/used analytics split out to track and analyse memory served to and used by the model.
- Which harnesses can inject PreToolUse context without denying the call (decides where the nudge works) — implementation fact to verify.
- Code as a Resource: diffs, source files, reads of a local clone — versioned by commit, not
updated_at, so it needs its own identity/freshness model.
- actions-graph must expose
tool_use_id as a matchable Action property so the Sweep can draw Touch→Action edges (small change in a sibling; lands with implementation).
- How Touches behave once Actions are compressed/decayed (Touch → Action is today's main path back to the model's decision).
- GitHub metadata as nodes (labels, GitHub users) once cross-Resource traversal needs it — and how GitHub users relate to extracted Entities and our own
(:User).
- Does an issue's
node_id survive a transfer to another repo? (unverified fact; affects Resource identity)
Out of scope
- Private / authenticated resources.
- Non-GitHub platforms in this map.
- Implementation — the map ends at the spec.
Destination
A spec for a Resources component in the Context Graph family, ready to hand to
/to-prd: what counts as a Resource, how harness activity reveals that one was touched, its graph model (GitHub first), cache/freshness semantics, and how it connects to recall and the Chunk/Entity layer — so that an agent re-reading e.g. 500 Memgraph issues is served from memory instead of re-fetching.Notes
context-graph/). ReadCONTEXT-MAP.md→ Sessions Graph, Actions Graph, Agent Context Graph and unstructured2graphCONTEXT.mdfiles before resolving a ticket./grilling+/domain-modelingfor grilling tickets (new terms like Resource go into aCONTEXT.md),/researchfor research tickets,/prototypefor the graph-model ticket.Decisions so far
gh/curlargv, MCP args, prompt URLs) in all harnesses but Antigravity; tool output is not usable as content (WebFetch is often a model summary, shell/MCP truncates, some harnesses send none); user-handed URLs arrive only via the prompt hook, so handed vs fetched is distinguishable.node_id(URL /owner/repo#nare mutable address props; issue/PR share numbering); freshness = sourceupdated_at+ ourfetched_at; unauthenticated = 60 REST calls/h, no GraphQL, 304s still cost — a 500-issue re-read is only cheap with a token.node_id, and leaves failures as unresolved Touches with a reason.context-graph/resources-graphpackage (connector → Touches, core, CLI Sweep, readTool); name Resource chosen to generalise beyond GitHub; Resources belong to no user (shared, public), Touches are private to their user viaHAD_SESSION, read side fails closed; soft joins only — Sweep links Touch→Action/Agent ontool_use_id, no sibling imports.resource(address)MCP tool (notrecall) + a non-blocking PreToolUse nudge, never a block; tool never calls GitHub, returns facts (fetched_at,updated_at) and the model judges staleness; refresh is touch-driven by real re-fetches only; listings return a paged index, members read one at a time; exact match plus subsumption for structured filters on fully expanded listings; cache reads are Touches with hit/subsumed/miss.(:Repository)->(:Issue|:PullRequest)->(:Comment), Touch→shared(:Listing)(not a Resource, members replaced on refetch); Sweep fetches only what was asked or explored; comments are nodes but not Resources;REFERENCES/CLOSESonly between stored Resources; metadata stays properties; resolve items byissueOrPullRequest(number); reactions don't bumpupdatedAt(accepted).Not yet specified
updated_at, so it needs its own identity/freshness model.tool_use_idas a matchable Action property so the Sweep can draw Touch→Action edges (small change in a sibling; lands with implementation).(:User).node_idsurvive a transfer to another repo? (unverified fact; affects Resource identity)Out of scope