Static authoring hazards in a packet.
packet doctor reports authoring gaps — a packet with no prompts, a prompt
with no targets. packet lint reports authoring hazards: constructs that
load, run, and produce a wrong answer without ever raising. Every check below
corresponds to an observed way a packet silently misbehaves.
Errors
Findings that make the packet mean something other than what it says. Each one exits non-zero.
prompt_id_filename_mismatch— prompts are ordered by the numeric filename prefix, the sort key built byPromptRunner.Source.DirectorySource, not byid:. A mismatch reorders the run while the front matter still reads correctly.prompt_filename_without_prefix— with no numeric prefix the file sorts last, by basename, among all other unprefixed files.duplicate_prompt_id— two prompts claiming one id collide in progress state, runtime state, andrun <packet> <id>selection.unknown_target_repo— a target that names no manifest repo contributes no working directory and no verifier scope.unknown_verify_repo— a verify entry scoped to a repo that does not exist resolves against nothing.repo_group_in_targets—@groupsyntax is a legacy-config feature.PromptRunner.RepoTargetsis never consulted with packet repo groups, so the target expands to nothing.unknown_verify_clause— an unrecognized key underverify:is parsed, stored, and never evaluated, so the contract is weaker than it reads.
Warnings
Findings that are usually wrong but legitimately intentional sometimes. They
exit zero unless strict: true promotes them.
verify_command_without_timeout— the verifier runs commands withSystem.cmd("bash", ["-lc", command])and no timeout, so a hung command hangs the whole run after the model work is already spent.prompt_without_verify— completion falls back to the provider's own claim of success.contract_without_commands— the contract has neither acommands:entry nor any content assertion (contains,matches,doc), so it is satisfied by an empty file.changed_paths_only_vacuous—changed_paths_onlyreadsgit status --porcelain, so it can only see work that is still uncommitted. It passes vacuously in any packet where the session commits its own work.inert_front_matter_key—references,required_reading,context_files, anddepends_onare parsed and stored and then never read at runtime.
Timeout detection
A command counts as bounded when any of its segments — split on &&, ||,
;, and | — begins with a timeout token. Lint checks that timeout is
invoked at all, not that every branch of a compound command is bounded;
deciding the latter needs a shell parser.
Summary
Functions
Lints the packet rooted at root.
Types
@type report() :: %{ packet: String.t(), root: String.t(), strict?: boolean(), findings: [finding()], errors: non_neg_integer(), warnings: non_neg_integer(), pass?: boolean() }