fix(kyberforge): resolve PR #144 review and audit round 2
- factory-audit: ./ and bare/absolute script checks scoped to command position (no false FAILs on ./src or printf); hook sources limited to .apm/hooks or package-root hooks/; Kiro-aware lowercase events; unfilled template placeholders FAIL; repo-only instructions FAIL at any scope; Vale description FAIL documented; bats 367 -> 378 - primitive-author: split-quote/spaced paths and handler-less entries promoted to Must; Step 4.2 renders into a scratch consumer instead of a no-op dry run; dispatch and gate hand-off trimmed - apm-workflow 1.0.2: mutual boundary with primitive-author - forge: no double package bump; gotcha wording - skill-author: create keeps seeded 0.1.0 (ADR-0022); portable, retry-safe new-skill.sh; template and flow consistency fixes - hook docs: cite the ADR-0019 correction; guard caveat Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KkT7RSDwDbmrM9T34b6sTi
This commit is contained in:
@@ -95,11 +95,28 @@ teardown() {
|
||||
assert_output --partial "naked settings-slice shape"
|
||||
}
|
||||
|
||||
@test "hook: an all-lowercase event is a FAIL" {
|
||||
write_hook hooks.json '{"hooks":{"stop":[{"hooks":[{"type":"command","command":"true"}]}]}}'
|
||||
@test "hook: an all-lowercase event no target maps is a FAIL" {
|
||||
write_hook hooks.json '{"hooks":{"pretooluse":[{"hooks":[{"type":"command","command":"true"}]}]}}'
|
||||
run bash "$SCRIPT" "$PKG/.apm/hooks/hooks.json"
|
||||
assert_failure 1
|
||||
assert_output --partial "event 'stop' is all-lowercase"
|
||||
assert_output --partial "event 'pretooluse' is all-lowercase — no target this package deploys to maps it"
|
||||
}
|
||||
|
||||
@test "hook: lowercase stop is a SUGGESTION for every target, clean for Kiro only, a FAIL without Kiro" {
|
||||
write_hook hooks.json '{"hooks":{"stop":[{"hooks":[{"type":"command","command":"true"}]}]}}'
|
||||
run bash "$SCRIPT" "$PKG/.apm/hooks/hooks.json"
|
||||
assert_success
|
||||
assert_output --partial "SUGGESTION event 'stop' is all-lowercase — only Kiro renames it"
|
||||
|
||||
printf 'name: test-package\nversion: 0.1.0\ntargets: [kiro]\n' > "$PKG/apm.yml"
|
||||
run bash "$SCRIPT" "$PKG/.apm/hooks/hooks.json"
|
||||
assert_success
|
||||
refute_output --partial "all-lowercase"
|
||||
|
||||
printf 'name: test-package\nversion: 0.1.0\ntargets: [claude, copilot]\n' > "$PKG/apm.yml"
|
||||
run bash "$SCRIPT" "$PKG/.apm/hooks/hooks.json"
|
||||
assert_failure 1
|
||||
assert_output --partial "event 'stop' is all-lowercase — no target this package deploys to maps it"
|
||||
}
|
||||
|
||||
@test "hook: camelCase userPromptSubmit in a Claude-shaped file is a FAIL; mapped sessionStart is not" {
|
||||
@@ -338,6 +355,101 @@ teardown() {
|
||||
assert_output --partial "script 'scripts/gone.sh' does not exist"
|
||||
}
|
||||
|
||||
@test "hook: a ./ argument outside command position is at most a SUGGESTION (npx prettier --check ./src)" {
|
||||
write_hook hooks.json '{"hooks":{"Stop":[{"hooks":[{"type":"command","command":"npx prettier --check ./src","timeout":5}]}]}}'
|
||||
run bash "$SCRIPT" "$PKG/.apm/hooks/hooks.json"
|
||||
assert_success
|
||||
refute_output --partial "FAIL"
|
||||
assert_output --partial "SUGGESTION argument './src' matches apm's ./ script pattern"
|
||||
}
|
||||
|
||||
@test "hook: a printf escape after a script is not a missing-script FAIL (printf '.\n')" {
|
||||
write_hook hooks.json '{"hooks":{"Stop":[{"hooks":[{"type":"command","command":"\"${PLUGIN_ROOT}/.apm/hooks/scripts/check.sh\" && printf '"'"'.\\n'"'"'","timeout":5}]}]}}'
|
||||
run bash "$SCRIPT" "$PKG/.apm/hooks/hooks.json"
|
||||
assert_success
|
||||
refute_output --partial "FAIL"
|
||||
refute_output --partial "does not exist"
|
||||
}
|
||||
|
||||
@test "hook: a ../ argument outside command position is a SUGGESTION; in command position a FAIL" {
|
||||
write_hook hooks.json '{"hooks":{"Stop":[{"hooks":[{"type":"command","command":"git -C ../sibling status","timeout":5}]}]}}'
|
||||
run bash "$SCRIPT" "$PKG/.apm/hooks/hooks.json"
|
||||
assert_success
|
||||
refute_output --partial "FAIL"
|
||||
assert_output --partial "SUGGESTION argument '../sibling'"
|
||||
|
||||
write_hook hooks.json '{"hooks":{"Stop":[{"hooks":[{"type":"command","command":"python3 ../tool","timeout":5}]}]}}'
|
||||
run bash "$SCRIPT" "$PKG/.apm/hooks/hooks.json"
|
||||
assert_failure 1
|
||||
assert_output --partial "starts with ../"
|
||||
}
|
||||
|
||||
@test "hook: a non-command-position ./ match is still a FAIL with a script extension or when it is a package directory" {
|
||||
write_hook hooks.json '{"hooks":{"Stop":[{"hooks":[{"type":"command","command":"cat ./gone.sh","timeout":5}]}]}}'
|
||||
run bash "$SCRIPT" "$PKG/.apm/hooks/hooks.json"
|
||||
assert_failure 1
|
||||
assert_output --partial "script 'gone.sh' does not exist in the package"
|
||||
|
||||
write_hook hooks.json '{"hooks":{"Stop":[{"hooks":[{"type":"command","command":"npx prettier --check ./scripts","timeout":5}]}]}}'
|
||||
run bash "$SCRIPT" "$PKG/.apm/hooks/hooks.json"
|
||||
assert_failure 1
|
||||
assert_output --partial "script 'scripts' exists in the package but is not a regular file"
|
||||
}
|
||||
|
||||
@test "hook: a quoted \${PLUGIN_ROOT} path followed by arguments is not a spaced path (bash -c \"…/bin/tool --config conf.sh\")" {
|
||||
mkdir -p "$PKG/bin"
|
||||
printf '#!/usr/bin/env bash\nexit 0\n' > "$PKG/bin/tool"
|
||||
chmod +x "$PKG/bin/tool"
|
||||
write_hook hooks.json '{"hooks":{"Stop":[{"hooks":[{"type":"command","command":"bash -c \"${PLUGIN_ROOT}/bin/tool --config conf.sh\"","timeout":5}]}]}}'
|
||||
run bash "$SCRIPT" "$PKG/.apm/hooks/hooks.json"
|
||||
assert_success
|
||||
refute_output --partial "FAIL"
|
||||
}
|
||||
|
||||
@test "hook: a bare relative or absolute script after an interpreter is a FAIL; as a later argument it is not" {
|
||||
write_hook hooks.json '{"hooks":{"Stop":[{"hooks":[{"type":"command","command":"bash scripts/check.sh","timeout":5}]}]}}'
|
||||
run bash "$SCRIPT" "$PKG/.apm/hooks/hooks.json"
|
||||
assert_failure 1
|
||||
assert_output --partial "script 'scripts/check.sh' is a bare relative path"
|
||||
|
||||
write_hook hooks.json '{"hooks":{"Stop":[{"hooks":[{"type":"command","command":"bash /opt/x.sh","timeout":5}]}]}}'
|
||||
run bash "$SCRIPT" "$PKG/.apm/hooks/hooks.json"
|
||||
assert_failure 1
|
||||
assert_output --partial "script '/opt/x.sh' is an absolute path"
|
||||
|
||||
write_hook hooks.json '{"hooks":{"Stop":[{"hooks":[{"type":"command","command":"/usr/bin/env python3 /opt/x","timeout":5}]}]}}'
|
||||
run bash "$SCRIPT" "$PKG/.apm/hooks/hooks.json"
|
||||
assert_failure 1
|
||||
assert_output --partial "script '/opt/x' is an absolute path"
|
||||
|
||||
write_hook hooks.json '{"hooks":{"Stop":[{"hooks":[{"type":"command","command":"echo scripts/check.sh /opt/x.sh","timeout":5}]}]}}'
|
||||
run bash "$SCRIPT" "$PKG/.apm/hooks/hooks.json"
|
||||
assert_success
|
||||
refute_output --partial "FAIL"
|
||||
}
|
||||
|
||||
@test "hook: a hook file under apm's deployed output is a FAIL naming the source location" {
|
||||
mkdir -p "$PKG/.github/hooks"
|
||||
printf '%s\n' '{"hooks":{"Stop":[{"hooks":[{"type":"command","command":"true","timeout":5}]}]}}' > "$PKG/.github/hooks/p.json"
|
||||
run bash "$SCRIPT" "$PKG/.github/hooks/p.json"
|
||||
assert_failure 1
|
||||
assert_output --partial "is apm's deployed output (.github/hooks/)"
|
||||
assert_output --partial ".apm/hooks/"
|
||||
|
||||
mkdir -p "$TMPDIR/loose/hooks"
|
||||
printf '%s\n' '{"hooks":{"Stop":[{"hooks":[{"type":"command","command":"true","timeout":5}]}]}}' > "$TMPDIR/loose/hooks/x.json"
|
||||
run bash "$SCRIPT" "$TMPDIR/loose/hooks/x.json"
|
||||
assert_failure 1
|
||||
assert_output --partial "is no package source"
|
||||
}
|
||||
|
||||
@test "hook: an unedited primitive-author hook template is an unfilled-placeholder FAIL" {
|
||||
cp "$REPO_ROOT/plugins/kyberforge/.apm/skills/primitive-author/assets/templates/hook.json.template" "$PKG/.apm/hooks/hooks.json"
|
||||
run bash "$SCRIPT" "$PKG/.apm/hooks/hooks.json"
|
||||
assert_failure 1
|
||||
assert_output --partial "unfilled template placeholder 'FILL_IN_'"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Instructions
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -445,6 +557,13 @@ applyTo: "**/*.py"' 'body'
|
||||
assert_output --partial "is a hardlink"
|
||||
}
|
||||
|
||||
@test "instruction: an unedited primitive-author template is an unfilled-placeholder FAIL" {
|
||||
cp "$REPO_ROOT/plugins/kyberforge/.apm/skills/primitive-author/assets/templates/name.instructions.md.template" "$PKG/.apm/instructions/name.instructions.md"
|
||||
run bash "$SCRIPT" "$PKG/.apm/instructions/name.instructions.md"
|
||||
assert_failure 1
|
||||
assert_output --partial "unfilled template placeholder 'FILL IN'"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Prompts
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -591,6 +710,13 @@ $(printf 'line\n%.0s' $(seq 1 80))
|
||||
assert_output --partial "is a hardlink"
|
||||
}
|
||||
|
||||
@test "prompt: an unedited primitive-author template is an unfilled-placeholder FAIL" {
|
||||
cp "$REPO_ROOT/plugins/kyberforge/.apm/skills/primitive-author/assets/templates/name.prompt.md.template" "$PKG/.apm/prompts/name.prompt.md"
|
||||
run bash "$SCRIPT" "$PKG/.apm/prompts/name.prompt.md"
|
||||
assert_failure 1
|
||||
assert_output --partial "unfilled template placeholder 'FILL IN'"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Never ran (exit 2)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user