close-session: teach it the claim envelope, and refresh its stale classification hint list #112

Closed
opened 2026-08-23 05:38:08 +00:00 by mathias · 1 comment
Owner

Two documentation gaps in skills/close-session/SKILL.md, found by checking it against this estate's current state before running it (2026-08-23). Neither breaks the skill today.

1. It does not know the claim envelope exists

capture's insight-write now passes through claim.ValidateEnvelope (#102): capture → brainstore.Write → api.WriteNote → writeHallNote → ValidateEnvelope.

Nothing breaks — validation only fires when half_life/applies/claim_provenance are present, and the skill never emits them. But:

  • an author who hand-writes half_life: durable into an insight without claim_provenance gets a per-item error in the receipt with a message the skill gives no context for;
  • more importantly, the affordance is invisible. A close-session insight is exactly the kind of note that should declare half_life: durable, applies: universal, claim_provenance: asserted — durable, generalizable, human-decided. The skill is the natural place to say so.

Suggested: a line in Phase 4's insights[] description noting the optional envelope, the enum values, and that provenance is required whenever either field is set.

2. The tagged-repo hint list is stale

The skill lists repos "tagged internal today" and correctly says "treat classification.yaml as authoritative — this list is a hint, not gospel." Since it was written, hyperguild#91's sweep took classification.yaml from 10 of 47 repos tagged to roughly 39, deliberately leaving eight untagged with reasons in the file.

Self-correcting in practice, but a stale hint on a fail-safe gate misleads in the expensive direction: someone reads the short list, assumes their repo is untagged, and skips a capture that would have worked.

Suggested: replace the enumerated list with the rule (untagged → confidential, fail-safe) plus a pointer at the file, and drop the enumeration entirely rather than re-freezing it.

Not in scope

The skill's capture-first design, the dry-run gate, and the classification-gate explanation are all still correct — including its account of the I1 refusal, which hyperguild#91 later confirmed was the real cause of the "tickets array is broken" report.

Risk: LOW — documentation.

Refs: #102, #91, brain#21, skills/close-session/SKILL.md.

Two documentation gaps in `skills/close-session/SKILL.md`, found by checking it against this estate's current state before running it (2026-08-23). Neither breaks the skill today. ## 1. It does not know the claim envelope exists `capture`'s insight-write now passes through `claim.ValidateEnvelope` (#102): `capture → brainstore.Write → api.WriteNote → writeHallNote → ValidateEnvelope`. Nothing breaks — validation only fires when `half_life`/`applies`/`claim_provenance` are present, and the skill never emits them. But: - an author who hand-writes `half_life: durable` into an insight **without** `claim_provenance` gets a per-item error in the receipt with a message the skill gives no context for; - more importantly, the affordance is invisible. A close-session insight is *exactly* the kind of note that should declare `half_life: durable, applies: universal, claim_provenance: asserted` — durable, generalizable, human-decided. The skill is the natural place to say so. Suggested: a line in Phase 4's `insights[]` description noting the optional envelope, the enum values, and that provenance is required whenever either field is set. ## 2. The tagged-repo hint list is stale The skill lists repos "tagged internal today" and correctly says *"treat `classification.yaml` as authoritative — this list is a hint, not gospel."* Since it was written, hyperguild#91's sweep took `classification.yaml` from **10 of 47** repos tagged to roughly **39**, deliberately leaving eight untagged with reasons in the file. Self-correcting in practice, but a stale hint on a fail-safe gate misleads in the expensive direction: someone reads the short list, assumes their repo is untagged, and skips a capture that would have worked. Suggested: replace the enumerated list with the *rule* (untagged → confidential, fail-safe) plus a pointer at the file, and drop the enumeration entirely rather than re-freezing it. ## Not in scope The skill's `capture`-first design, the dry-run gate, and the classification-gate explanation are all still correct — including its account of the I1 refusal, which hyperguild#91 later confirmed was the real cause of the "tickets array is broken" report. **Risk:** LOW — documentation. Refs: #102, #91, brain#21, `skills/close-session/SKILL.md`.
mathias added the risk/lowsize/xstype/docs labels 2026-08-27 05:25:42 +00:00
mathias added the agent/ready label 2026-08-27 05:28:18 +00:00
Author
Owner

Verified and merged in mathias/hyperguild#124, commit 5a5d938e8e.

Second-round fix (e2cb315) builds the claim envelope map from fm (post-merge, pre-write) instead of the caller's raw contentFM fragment, in ingestion/internal/api/update.go. Independently re-verified before merging:

  • Flip-tested TestUpdateNoteRejectsClearingProvenanceWhileEnvelopeSurvives myself: reverted the envelope map to build from contentFM again, confirmed the test goes red ("An error is expected but got nil"); restored the fix, confirmed green.
  • Adversarial case (mine, not in the PR's own tests): prior note with no envelope at all, update sets half_life: durable alone -> correctly rejected, file unchanged.
  • Confirmed updated_at/supersedes cannot be spoofed via the caller's fragment: both are unconditionally re-set after the merge loop.
  • Noted, non-blocking: supersede_reason set via the caller's own fragment survives when opts.Reason is empty -- same-actor two ways to set the same field, not a cross-update provenance leak like the envelope bug, so not treated as blocking.

CI green on the merged head SHA (run 7795, e2cb315, conclusion success).

Verified and merged in mathias/hyperguild#124, commit 5a5d938e8e1d0f9d356e9d0d1d2bfed80dc506ad. Second-round fix (e2cb315) builds the claim envelope map from `fm` (post-merge, pre-write) instead of the caller's raw `contentFM` fragment, in ingestion/internal/api/update.go. Independently re-verified before merging: - Flip-tested TestUpdateNoteRejectsClearingProvenanceWhileEnvelopeSurvives myself: reverted the envelope map to build from `contentFM` again, confirmed the test goes red ("An error is expected but got nil"); restored the fix, confirmed green. - Adversarial case (mine, not in the PR's own tests): prior note with no envelope at all, update sets `half_life: durable` alone -> correctly rejected, file unchanged. - Confirmed `updated_at`/`supersedes` cannot be spoofed via the caller's fragment: both are unconditionally re-set after the merge loop. - Noted, non-blocking: `supersede_reason` set via the caller's own fragment survives when `opts.Reason` is empty -- same-actor two ways to set the same field, not a cross-update provenance leak like the envelope bug, so not treated as blocking. CI green on the merged head SHA (run 7795, e2cb315, conclusion success).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mathias/hyperguild#112