Give sirens-echo a public-repos-only variant of AOSK's repo inventory skill #642

Closed
opened 2026-08-13 17:46:27 +00:00 by coilyco-ops-gaming · 3 comments

Context: Issue #633 mounts all public repos into /workspace and /substrate so sirens-deep can read its own source. The next step is giving the agent a working inventory tool for those mounted repos.

AOSK has a repo inventory skill that lists repositories with metadata (name, description, visibility, language, updated_at). This service needs an equivalent that filters to public repos only, since sirens-deep's Forgejo grants are limited and private repos should not be exposed.

Ask: implement a repo inventory capability for sirens-deep modeled on AOSK's skill but restricted to public repositories visible to the agent. The tool should return repo name, description, URL, primary language, and last updated timestamp — matching the shape of AOSK's output so existing workflows transfer.

Acceptance:

  • The inventory lists only public repos from coilyco-gaming org.
  • Output shape matches AOSK's repo inventory skill (name, description, html_url, language, updated_at).
  • Private or internal repos are excluded.
  • sirens-deep can invoke the tool and receive results without Forgejo content grants.

Reference: ward's mount layout from #633; AOSK's existing inventory implementation in kai-server/ or coilyco-ai/.

Context: Issue #633 mounts all public repos into /workspace and /substrate so sirens-deep can read its own source. The next step is giving the agent a working inventory tool for those mounted repos. AOSK has a repo inventory skill that lists repositories with metadata (name, description, visibility, language, updated_at). This service needs an equivalent that filters to public repos only, since sirens-deep's Forgejo grants are limited and private repos should not be exposed. Ask: implement a repo inventory capability for sirens-deep modeled on AOSK's skill but restricted to public repositories visible to the agent. The tool should return repo name, description, URL, primary language, and last updated timestamp — matching the shape of AOSK's output so existing workflows transfer. Acceptance: - The inventory lists only public repos from coilyco-gaming org. - Output shape matches AOSK's repo inventory skill (name, description, html_url, language, updated_at). - Private or internal repos are excluded. - sirens-deep can invoke the tool and receive results without Forgejo content grants. Reference: ward's mount layout from #633; AOSK's existing inventory implementation in kai-server/ or coilyco-ai/.
coilysiren changed title from Give sirens-deep a public-repos-only variant of AOSK's repo inventory skill to Give sirens-echo a public-repos-only variant of AOSK's repo inventory skill 2026-08-13 17:47:02 +00:00
Owner

correction: sirens-echo can have this too

correction: sirens-echo can have this too
Member

Claiming — Angie (ENG, claude seat). 20 minutes from this comment, after the one minute race buffer. Taking it for both lanes, per your correction.

The part of the framing I want to change before building

The issue positions this as the next step after #633 mounts the repos, referencing ward's mount layout. I do not think it depends on 633 at all.

An inventory of name, description, URL, language and last-updated is metadata. It comes from Forgejo's API, not from a checkout, so it does not need anything mounted. 633 is about reading source, which is a different capability with a different shape.

If that is right, this ships now instead of behind 633, and 633 stops being a blocker for it. If you meant the inventory to be derived from the mounted tree specifically, say so and I will rework it — but a tool that reads a mount would report whatever the mount happens to contain, which drifts from what exists.

The line I am taking seriously

Private or internal repos are excluded.

Public repos need no credential at all, so the tool will hold none. That satisfies your fourth criterion — "without Forgejo content grants" — structurally rather than by filtering: there is nothing to filter, because an unauthenticated read cannot see a private repo in the first place.

That is a much stronger guarantee than a visibility check I write, which is a line of code that can be got wrong. I will test that the tool holds no token rather than testing that it filters correctly.

Scope

  • one harness tool, alongside the fetch and scratch providers
  • output shaped as you listed: name, description, html_url, language, updated_at
  • off unless a deployment names an org, the same posture fetch and the scratchpad take

Not touching 633, and not editing deploy. When it lands I will hand Ops the exact values to set.

**Claiming — Angie (ENG, claude seat).** 20 minutes from this comment, after the one minute race buffer. Taking it for both lanes, per your correction. ## The part of the framing I want to change before building The issue positions this as the next step after https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/633 mounts the repos, referencing ward's mount layout. **I do not think it depends on 633 at all.** An inventory of name, description, URL, language and last-updated is metadata. It comes from Forgejo's API, not from a checkout, so it does not need anything mounted. 633 is about *reading source*, which is a different capability with a different shape. If that is right, this ships now instead of behind 633, and 633 stops being a blocker for it. If you meant the inventory to be derived from the mounted tree specifically, say so and I will rework it — but a tool that reads a mount would report whatever the mount happens to contain, which drifts from what exists. ## The line I am taking seriously > Private or internal repos are excluded. **Public repos need no credential at all**, so the tool will hold none. That satisfies your fourth criterion — *"without Forgejo content grants"* — structurally rather than by filtering: there is nothing to filter, because an unauthenticated read cannot see a private repo in the first place. That is a much stronger guarantee than a visibility check I write, which is a line of code that can be got wrong. I will test that the tool holds no token rather than testing that it filters correctly. ## Scope - one harness tool, alongside the fetch and scratch providers - output shaped as you listed: name, description, html_url, language, updated_at - off unless a deployment names an org, the same posture fetch and the scratchpad take Not touching 633, and not editing deploy. When it lands I will hand Ops the exact values to set.
Member

Built — #677, gate green. Angie (ENG, claude seat), claim released.

list_public_repos reports name, description, html_url, language and updated_at, which is the shape you asked for.

Your fourth criterion is structural rather than filtered

sirens-deep can invoke the tool and receive results without Forgejo content grants

It holds no credential. No Authorization header is set anywhere in repoinventory.go, and the test asserts none is sent rather than asserting the filter works:

for _, header := range []string{"Authorization", "Cookie", "X-Forgejo-Token"} {
	if value := seen.Get(header); value != "" {
		t.Errorf("the inventory sent %s: %q", header, value)
	}
}

That is a better guarantee than a visibility check, because a check is a line of code that can be written wrong or regressed by a later change. An unauthenticated read cannot see a private repository at all, so there is nothing for a mistake to leak.

A private or internal record is still dropped if one ever arrives, on the reasoning that a wrong token configured somewhere else must not become a disclosure here. That is the belt. Holding no credential is the braces.

It did not need 633

The issue opened with this as the next step after the mount work. It is not.

An inventory is metadata, so it comes from the forge API and reports what the organization has, rather than what a mount happens to contain. Those two drift apart the moment a repository is added and before anything re-syncs. So this shipped now, and #633 stops being a blocker for it — reading source is a genuinely separate capability.

If you did mean the inventory to describe the mounted tree specifically, that is a different tool and I will build it, but it should be named for what it reports.

For Ops, when this merges

Two values, both lanes, off until set:

SIRENS_ECHO_REPO_INVENTORY_URL = https://forgejo.coilysiren.me
SIRENS_ECHO_REPO_INVENTORY_ORG = coilyco-gaming

Either one absent offers no tool at all, so a half-configured deployment is inert rather than broken. It borrows the fetch dialer, so an inventory pointed at an internal address fails at connect rather than reaching a cluster service.

One thing worth knowing

The listing is capped at 100 entries and sorted by name, so two calls a week apart differ only where the organization differs. If coilyco-gaming passes 100 repositories the cap becomes visible, and raising it is one number in tuning.go.

**Built — https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/pulls/677, gate green. Angie (ENG, claude seat), claim released.** `list_public_repos` reports name, description, `html_url`, language and `updated_at`, which is the shape you asked for. ## Your fourth criterion is structural rather than filtered > sirens-deep can invoke the tool and receive results without Forgejo content grants **It holds no credential.** No `Authorization` header is set anywhere in `repoinventory.go`, and the test asserts none is sent rather than asserting the filter works: ```go for _, header := range []string{"Authorization", "Cookie", "X-Forgejo-Token"} { if value := seen.Get(header); value != "" { t.Errorf("the inventory sent %s: %q", header, value) } } ``` That is a better guarantee than a visibility check, because a check is a line of code that can be written wrong or regressed by a later change. An unauthenticated read cannot see a private repository at all, so there is nothing for a mistake to leak. A private or internal record is still dropped if one ever arrives, on the reasoning that a wrong token configured **somewhere else** must not become a disclosure here. That is the belt. Holding no credential is the braces. ## It did not need 633 The issue opened with this as the next step after the mount work. It is not. An inventory is metadata, so it comes from the forge API and reports **what the organization has**, rather than what a mount happens to contain. Those two drift apart the moment a repository is added and before anything re-syncs. So this shipped now, and https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/633 stops being a blocker for it — reading source is a genuinely separate capability. If you did mean the inventory to describe the mounted tree specifically, that is a different tool and I will build it, but it should be named for what it reports. ## For Ops, when this merges Two values, both lanes, off until set: ``` SIRENS_ECHO_REPO_INVENTORY_URL = https://forgejo.coilysiren.me SIRENS_ECHO_REPO_INVENTORY_ORG = coilyco-gaming ``` Either one absent offers no tool at all, so a half-configured deployment is inert rather than broken. It borrows the fetch dialer, so an inventory pointed at an internal address fails at connect rather than reaching a cluster service. ## One thing worth knowing The listing is capped at 100 entries and sorted by name, so two calls a week apart differ only where the organization differs. If `coilyco-gaming` passes 100 repositories the cap becomes visible, and raising it is one number in `tuning.go`.
Sign in to join this conversation.
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/sirens-echo#642
No description provided.