Skip to content

fix: harden forge-global and always-on-guidance skills for compression resilience - #59

Merged
jflowers merged 3 commits into
unbound-force:mainfrom
jflowers:opsx/harden-skill-compression
Aug 11, 2026
Merged

fix: harden forge-global and always-on-guidance skills for compression resilience#59
jflowers merged 3 commits into
unbound-force:mainfrom
jflowers:opsx/harden-skill-compression

Conversation

@jflowers

@jflowers jflowers commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Restructures two embedded skill files to improve constraint survival under DCP context compression, addressing six specific vulnerabilities identified in #51.

forge-global: Replaces parallel "do/don't" lists with a decision table (Signal/Forge/Skip columns), inlines TTL parameter into the reservation step, and adds temporal ordering markers (FIRST/THEN/FINALLY) to protocol steps.

always-on-guidance: Adds a dedicated ## Critical Safety section for safety-critical rules, moves hivemind_find from last to first position in Tool Usage, and splits Code Quality/Testing/Error Handling lists into sub-headed groups of 2-3 items each.

All changes are structural reorganization -- no rules were added, removed, or weakened.

Closes #51

How to Test

# Build passes (embedded content compiles via go:embed)
make build

# All tests pass including agentkit tests (file existence, count, frontmatter)
make test

# Verify semantic equivalence
git diff main -- internal/agentkit/content/skills/

Acceptance criteria from specs:

  • Critical Safety section appears before all other rule sections
  • Decision table has Signal/Forge/Skip columns with all 6 original criteria
  • Each protocol step contains a temporal marker (FIRST/THEN/FINALLY)
  • hivemind_find is the first item in Tool Usage
  • TTL is inlined into the comms_reserve call (no standalone TTL bullet)
  • All sub-lists contain no more than 3 items

How to Demo

Inspect the restructured skill files:

cat internal/agentkit/content/skills/forge-global/SKILL.md
cat internal/agentkit/content/skills/always-on-guidance/SKILL.md

Compare the decision table format in forge-global and the sub-headed groups in always-on-guidance against the original flat list structure.

Key Files Changed

File Description
internal/agentkit/content/skills/forge-global/SKILL.md Decision table, inline TTL, temporal ordering
internal/agentkit/content/skills/always-on-guidance/SKILL.md Critical Safety section, repositioned hivemind_find, sub-headed groups
.opencode/skills/forge-global/SKILL.md Synced with canonical embedded source
.opencode/skills/always-on-guidance/SKILL.md Synced with canonical embedded source
openspec/changes/harden-skill-compression/* OpenSpec artifacts (proposal, design, specs, tasks)

This PR was generated by /uf.finale (AI-assisted).

@jflowers
jflowers requested a review from a team as a code owner August 2, 2026 20:35
@jflowers
jflowers requested a review from yvonnedevlinrh August 2, 2026 20:50
@jflowers jflowers self-assigned this Aug 2, 2026
@jflowers jflowers moved this to In Review 👀 in Unbound Force Planning Aug 2, 2026

@sonupreetam sonupreetam left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Council

Ran the review council (6 Divisor agents). The restructuring patterns (decision table, temporal markers, priority positioning) are sound but needs structural tests and drift detection.

Cross-PR note: The Curator filed a blog opportunity issue for the prompt hardening methodology: unbound-force/website#198.

Comment thread internal/agentkit/content/skills/always-on-guidance/SKILL.md Outdated
Comment thread internal/agentkit/content/skills/forge-global/SKILL.md Outdated
Comment thread internal/agentkit/content/skills/always-on-guidance/SKILL.md

@sonupreetam sonupreetam left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Council (6 Divisor agents)

Verdict: REQUEST CHANGES — mechanical blockers only, no content findings.

Content restructuring is well-done: decision table for forge-global, Critical Safety section for always-on-guidance, drift detection tests. No documentation gaps (blog issue unbound-force/website#198 covers the series).

Findings

CRITICAL — findRepoRoot conflict with PR #56: PR #56 defines findRepoRoot(t *testing.T) string and this PR defines findRepoRoot() (string, error) — both in agentkit_test.go. Guaranteed compile error when both merge. Must rebase after #56 merges and adopt its signature.

LOW — Missing Closes #51: PR description should include Closes #51 for auto-closing the tracked issue.

LOW — Drift detection covers 2 of 7 skills: Consider extending TestSkillFiles_DriftDetection to all 7 skills in a follow-up.

Mechanical blockers

  • Needs rebase onto main (PR #54 merged, test file has shifted)
  • Must merge AFTER PR #56 to avoid findRepoRoot conflict

Merge order recommendation

Merge last (#54 already merged → #55#57#56#59). Rebase after #56 merges.

@jflowers

Copy link
Copy Markdown
Contributor Author

Addressing Review Council Findings (2nd review)

Thanks for the thorough second review council pass.

CRITICAL — findRepoRoot conflict with PR #56

Acknowledged. PR #56 is still open, so rebase is blocked until it merges. Will rebase onto main and adopt the findRepoRoot(t *testing.T) string signature from #56 once it lands. This PR should merge last per the recommended order.

LOW — Missing Closes #51

Closes #51 is already present in the PR description (end of the Summary section). No change needed.

LOW — Drift detection covers 2 of 7 skills

Agreed this is a reasonable follow-up. The current test covers the two skills modified in this PR. Extending to all 7 skills is tracked for a separate change to keep this PR focused.

Mechanical blockers

@jflowers
jflowers force-pushed the opsx/harden-skill-compression branch 2 times, most recently from 5c6b9c7 to 8909a6e Compare August 11, 2026 11:35
jflowers and others added 3 commits August 11, 2026 07:59
…n resilience

Restructure two embedded skill files to improve survival under DCP
context compression, addressing six specific vulnerabilities (unbound-force#51):

- Replace parallel do/don't lists with decision table in forge-global
- Inline TTL parameter into reservation step, add temporal ordering
- Add Critical Safety section in always-on-guidance for safety rules
- Move hivemind_find from last to first position in Tool Usage
- Split Code Quality, Testing, Error Handling into sub-headed groups
- Sync .opencode/skills/ copies with canonical embedded source

No semantic changes to any rules -- structural reorganization only.

Closes unbound-force#51

Assisted-by: claude-opus
Generated with AI assistance (claude-opus)
- always-on-guidance: Never -> NEVER force push to main (DR-002)
- forge-global: add (5-minute auto-release) parenthetical to TTL

Co-authored-by: claude-opus-4-6 <noreply@anthropic.com>
- TestAlwaysOnGuidance_StructuralHardening: verifies Critical Safety
  section positioning, RFC 2119 keywords, hivemind_find priority,
  and sub-header splits
- TestForgeGlobal_StructuralHardening: verifies decision table format,
  temporal markers, inlined TTL, and no standalone TTL step
- TestSkillFiles_DriftDetection: TC-007 drift detection comparing
  embedded files against .opencode/ scaffolded copies

Co-authored-by: claude-opus-4-6 <noreply@anthropic.com>

@yvonnedevlinrh yvonnedevlinrh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

APPROVE. All 6 issue #51 requirements are covered. Production changes are markdown-only with no semantic differences. CI passes.

Four findings noted — none blocking. Tracked in #70.

ID Severity Finding
F1/F10 MEDIUM Assertion (6) in TestForgeGlobal_StructuralHardening is a dead negative test — the triple-AND condition can never fire. Mitigated by assertion (4) already covering the TTL-inlined invariant positively.
F4 MEDIUM TestSkillFiles_DriftDetection name implies generic skill file coverage, implementation covers 2/7.
F2 LOW Drift detection split across two tests covering disjoint skill subsets; 4 skills uncovered.
F3 LOW t.Fatalf in loop body masks second-skill failures.

for _, line := range lines {
trimmed := strings.TrimSpace(line)
// Old format was a standalone step like "3. Set `ttl_seconds` to auto-release..."
if strings.HasPrefix(trimmed, "3.") && strings.Contains(trimmed, "ttl_seconds") && strings.Contains(trimmed, "auto-release") {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MEDIUM
The test iterates all lines looking for one that starts with "3." AND contains "ttl_seconds" AND contains "auto-release". The current forge-global SKILL.md step 3 reads:

3. FINALLY, coordinator can emergency release if workers fail: comms_release_all()

This line starts with "3." but does not contain "ttl_seconds", so the triple-AND condition can never be true. The test passes trivially — it's testing for the absence of something that's already structurally impossible given how the file was rewritten. It would still pass if someone reintroduced a 4. Set ttl_seconds... step (the old format used step 3, but a future author might use step 4). The assertion is coupled to the old numbering, not to the actual invariant ("no standalone TTL step exists").
A more robust check:

for _, line := range lines {
    trimmed := strings.TrimSpace(line)
    if strings.Contains(trimmed, "ttl_seconds") && strings.Contains(trimmed, "auto-release") && !strings.Contains(trimmed, "comms_reserve") {
        t.Error("forge-global: standalone TTL step should be removed (inlined into step 1)")
    }
}

This fires regardless of step number and regardless of whether the line is a numbered step at all.

Also
MEDIUM
The conditional at agentkit_test.go:1023:

if strings.HasPrefix(trimmed, "3.") && strings.Contains(trimmed, "ttl_seconds") && strings.Contains(trimmed, "auto-release") {

Tracing the input: text comes from content.ReadFile("content/skills/forge-global/SKILL.md"). The file's line starting with "3." is "3. FINALLY, coordinator can emergency release if workers fail: comms_release_all()". This line does not contain "ttl_seconds", so the branch body (the t.Error call) is dead code. The test would need a future regression that coincidentally uses "3." as the step number AND reintroduces both "ttl_seconds" and "auto-release" in the same line to ever trigger.

}
}

func TestSkillFiles_DriftDetection(t *testing.T) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MEDIUM
The function name TestSkillFiles_DriftDetection uses the plural generic "SkillFiles" (not "TwoSkillFiles" or "HardenedSkillFiles"). A new contributor reading this name would expect it to cover all embedded skill files. The skills slice at line 1037-1040 hardcodes only ["always-on-guidance", "forge-global"]. Meanwhile TestForgeCoordinationSkill_StructuralHardening separately covers forge-coordination. The remaining 4 skills (replicator-cli, testing-patterns, system-design, learning-systems) have no drift detection.
The doc comment (line 1030-1031) says "Verify embedded skill files match the .opencode/ scaffolded copies" — again generic, not qualified to a subset.
Either the name should be scoped (TestHardenedSkillFiles_DriftDetection) or the implementation should cover all skills.

Also
LOW
agentkit_test.go:894-904 already verifies byte-for-byte identity of the forge-coordination embedded vs .opencode/ copies. The new TestSkillFiles_DriftDetection at line 1029 covers always-on-guidance and forge-global but does not include forge-coordination — so the repo now has two independent drift-detection mechanisms that cover disjoint skill subsets. Neither covers all 7 skills. This isn't a bug, but the name TestSkillFiles_DriftDetection implies comprehensive drift detection for skill files generically. Anyone extending it to all 7 skills would introduce a duplicate assertion for forge-coordination.

embeddedPath := filepath.Join("content", "skills", skill, "SKILL.md")
embedded, err := content.ReadFile(embeddedPath)
if err != nil {
t.Fatalf("read embedded %s: %v", embeddedPath, err)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agentkit_test.go:1046 and 1052: Both ReadFile error handlers use t.Fatalf, which stops the entire test on the first skill that fails to read. If both skills have issues, only the first is reported. For a 2-element loop this is marginal, but t.Errorf + continue would be more informative. The drift comparison itself at line 1055 correctly uses t.Errorf.

@jflowers
jflowers merged commit 207e3e0 into unbound-force:main Aug 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Review 🏁

Development

Successfully merging this pull request may close these issues.

bug: forge-global and always-on-guidance skills contain compression-vulnerable decision logic and quality rules

4 participants