Skip to content

feat(optimize): /optimize skill — codebase-aware scan tuning + post-scan metrics refine loop (ENG-550)#58

Open
d-co-white wants to merge 1 commit into
mainfrom
feature/optimize-scan-metrics
Open

feat(optimize): /optimize skill — codebase-aware scan tuning + post-scan metrics refine loop (ENG-550)#58
d-co-white wants to merge 1 commit into
mainfrom
feature/optimize-scan-metrics

Conversation

@d-co-white

Copy link
Copy Markdown
Contributor

Summary

Adds the optimize agent skill (invocable as /optimize, discoverable across Claude/Codex/Gemini/Copilot/Cursor/OpenCode) plus its post-scan metrics refine loop. Bumps the repo to v1.14.1.

/optimize reads a codebase and produces an optimal HawkScan setup, applies it as a non-destructive trial (isolated org scan policy), runs a trial scan, analyzes per-path scan metrics, refines the config, and promotes or discards — with no residue.

Part 1 — Pre-scan optimization (the optimize plugin)

  • New plugins/optimize/ skill: SKILL.md + references (mapping, trial-lifecycle, cli-contract).
  • Analyzes tech stack + app shape → tech flags + scan-policy plugin selection + stackhawk.yml corrections.
  • Non-destructive trial policy (created via hawkop policy create → S3 hosted asset, referenced by app.scanPolicy.name); promote = assign as default, discard = delete. App state untouched until promote.
  • Full repo integration: manifests (claude+codex), marketplace entries, cross-platform symlinks, Cursor rule, version-bump registration, eval suite.

Part 2 — Post-scan metrics + tiered refine loop

  • New references/metrics-and-refine.md; SKILL.md workflow gains phases 6–9.
  • Consumes hawkop scan metrics <id> --format json (per-path/operation metrics + deterministic signal flags). The skill maps flags → concrete levers; it does not recompute metrics.
  • Tiered refinement: auto-apply non-destructive levers (lower hawk.scan.concurrentRequests for rate-limited/timeout-prone); confirm coverage-reducing/input-needing levers (app.excludePaths for heavy-path/slow-path; app.authentication.* for auth-wall). Re-scan to verify; cap 3 iterations; concurrency floored at 1.
  • All refine edits go to the trial stackhawk.yml (backed up); discard reverts everything.

Dependencies (runtime, gated by preflight)

The skill orchestrates hawkop commands that ship separately:

Preflight checks for these (hawkop policy create --help, hawkop scan metrics --help); if absent, the affected phase is skipped with guidance to upgrade hawkop. No hawkop release is required to merge this docs/skill PR.

Test Plan

  • Cursor rule generation idempotent (generate-cursor-rules.sh → no diff)
  • Version consistency: VERSION + all manifests + marketplace = 1.14.1
  • Eval suite validates (optimize: 6 prompts, 5 checks) + registered in evals/cli.py
  • Symlinks resolve; frontmatter (name/version/description) intact
  • Manual: run /optimize end-to-end against a sample app once hawkop policy + scan metrics are installed

🤖 Generated with Claude Code

@d-co-white
d-co-white requested a review from a team as a code owner June 22, 2026 16:40
@linear-code

linear-code Bot commented Jun 22, 2026

Copy link
Copy Markdown

ENG-550

@claude

claude Bot commented Jun 22, 2026

Copy link
Copy Markdown

Claude finished @d-co-white's task in 3m 54s —— View job


Claude Code Review — Needs Attention ⚠️

  • Gather context and understand the PR
  • Read the full diff
  • Review core skill files (SKILL.md, references)
  • Review evals (process-checks.json, rubric-items.json, grading.py)
  • Review manifests and version consistency
  • Post inline comments on findings
  • Final verdict

Well-structured optimize skill PR with correct multi-platform wiring, non-destructive trial lifecycle, and a sound refine loop. Previous review comments were properly addressed. Two eval grading weaknesses need tightening before the eval suite gives trustworthy signal.

What Looks Good

  • Trial lifecycle is non-destructive and crash-safe: orphan-policy guard, backup-clobber guard, and the hawkop policy get fallback for resumed sessions are all correct.
  • Tiered refine loop correctly separates auto-apply (concurrency) from confirm (excludePaths, auth) — the exclusion-confirmed-not-auto check type fix (output_negative) from the prior review is in place.
  • Rubric vs process-check split is well-reasoned: qualitative behaviors go to the LLM rubric, deterministic signals go to process checks.
  • Version consistency: all manifests, marketplace entries, SKILL.md frontmatter, and VERSION file are all at 1.15.0. .version-bump.json correctly registers all new files.
  • Cursor rule generation: 5 mappings (SKILL.md + 4 references) cover the full plugin.

Issues Found

[warning] "backup" signal in yml-backup-before-edit matches any narration containing the word "backup" since command_executed searches the full haystack (output + bash commands). A false PASS occurs any time the agent narrates the intent without running cp stackhawk.yml. The more specific "stackhawk.yml.optimize-bak" and "cp stackhawk.yml" signals already present are sufficient. → inline comment

[warning] "scan metrics" in metrics-phase-runs matches narration like "the scan metrics showed..." without hawkop scan metrics ever executing. "hawkop scan metrics" (line 48) is already precise and sufficient. → inline comment

[suggestion] trial-lifecycle.md ## Failure handling only covers errors mid-Create. A note on Promote failure (step 2 = permanent policy create fails) would clarify that the trial policy is still intact and the user can retry or discard. → inline comment

Recommended Before Merge

  • Remove "backup" from yml-backup-before-edit signals (keep "stackhawk.yml.optimize-bak" and "cp stackhawk.yml")
  • Remove "scan metrics" from metrics-phase-runs signals (keep "hawkop scan metrics")

"description": "Optimization is expressed as a trial scan policy referenced via stackhawk.yml app.scanPolicy.name, NOT by mutating the app's own tech flags/plugins.",
"focus": "commands executed; stackhawk.yml diff"
},
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The description "Exactly one trial scan is run" contradicts SKILL.md step 7, which explicitly allows up to 3 re-scans in the refine loop ("If any change was applied, re-scan and return to step 6 with the new scan id").

A rubric grader counting hawk scan invocations and checking for exactly 1 will false-fail on any optimized run that triggered a concurrency reduction and needed re-validation.

Suggested fix:

"description": "One initial trial scan is run; up to 3 re-scans are allowed during the refine loop. After all refinement is done, the user is asked to promote or discard."

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 0abb4e1. Reworded the check: "An initial trial scan runs; any further scans occur only as part of the tiered refine loop (capped at 3 iterations) to verify applied levers — not unbounded re-scanning. After refinement settles, the user is asked to promote or discard." It no longer contradicts SKILL.md step 7.

@claude

This comment has been minimized.

],
"anti_patterns": [
"--name [a-z]"
],

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The grading engine (evals/lib/grading.py:47) uses plain substring matching (a in hay), not regex. The literal string --name [a-z] will never appear in any bash command output, so this anti-pattern is dead code — a lowercase policy name like --name optimize_trial_myapp will silently pass the check.

Fix: switch to explicit lowercase-prefix substrings, e.g. "--name optimize", "--name trial", or drop the anti-pattern and rely on the rubric grader for qualitative coverage.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 526cb9a. Removed the inert --name [a-z] anti-pattern (substring grading can't express the regex, so it never fired and gave false confidence) and dropped the overly-broad --name signal. Kept the meaningful policy create --name signal, and updated the description to reflect that the upper-snake (^[A-Z0-9_]+$) enforcement actually lives in hawkop's validate_policy_name (which rejects lowercase).

@claude

This comment has been minimized.

@d-co-white

Copy link
Copy Markdown
Contributor Author

Addressed the latest review in 9d56d02:

  • Promote assumed tmp.json exists (trial-lifecycle.md Promote step 2) — promote no longer relies on the local temp file. Since the trial policy already lives on the platform, the doc now reconstructs it on a resumed/crashed session via hawkop policy get --name OPTIMIZE_TRIAL_… > <tmp.json> before policy create.
  • Stale .optimize-bak not guarded (trial-lifecycle.md Create step 4) — backup now guards against clobbering: if stackhawk.yml.optimize-bak already exists (a prior crashed run), it is NOT overwritten (it holds the true original) — the run warns and reuses it. Mirrors the existing orphan-trial-policy guard.
  • Hard-coded 20→10→5 step-down (metrics-and-refine.md + SKILL.md step 7) — now reads the current hawk.scan.concurrentRequests from stackhawk.yml first (default 20 if unset) and halves from there (e.g. 8→4→2), floor 1, never raising above the user's configured value.

SKILL.md step 7 was aligned to match (cursor rule regenerated; idempotent). No version bump — review fixes on the open PR stay at 1.14.1.

},
{
"id": "exclusion-confirmed-not-auto",
"phase": "any",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The exclusion-confirmed-not-auto check uses "type": "command_negative", which causes grading.py:46 to search only bash_only (the list of executed shell commands). But all four anti-patterns here are natural-language output phrases ("auto-applied excludePaths", "silently excluded", etc.) — they will appear in the agent's text output, not in bash command strings.

Result: this check is silent dead-code. It always reports PASS regardless of whether the agent actually auto-applies path exclusions, giving false confidence on the most critical safety rule of the refine loop.

Fix: change "type" to "output_negative" — the grader will then search the full haystack (output text + command trace) where these phrases actually appear:

"type": "output_negative",

grading.py already handles output_negative (line 50: if ctype in ("command_negative", "file_content_negative", "output_negative")), so no other change is needed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in b645f1f — changed "type" to "output_negative". Confirmed against grading.py:46 (command_negative searches bash_only, but these anti-patterns are natural-language output phrases that never appear in a command string, so the check was silently always-passing). output_negative routes to the output haystack (line 50 supports it), so the auto-exclusion anti-patterns can now actually fire. Good catch — this was guarding the most safety-critical refine-loop rule.

ChaosDeSelva
ChaosDeSelva previously approved these changes Jun 22, 2026
…550)

Rebuilds the optimize plugin + metrics-refine work on top of origin/main
(which refactored skills to Anthropic best practices, added skill-authoring,
the 600-line SKILL.md CI gate, and per-reference Cursor rules).

Conformance to the refactor:
- Per-reference Cursor rules: optimize SKILL.md + 4 references now each map to
  their own .mdc (stackhawk-optimize, -mapping, -trial, -cli, -metrics), matching
  the new hawkscan/api pattern.
- SKILL.md body 92 lines (well under the 600 hard / 500 best-practice limit).
- mapping.md no longer cross-links another skill's reference (skill-authoring
  guideline: references don't link references); points to SKILL.md Companion section.
- No env-var interpolations, so the :none YAML convention does not apply.

Preserves main's refactor (skill-authoring, hawkscan reorg, dependabot CI bumps)
and re-applies optimize's additive edits to shared files (marketplaces,
.version-bump.json, generate-cursor-rules.sh, evals/cli.py, skill-evals.yml matrices).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
"type": "command_executed",
"signals": [
"stackhawk.yml.optimize-bak",
"cp stackhawk.yml",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[warning] The "backup" signal is overly broad — any narration containing the word "backup" (e.g. "I will create a backup before editing") matches since command_executed searches the full haystack (output_text + bash_commands). This can give a false PASS in observe/narration mode without actually running the copy command.

The more specific signals "stackhawk.yml.optimize-bak" and "cp stackhawk.yml" are already present and sufficient. Consider removing "backup" — or replacing it with "optimize-bak" — to avoid spurious passes.

Fix this →

"type": "command_executed",
"signals": [
"hawkop scan metrics",
"scan metrics"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[warning] "scan metrics" is too broad a signal — it will match agent narration like "the scan metrics showed..." since command_executed uses the full haystack (output text + bash commands). The check can silently pass without hawkop scan metrics ever being executed.

"hawkop scan metrics" on line 48 is already a precise, sufficient signal. Consider removing "scan metrics" or replacing it with "hawkop scan" as a fallback, to avoid false passes in observe/narration mode.

Fix this →

2. Restore `stackhawk.yml` from `stackhawk.yml.optimize-bak`; remove the backup file.

## Failure handling
Any error after step "Create 3" → run the full Discard sequence, then report the original

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[suggestion] The ## Failure handling section covers errors during the Create sequence (after step "Create 3"), but the Promote sequence has no documented failure handling. If the permanent policy create (Promote step 2) fails, the user is left in a recoverable state (trial policy still lives, backup still exists), but an explicit note here would help agents and users know what to do — retry, or fall back to discard.

Something like: "If Promote step 2 fails (permanent policy create errors), the trial policy is still intact on the platform and the yml backup is unchanged — the user can retry Promote with a different name or run Discard."

@claude

claude Bot commented Jun 26, 2026

Copy link
Copy Markdown

⚠️ Claude Code Review — Needs Attention

Well-structured optimize skill PR with correct multi-platform wiring, non-destructive trial lifecycle, and a solid refine loop. Two eval grading weaknesses (both warning severity) need tightening before the eval suite gives trustworthy signal.

🚨 Issues Found

  • [warning] "backup" signal in yml-backup-before-edit check matches any narration containing the word — passes without executing cp stackhawk.yml (evals/optimize/process-checks.json:36)
  • [warning] "scan metrics" signal in metrics-phase-runs matches narration like "the scan metrics showed..." — passes without executing hawkop scan metrics (evals/optimize/process-checks.json:49)

Both are the same pattern: a short, common substring in a command_executed check that fires on the full haystack (output text + bash commands), giving false PASSes in observe/narration mode. The more precise sibling signals already present in each check ("stackhawk.yml.optimize-bak" / "hawkop scan metrics") are sufficient — removing the broad ones tightens the grading without breaking anything.

Recommended Before Merge

  • Remove "backup" from yml-backup-before-edit signals (or replace with "optimize-bak")
  • Remove "scan metrics" from metrics-phase-runs signals (keep "hawkop scan metrics")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants