Repository navigation
v0.7.0
Three checks on what the next agent will read and on whether the change is tested. The prompt-injection scan, signals
PI01 to PI05 (INJECTION_PI01 to INJECTION_PI05, the report's injection object), flags content a pull request adds
that is aimed at an agent: invisible or bidirectional Unicode, hidden Markdown that addresses an agent, known injection
phrases, long encoded blobs in an instruction file and an instruction file added in a vendored directory. Stale agent
instructions, signals SI01 to SI04 (SETUP_STALE_SI01 to SETUP_STALE_SI04, setupHealth.stale), flag an instruction
file that names a script, make target, path or file that does not exist, or that is old and names a file the change
edits. TESTS_NOT_EXERCISING_CHANGES warns when no test file the pull request adds or modifies imports a changed JS/TS
source file. A behaviour change: PI01 is an error by default, so a pull request that adds a zero-width character, a
bidi override or isolate, a tag character or a stray byte order mark now fails the check where it passed; test files,
fixtures/, __fixtures__/ and testdata/ are exempt, and an app policy can exempt paths (injection.exempt) or set
PI01's level (injection.signals). A pull request that changes JS/TS source without a test importing it now gets a
warn verdict where it got pass; it never fails the check. The CLI and the Action now read the committed text of the
agent instruction files, the root package.json and Makefile on every run with a local diff, with or without an org
policy, for the stale-instruction signals (Security below). Report v2 gains the optional injection, setupHealth and
testIntegrity.exercise fields and the new message codes; no field, input or code was removed or renamed.
Added
- Tests exercise the changed lines (A8 step 1,
TESTS_NOT_EXERCISING_CHANGES,warn): a changed JavaScript or
TypeScript source file counts as exercised when a JS/TS test file the pull request adds or modifies imports it
directly with a relative import and keeps or raises its assertion count. When at least one changed source file is not
exercised, the report carries one warning with the counts and up to 10 paths, the new optional
testIntegrity.exerciselists up to 200 paths, and the comment shows one line under "Test integrity" with a collapsed
list. It is a warning in every test-integrity mode and never fails the check, so a pull request that changes code
without a test now gets awarnverdict where it gotpass. Test files, declaration and config files, build output,
vendored, minified and generated files andcoverage.excludepaths are not asked; import aliases, workspace packages,
re-exports and per-test coverage are not followed (docs/LIMITS.md). It reads only the touched test files' text the
signals already read, and is silent in modeoff, without a diff and without that text. Report v2 gains the message
code and the optional field; nothing was removed or renamed. - Stale agent instructions, signals SI01 to SI04: on a change that touches an agent instruction file (
CLAUDE.md,
AGENTS.md,.cursor/rules,.github/copilot-instructions.mdand the other instruction kinds), or that deletes,
renames or removes what one names, pharn-ci reports a backticked command whose script is not in the root
package.jsonor whose target is not in the rootMakefile(SI01,SETUP_STALE_SI01), a backticked path that is not
tracked (SI02), a linked or@-imported file that is not tracked (SI03), allwarn, and an instruction file last
changed more than 90 days before HEAD's commit that names a file the change edits (SI04,info). Report v2 gains the
optionalsetupHealth.stalelist and the four codes; the PR comment gains a 📄 Instructions section. No finding
fails the check, and without a diff nothing is checked. - Prompt-injection surface scan (H4), signals PI01 to PI05: the lines a pull request adds are scanned for content aimed
at the next agent that reads the repository. PI01 (defaultblock, so it fails the check) flags invisible and
bidirectional Unicode (zero-width characters, bidi overrides and isolates as in Trojan Source, tag characters, a
stray byte order mark), with right-to-left marks, Persian and Indic joiners, emoji sequences and locale files left
alone; PI02 hidden Markdown (HTML comments, reference definitions, link titles) that addresses an agent; PI03 known
injection phrases from a versioned list (PH01toPH32); PI04 a base64 or hex blob over 200 characters in an agent
instruction file; PI05 an instruction file added undernode_modules/,vendor/,dist/and similar (PI02 to PI05
warn). Test files,fixtures/,__fixtures__/andtestdata/are exempt. Findings go into the new optional
injectionobject of the report and the comment's 🧬 Content section, as fixed words, phrase ids and code points,
never file text. New message codesINJECTION_PI01toINJECTION_PI05andINJECTION_TEXT_TRUNCATED(a file too
large to scan in full), and a newinjectionpolicy key (exempt,phrases,signals): an app policy can exempt
paths, add phrases and set severities; afile:policy can only add phrases and raise severities. Diff-only: no file
read, no new input, no new dependency, no network call.
Security
- The CLI and the Action now read the committed text of the agent instruction files (at most 50, 256 KiB scanned
each), the rootpackage.jsonandMakefile, andgit logtimes of up to 20 instruction files on every run with a
local diff, with or without an org policy. Only inline code, shell blocks, link targets and@imports are read; a
finding names a path or command made of repo-path characters only, and nothing else of the files leaves the job
(docs/THREAT-MODEL.mdrow C8, residual 40).