A filed issue carries its destination as well as the sandbox mark #828

Merged
coilysiren merged 1 commit from aos/claude/xh55-move-to-repo into main 2026-08-15 20:12:36 +00:00
Member

Closes #756. ward exec gate PASS on all six steps.

The defect in the title

The creation path set the labels field to exactly one id:

labelled[sandboxLabelField] = []int{p.LabelID}

So a second label was unreachable, which is what blocked applying move-to-repo/unknown at creation. The policy now carries a set: the sandbox id and a destination id, each independently optional, applied in a fixed order.

What it deliberately does not do

It does not let the model's labels through. docs/sirens-echo-sandbox-label.md records that setting rather than merging is the control, chosen over three rejected layers, because issue bodies contain member-influenced text. That survives intact — a model that could name its own destination could route its own issue away from the people who read this tracker. TestAModelCannotChooseItsOwnLabels pins it.

Step 1 was already done, and not where the spec said

The spec asked me to create move-to-repo/unknown in the coilyco-gaming org label set, matching the convention of the existing move-to-repo/* labels.

It already exists — id 358 — and it is a repo-level label on coilyco-gaming/sirens-echo, not an org label. So are the other four move-to-repo/* labels and SANDBOXED. The org set has ten labels and none of them are these.

Nothing was created and no live mutation was needed. I checked the org set first, found nothing matching, and only then found them at repo level — which is the only reason this did not land as a duplicate label in the wrong scope.

id label
353 🔒⚠️📦⚠️🔒 SANDBOXED 🔒⚠️📦⚠️🔒
354-357 move-to-repo/<destination>
358 move-to-repo/unknown

Default rather than replacement

SIRENS_ECHO_DESTINATION_LABEL names the id to apply. The deployment sets the unknown one unless it knows the home — which is where the label-id-to-name mapping already lives, and it is how SIRENS_ECHO_SANDBOX_LABEL already works.

Only one destination is ever sent. The move-to-repo/* labels are exclusive: true in Forgejo, so the tracker keeps one per issue by itself and an ordinary triage label displaces unknown with no help from this service. That is why the acceptance case "an explicit destination does not also carry unknown" needs no code — it is a property of the label scope.

Acceptance

  • Two or more labels at creation carry all of themTestCreationCarriesEveryConfiguredLabel.
  • No destination configured carries nothing extra, each label independently optionalTestEitherLabelAloneStillApplies.
  • An explicit destination is not accompanied by unknownTestTheDestinationIsWhicheverOneIsConfigured, plus Forgejo's own exclusivity.
  • Removing unknown and adding a real destination needs no special handling — it is a tracker-side edit and this service reads none of it back.

Naming

sandboxLabelPolicy applied two different labels once this landed, so it is issueLabelPolicy in issuelabels.go, and withSandboxLabel is withHarnessLabels. The source-text assertion in sandboxwiring_test.go moves with it, since it names the call it checks.

Deployment half

Unchanged in shape from the sandbox label's: the id is configured there, and the labels field is already granted on create-issue. Until SIRENS_ECHO_DESTINATION_LABEL is set, behaviour is exactly today's.

Closes #756. `ward exec gate` PASS on all six steps. ## The defect in the title The creation path set the `labels` field to exactly one id: ```go labelled[sandboxLabelField] = []int{p.LabelID} ``` So a second label was unreachable, which is what blocked applying `move-to-repo/unknown` at creation. The policy now carries a set: the sandbox id and a destination id, each independently optional, applied in a fixed order. ## What it deliberately does not do It does **not** let the model's labels through. `docs/sirens-echo-sandbox-label.md` records that setting rather than merging is the control, chosen over three rejected layers, because issue bodies contain member-influenced text. That survives intact — a model that could name its own destination could route its own issue away from the people who read this tracker. `TestAModelCannotChooseItsOwnLabels` pins it. ## Step 1 was already done, and not where the spec said The spec asked me to create `move-to-repo/unknown` in the **coilyco-gaming org** label set, matching the convention of the existing `move-to-repo/*` labels. It already exists — **id 358** — and it is a **repo-level** label on `coilyco-gaming/sirens-echo`, not an org label. So are the other four `move-to-repo/*` labels and `SANDBOXED`. The org set has ten labels and none of them are these. Nothing was created and no live mutation was needed. I checked the org set first, found nothing matching, and only then found them at repo level — which is the only reason this did not land as a duplicate label in the wrong scope. | id | label | | --- | --- | | 353 | `🔒⚠️📦⚠️🔒 SANDBOXED 🔒⚠️📦⚠️🔒` | | 354-357 | `move-to-repo/<destination>` | | 358 | `move-to-repo/unknown` | ## Default rather than replacement `SIRENS_ECHO_DESTINATION_LABEL` names the id to apply. The deployment sets the unknown one unless it knows the home — which is where the label-id-to-name mapping already lives, and it is how `SIRENS_ECHO_SANDBOX_LABEL` already works. **Only one destination is ever sent.** The `move-to-repo/*` labels are `exclusive: true` in Forgejo, so the tracker keeps one per issue by itself and an ordinary triage label displaces `unknown` with no help from this service. That is why the acceptance case "an explicit destination does not also carry unknown" needs no code — it is a property of the label scope. ## Acceptance * **Two or more labels at creation carry all of them** — `TestCreationCarriesEveryConfiguredLabel`. * **No destination configured carries nothing extra, each label independently optional** — `TestEitherLabelAloneStillApplies`. * **An explicit destination is not accompanied by unknown** — `TestTheDestinationIsWhicheverOneIsConfigured`, plus Forgejo's own exclusivity. * **Removing unknown and adding a real destination needs no special handling** — it is a tracker-side edit and this service reads none of it back. ## Naming `sandboxLabelPolicy` applied two different labels once this landed, so it is `issueLabelPolicy` in `issuelabels.go`, and `withSandboxLabel` is `withHarnessLabels`. The source-text assertion in `sandboxwiring_test.go` moves with it, since it names the call it checks. ## Deployment half Unchanged in shape from the sandbox label's: the id is configured there, and the `labels` field is already granted on create-issue. Until `SIRENS_ECHO_DESTINATION_LABEL` is set, behaviour is exactly today's.
feat(labels): a filed issue carries its destination as well as the sandbox mark
All checks were successful
ci / image-build (pull_request) Successful in 26s
ci / test (pull_request) Successful in 46s
ci / publish-echo-image (pull_request) Has been skipped
ci / publish-observed (pull_request) Has been skipped
448242f7e0
The creation path set the labels field to exactly one id, so a second label was
unreachable. That is the defect in the title, and it blocked applying
move-to-repo/unknown at creation.

The policy now carries a set. The sandbox id and a destination id are each
independently optional, applied in a fixed order, and still SET rather than
merged. That last part is the control the sandbox label exists for and it is
why this is not simply "let labels through": a model that could name its own
destination could route its own issue away from the people who read this
tracker. TestAModelCannotChooseItsOwnLabels pins it.

WHAT THE SPEC ASKED FOR AND WHAT WAS ALREADY THERE

Step 1 asked for move-to-repo/unknown to be created in the coilyco-gaming org
label set. It already exists, as id 358, and at repo level on sirens-echo
rather than on the org. So do the other four move-to-repo labels and SANDBOXED,
none of which are org labels. Nothing was created and no live mutation was
needed. Reading the tracker first is the only reason this did not land as a
duplicate label in the wrong scope.

DEFAULT RATHER THAN REPLACEMENT

SIRENS_ECHO_DESTINATION_LABEL names the move-to-repo id to apply. The
deployment sets the unknown one unless it knows the home, which is where the
label-id-to-name mapping already lives, so a deployment that does know sets
that id and unknown is never the one applied.

Only one destination is ever sent. The move-to-repo labels are exclusive in
Forgejo, so the tracker keeps one per issue on its own and an ordinary triage
label displaces unknown with no help from this service. That is also why the
"explicit destination does not also carry unknown" case needs no code: it is a
property of the label scope, not of this policy.

NAMING

sandboxLabelPolicy applied two different labels once this landed, so it is
issueLabelPolicy in issuelabels.go, and withSandboxLabel is withHarnessLabels.
The source-text assertion in sandboxwiring_test.go moves with it, since it
names the call it checks.

The deployment half is unchanged in shape from the sandbox label's: the id is
configured there, and the labels field is already granted on create-issue.

Closes #756

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Angie <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
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!828
No description provided.