fix: audit follow-ups — batch 1.5, OpenCode spec-workflow port (Option A), tollgate v2 Stop gate#67
Merged
Merged
Conversation
hapo-nghialuu
force-pushed
the
fix/audit-batch-1
branch
from
July 17, 2026 04:08
4af877c to
1fc0ced
Compare
… changelog Review findings on PR #66 (self-review): - video-analysis.md / audio-processing.md still carried gemini-3-pro-preview and gemini-1.5-flash; model sections were also duplicated after the bulk rename — collapsed to a single gemma-4-31b-it recommendation pointing at runtime.json. - Root README and package README still advertised hapo:generate-graph and listed impact-analysis as bundled (package README ships in the npm tarball). - CHANGELOG [Unreleased] and docs/project-changelog.md now document the batch including the breaking skill removal.
parseNodeTestCount anchors on line-start 'ℹ tests N'; when the child inherits a color-forcing env the ANSI prefix breaks the match and the suite false-fails with NO_TESTS despite all tests passing. Spawn test children with NO_COLOR=1 / FORCE_COLOR=0.
…ins (Option A)
Closes the spec-workflow enforcement gap on OpenCode. Both plugins were
independently verified with live smoke tests on opencode 1.17.15:
- spec-state.ts injects the tollgate via chat.message. Parts pushed onto
output.parts MUST be schema-complete (id/sessionID/messageID) — the
original bare {type,text} part failed OpenCode's durable-part schema and
crashed every user turn ('invalid user part before save'); fixed and
verified end-to-end (tollgate text reaches the model).
- task-scaffold-guard.ts blocks write/apply_patch on task files, and
additionally gates edit on non-existent task files: OpenCode's edit can
CREATE files (unlike Claude's Edit), a bypass proven live. Edit on an
existing stub stays allowed. Existence checks resolve the specs/ suffix
against the plugin directory (tool paths may be sandbox-virtual).
- Block message no longer advertises the runtime.json escape hatch: the
smoke test caught the model writing scaffold_guard:false itself and
disabling the guard. The hatch stays functional for humans.
- session.ts compaction banner + AGENTS.md now map Claude-only tools to
OpenCode built-ins (AskUserQuestion->question, TodoWrite->todowrite,
Task->agent/subtask).
- agent.cjs remains unported (documented: low ROI, unreliable surface).
- Port audit + plugin contract docs updated with the verified findings.
…odel The OpenCode smoke test proved the self-disarm vector: shown the override line in the block message, the model wrote runtime.json with scaffold_guard:false and bypassed the guard instead of scaffolding. The Claude hook printed the same line — removed. The escape hatch remains functional and documented for humans.
Owner-local project preferences, split out of the feature commit for a clean history.
hapo-nghialuu
force-pushed
the
fix/audit-batch-1
branch
from
July 17, 2026 04:58
1fc0ced to
197a04b
Compare
…list in .env.example
…on newly-done tasks
This was referenced Jul 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up train to the 2026-07 full-package audit (
docs/audit-cafekit-vs-claude-code-2026-07.md, run against v0.13.2). Batch 1 (9 fixes) merged in #66; hook hardening merged in #65. This PR carries four workstreams, 14 commits, each independently revertable. Branch is rebased ondevafter both merges; the full self-test suite passes at 150 tests on the final tree.A. Batch-1 leftover cleanup (
a705f98,71f6b45)generate-graph/impact-analysisskills and stale Gemini model IDs missed by fix: audit batch 1 — validator, installer, and payload fixes #66 (READMEs, ai-multimodal references, changelog).run-skill-self-tests.mjsanchor on line starts; ANSI color prefixes fromFORCE_COLORenvironments broke them into falseNO_TESTS. Child processes now run withNO_COLOR=1, FORCE_COLOR=0.B. Audit batch 1.5 — items #10/#11/#13 (
cb05ace,f963bff,937fa5c,6dfdb65)pdf/pptx/docx/xlsxare adapted Anthropic stock skills (theirLICENSE.txtis Anthropic's) but claimedauthor: haposoft. Frontmatter now creditsAnthropic, PBC — adapted by Haposoft. License files untouched.session.tsinstructedAskUserQuestion— a Claude-only tool thatAGENTS.md:85itself declares unavailable in OpenCode. The banner now tells the agent to ask the user directly in chat (same safety intent).LICENSE.txtthat does not exist. Provenance grep (anthropic→ 0 hits) confirms it is Haposoft-authored →license: MIT, matching the other authored skills. No license file fabricated.C. OpenCode spec-workflow port, Option A (
dc74f1e,41de4d0,256f44b,0ea97bc)Closes 2 of the 3 enforcement hooks the audit flagged as missing from the OpenCode runtime:
plugins/spec-state.ts— tollgate reminder viachat.message, pushing a schema-complete synthetic text part (id+sessionID+messageIDrequired; a bare part crashes the turn — verified on opencode 1.17.15). Same state-change fingerprint gate as the Claude hook. Escape hatchspec.tollgate: false.plugins/task-scaffold-guard.ts— blocks hand-written task files ontool.execute.before. Covers OpenCode-specific creation vectors the Claude hook never needed:apply_patch(*** Add File:scan, defensive) andediton a non-existent task file (OpenCode'seditcan create files, unlike Claude's Edit). Sandbox-virtual paths resolved against the plugindirectory.runtime.jsonoverride, the model simply wrote the override and disarmed the guard. Block messages no longer mention the hatch; it stays functional for humans and is documented indocs/opencode-hook-port-audit.mdonly.agent.cjsport explicitly dropped (unreliable subagent surface, low ROI) — decision recorded in the port audit doc.D. Tollgate v2 — Stop-gate completion enforcement (
6df8473,80b1ae0,74ca18c)Audit §3.4.1: the per-prompt tollgate was a reminder, not a barrier — the model could mark tasks
donewith no verification evidence. Enforcement now moves to the turn boundary:hooks/spec-gate.cjs(Stop hook, registered first on Stop). When a turn ends with newly-done tasks in the active spec'stask_registry, each must carry a verification receipt: task-mdStatus: done(a), an Evidence section (all 3 heading aliases) (b) containing no{{...}}placeholders and at least a fenced block or PASS/FAIL/exit-code line (c), andcompleted_atset (d). Violations emit{"decision":"block","reason":…}listing each failing task and the exact fix — the assistant must repair before it can end the turn.stop_hook_activeloop guard; first run seeds the status cache without blocking (legacy specs are never gated retroactively); failing tasks are held at their old cache status so the gate re-fires on the next Stop; escape hatchspec.completion_gate: false(missing key → ON); crash-wrapper fail-open.spec-state.cjsslimmed: the bilingual ALL-CAPS tollgate wall is gone — state-change turns get a ≤7-line neutral summary; unchanged turns keep the one-liner. Hard enforcement now lives on Stop, so the loud prompt no longer pays its context cost.runtime.jsontemplate documentsspec.{scaffold_guard, completion_gate};rules/state-sync.mddescribes the gate; 7 new behavioral tests inhooks/__tests__/spec-gate.test.js(subprocess harness from fix(hooks): harden env escaping and privacy symlink resolution #65).Behavior changes at a glance
donetaskwrite/apply_patch/edit-create)chat.message)haposoftAnthropic, PBC — adapted by HaposoftVerification
npm test(packages/spec): PASS — 150 tests executed (143 baseline after fix(hooks): harden env escaping and privacy symlink resolution #65/fix: audit batch 1 — validator, installer, and payload fixes #66 + 7 new spec-gate tests), re-run on the final rebased tree.node --test hooks/__tests__/spec-gate.test.js: 7/7 (block-no-receipt, allow-with-receipt, no-active-spec,stop_hook_activeloop guard, first-run seeding, escape hatch, placeholder rejection).grep -cE "URGENT|BẮT BUỘC|CẤM" hooks/spec-state.cjs→ 0.Known follow-ups (non-blocking)
spec.completion_gate, OpenCode usesspec.tollgate;tollgateis not listed in the shippedruntime.jsontemplate. Unify or document.spec-state.tspreserves the full URGENT block. Defensible — OpenCode has no Stop-gate equivalent, so the loud prompt is its only completion control — but the port-audit doc should state that rationale explicitly..opencode/plugins/.logs/cache dir should be confirmed covered by the installed.opencode/.gitignore.spec-state.cjs: only the firstin_progressspec is gated per turn (pre-existing limitation, now shared by two hooks).Upgrade path
Existing installs pick everything up on
npx @haposoft/cafekit --upgrade: the settings merge appendsspec-gate.cjsto the existing Stop entry (per-command merge shipped in #66), the manifest ships the new hook, and the first-run cache seed guarantees no retroactive blocking on in-flight specs.