…overage
Ports five small items from the closed parallel PR #1185 into the
tolerant annotate argument resolution that landed in #1183 (#1182):
- Bug fix: the token probe tested the raw token against the URL regex,
but the pipeline strips the @ reference marker and wrapping quotes
first, so a multi-token 'annotate @https://example.com/page and
summarize it' probed to nothing and emitted the handoff instead of
opening the URL. The probe now unwraps with stripAtPrefix before the
regex and returns the unwrapped form (the pipeline re-strips
harmlessly). Tests cover @-prefixed and quote-wrapped URLs as
multi-token candidates.
- Test ports: absolute-path candidate, the wider plain-text set (.txt,
.yaml) guarding ANNOTATABLE_DOC_REGEX breadth, the scoped-package
literal-@ fallback against a real @scope/ directory, and the
whole-un-split-string preference over its own tokens ('Meeting
Notes.md' wins over a resolving 'Notes.md' token) covering
annotateInputNamesExistingTarget.
- Defensive scan: the strict-mode source-scan test now asserts the
annotate startup block gates tolerance on !strictAnnotate via
isStrictAnnotateInvocation, since an inverted gate cannot be
spawn-tested without starting a server.
- DRY: the strict predicate was defined twice (strict-annotate-result
exit-code helper and the index.ts tolerance bypass). Extracted
isStrictAnnotateInvocation with a StrictAnnotateFlags type; both
sites use it so the exit-code path and the tolerance bypass can
never drift. Behavior byte-identical; existing subprocess tests
unchanged.
- Docs: the tolerant-resolution section now cites #872 (commit
aac5aac) for why the bang prefix is deliberate and states that
argument-shape issues belong in the CLI's resolution, not the skill
templates.
Refs #1185, #1182
Co-authored-by: Josh Nichols <josh.nichols+agent@gusto.com>
Ports five small items from @technicalpickles' closed parallel implementation (#1185) into the tolerant annotate argument resolution that landed via #1183 (#1182). Full credit to @technicalpickles for catching the URL-probe bug and the coverage gaps; a comparison pass of the two implementations surfaced these.
1. Bug fix: wrapped URLs were not URL candidates
probeAnnotateTokentested the raw token against/^https?:\/\//i, but the resolution pipeline strips the@reference marker and wrapping quotes before its own URL check (stripAtPrefixunwraps both). So the multi-token invocationprobed to zero candidates and emitted the tier-3 handoff instead of opening the URL. The probe now unwraps with
stripAtPrefixbefore the regex and returns the unwrapped form; the pipeline re-strips harmlessly. Verified by unit tests (@-prefixed and quote-wrapped URLs, single and multi-token) and a manual smoke: the invocation above now reachesFetching: https://example.com(tier 1), whileannotate the aim docstill hands off and a strict typo still exits 2.2. Test ports
Added to
packages/shared/annotate-target.test.tsfrom their suite's coverage: absolute paths resolve as candidates; the wider plain-text set (.txt,.yaml) resolves, guardingANNOTATABLE_DOC_REGEXbreadth (which the probe's no-walk cheapness argument relies on); the scoped-package literal-@fallback resolves against a real@scope/directory (the strip half was covered, the fallback half was not); and the whole un-split string is preferred over its own tokens (Meeting Notes.mdwins over a resolvingNotes.mdtoken), coveringannotateInputNamesExistingTargetin the OpenCode/Pi pre-pass direction.3. Defensive source scan
The strict bypass cannot be spawn-tested in its inverted form (tolerance applying in strict mode would require a live server to observe). The existing source-scan test in
apps/hook/server/strict-annotate-result.test.tsnow also asserts the annotate startup block gates tolerance on!strictAnnotatecomputed viaisStrictAnnotateInvocation, so an inverted or bypassed gate fails the scan.4. DRY: single strict predicate
The strict predicate (
requireApproval || !!resultFile) was defined twice: inannotateStartupFailureExitCodeand inline inindex.tsfor the tolerance bypass. Adopted their factoring: aStrictAnnotateFlagstype plusisStrictAnnotateInvocationinstrict-annotate-result.ts, used by both the exit-code helper and the bypass, so the two paths can never drift. Behavior is byte-identical; the existing subprocess tests inannotate-cli.test.tspass unchanged.5. Docs
The AGENTS.md tolerant-resolution section now cites #872 (commit
aac5aacb, "restore/plannotator-*bash execution on Claude Code") for why the bang prefix is deliberate, and states that argument-shape issues belong in the CLI's resolution rather than the skill templates.Verified
bun run typecheckgreen; fullbun testgreen (2709 pass, 0 fail);bash apps/pi-extension/vendor.shregenerates cleanly.annotate @https://example.com and summarize --no-jinaresolves the URL (tier 1, fetch reached);annotate the aim docstill hands off with exit 0;annotate nope-not-here.md --gate --json --require-approvalstill exits 2 withFile not foundon stderr.Refs #1185, #1182. Co-authored with Josh Nichols (@technicalpickles).