Issue-corpus renderer: git-mirrored discovery index of fj issues for warded containers #297
Labels
No labels
burndown-2026-06
coherence-core
consult
headless
interactive
P0
P1
P2
P3
P4
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
coilyco-flight-deck/agentic-os#297
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Motivation
A critical bit of information lived in
coilysiren/inboxand neither Kai nor theagent could find it. It surfaced only after a native agent grepped two weeks of
session logs. The real gap is offline full-text grep over the issue/inbox
corpus. Today
ward ops forgejo issue list-allgives title/label filtering andone-issue-at-a-time API reads. It cannot do "grep every body and comment across
every repo for this phrase", which is exactly the operation that finally worked.
Design decision (settled with Kai)
Build a discovery index, not an offline source of truth. Render the issue
corpus to git-mirrored markdown, hydrated into containers via the existing
warm-cache / gitcache machinery (the same path that seeds
/substrate/<name>from
/opt/substrate-seed, seedocker/dev-base/Dockerfile:163-181). The agentgreps the corpus offline to locate an issue, then confirms current state live
via
ward ops forgejo issue view <owner> <name> <N>. Grep finds the needle, theAPI confirms the live state. This respects the anti-drift doctrine in AGENTS.md
(a point-in-time snapshot must not silently anchor a stale picture) and reuses
the hydrate path unchanged: issues become just another mirror input.
Scope chosen: all tracked repos, open AND closed issues. The needle could
just as easily live in a closed issue.
This issue = the renderer + its cron (authoring side)
Per the authoring-vs-rollout contract, the renderer is a tool authored here in
agentic-os and triggered by a cron, never hand-run. The container mount wiring is
a separate ward issue (filed as a sibling, blocked on this).
Spec
(
docker/dev-base/substrate-image-repos.txt) pluscoilysiren/inbox, open andclosed, bodies and all comments. Make the repo list a small config, not hardcoded.
<owner>/<name>/<index>-<slug>.md,in a dedicated git mirror repo.
state: open|closed,rendered-at(timestamp + source commit/issue updated_at), title, labels, author. Then the
body and every comment. The header must carry the index disclaimer: "discovery
index, confirm live state via
ward ops forgejo issue view <owner> <name> <N>".coilysiren/inboxis private. The mirror repo MUST be private andMUST NOT land in the public substrate image seed
(
substrate-image-repos.txtis the public tier). It goes in the privatecache-tier, hydrated with creds. Run trufflehog over the rendered corpus before
push as the secret-scan backstop.
ward ops forgejo(ward-kdl),so the renderer holds no
FORGEJO_TOKEN, same asscripts/goose-triage.py:41-46..forgejo/workflows/job). Tight cadence boundsstaleness. Incremental where practical (use
updated_at/sinceto re-renderonly changed issues).
Out of scope (separate issues)
sibling issue, blocked on this.
was actually grepped) - separate agentic-os sibling issue.
Design consult and capture from a
warded architectsession.🔒 Reserved by
ward agent --driver claude— containerward-agentic-os-issue-297-claude-8d9f0a47on host61f1003a88ecis carrying this issue (reserved 2026-06-26T02:41:16Z). Concurrentward agentruns are blocked until it finishes or the reservation goes stale (2h0m0s TTL);--forceoverrides.— Claude (she/her), via
ward agentWARD-OUTCOME: done - issue-corpus renderer + hourly cron landed on main (closes #297)
Retrospective from the agent that carried this:
The shape settled fast because the issue had already done the hard design work
with Kai, so this was mostly faithful execution. The renderer worked first try
against the live Forgejo API -
ward ops forgejo issue list-all --state allplusa per-issue
issue-comment listgave everything the header needed, and theincremental manifest skip dropped the second run of 296 agentic-os issues to zero
re-renders and zero comment fetches, which is exactly the cheap-listing-expensive-
comment split I was hoping for.
What fought back was small: the code-comments hook rejected a YAML comment tucked
under the
env:block (a key-sorter would drift it), so I moved that note up intothe top header. Good discipline, caught at author time.
The honest soft spot is that this is the authoring half only. The renderer and
cron are real and tested (29 unit tests, live smoke run over the full agentic-os
backlog), but the cron cannot actually fire green until the rollout side lands in
infrastructure/ansible:
ward+ AWS/SSM on the Forgejo runner, the privatecoilysiren/issue-corpusmirror repo, and theISSUE_CORPUS_PUSH_TOKENsecret.I made it no-op cleanly while the token is unset so it does not red-fail hourly in
the meantime. Confidence in the renderer logic is high; confidence that the first
scheduled run is green is lower, since the runner provisioning is out of this repo
and untested here.
Follow-ups worth filing: the container mount that hydrates this mirror into
/substrateis the blocked ward sibling and still needs writing; deleted issuescurrently leave a stale file behind (no reaping); and
coilysiren/coilysirenisomitted until its Forgejo mirror lands (infrastructure#352).
Design refinement (from the architect session, surfaced after dispatch):
Segment the rendered output by sensitivity. Emit two corpus subtrees (or two
mirror repos):
(
docker/dev-base/substrate-image-repos.txt), greppable by any agent, andcoilysiren/inboxplus any private repos, gated.Why: the mount layer (ward#367) gates inbox content behind per-driver permission
segmentation. A clean public/private split lets the public issue corpus mount
broadly while inbox mounts only for the cleared driver tier. If a split is
expensive, whole-corpus-private is the safe default (it just over-gates the
public issues) and the split can be a follow-up - do not block this carry on it.
Either way the mirror stays private and never touches the public image seed.