Testing
This page describes safe local tests, linked tests, coverage, and release-readiness checks.
Tracked implementation updates: pm-52eh, pm-mcxr, pm-u42x, pm-atfm, pm-xmp5, pm-39cqqx, pm-5cgm2z, pm-avv3wx, pm-rizqb6, pm-95h7pg, pm-giks4s, pm-xa3t0o, pm-e97jyf, pm-efkvdy, pm-ed28wi, and pm-5ug5xq.
Agent Quick Context
- Unit and integration tests must not read or write real
.agents/pmdata. - Prefer
node scripts/run-tests.mjs ...because it creates sandboxedPM_PATHandPM_GLOBAL_PATH. - Linked-test execution injects isolated
PM_PATHandPM_GLOBAL_PATHfor every command and applies stored-command provenance checks before process creation. Direct runners are accepted; prefernode scripts/run-tests.mjs ...when the repository provides it because the wrapper also reproduces build, coverage, and cleanup policy. - Run linked tests before closing the item that owns the work.
Tracked documentation work: pm-u9d0.
Local/hosted gate parity is tracked by pm-ei6x66.
Standard Local Checks
pnpm build
pnpm lint
pnpm typecheck
node scripts/run-tests.mjs test
node scripts/run-tests.mjs coverage
For the exact ordered local preflight used to make release-readiness claims, run the registry-owned entrypoint:
pnpm verify:preflight
scripts/release/gate-registry.json is the executable plan for this command:
each ordered step declares its command, arguments, environment, capture mode,
and whether an explicit skip flag is permitted. Receipts distinguish passed
steps from declared skips, and quality:gate-registry maps hosted workflow
claims to the same canonical gate IDs. Hosted-only environment isolation and
tracker-integrity steps remain explicit entries with reasons rather than
silently disappearing from local parity.
node scripts/run-tests.mjs wraps Vitest in temporary tracker roots, disables
external Sentry delivery for the build, test workers, and their nested CLI
children, then cleans the roots up. Instrumentation tests can still exercise
Sentry initialization through their mocked module boundary; ordinary negative
fixtures must never create production incidents from a developer host.
Temporary directories must live outside the checkout and outside any ancestor
workspace with initialized tracker data. The runner rejects a checkout-local
temporary root, including a symlink alias, before starting build or test
processes (pm-bukwmy). If the default
temporary filesystem is full, set TMPDIR (or TEMP/TMP on Windows) to an
existing isolated scratch directory; an ignored directory inside the repository
is not isolated. Filesystem fixtures must honor node:os's tmpdir() and remove
only the temporary directories they created.
Public SDK changes additionally run semantic surface and import-cost contracts:
pnpm sdk:surface:check
pnpm benchmark:sdk-entrypoints:check
pnpm benchmark:transport:check
The surface gate detects exported signature, type-parameter, declaration-kind, and stable error-code drift across the aggregate and every narrow SDK entrypoint. The performance gates protect entrypoint import cost and one-item CLI cold-start overhead without touching the repository tracker.
pnpm lint and pnpm quality:static are the same canonical local static gate.
The gate layers ESLint rules for
shipped source, package, plugin, and script surfaces that match the CodeFactor
maintainability findings this repo tracks (complexity,
no-unsafe-optional-chaining, and the relevant eslint-plugin-unicorn
mechanical rules), jscpd duplicate detection across source and tests, and the
repo-specific quality:static gate. The dedicated quality:static gate remains
authoritative for source/exported docstring coverage, orphan-module checks,
directory-load caps, and the TypeScript-aware duplicate/complexity checks that
are tailored to pm's source layout; pnpm lint delegates to it instead of
running a second threshold profile. It also includes a changed-file
CodeFactor-parity complexity scan for shipped source, package, and script files
so PR-local CodeFactor maintainability annotations fail locally before commit or
push. Existing legacy high-complexity test fixtures are tracked separately and
must not be used as precedent for new changed production/script code.
The same required static gate validates an explicit seven-day Dependabot cooldown for every updater and requires both npm and GitHub Actions entries. Missing values, semver overrides outside 7–90 days, invalid YAML, removed updaters, and include/exclude bypasses fail the gate. The maximum follows GitHub's cooldown limits. Security updates retain GitHub's separate security-update behavior. The negative controls are tracked by pm-gkut and pm-dmo5.
Release synchronization and commit staging share one distribution manifest inventory. The pm-t4prek regression bumps versions in a temporary Git repository and reads the resulting commit to verify workspace versions and exact plugin runtime pins. The pipeline checks version consistency immediately before staging, including required string versions and runtime pins in both plugin package manifests; tests of a prepared working tree alone cannot establish that the release commit contains those changes.
lint:duplicates runs three zero-clone profiles: the broad repository profile,
the production cross-format profile, and a supplemental long-table profile at
28 lines / 80 tokens. The last profile detects the historical GH-508 normalizer
tables below the other profiles' token floors; it does not replace their shorter
line thresholds. Its real detector regression rejects the historical table rows
and accepts a shared declaration. The earlier 12-line / 60-token exploratory
census informed calibration, but is not the enforced profile. These bounded
profiles do not claim complete equivalence with hosted analyzers.
See pm-xspd for calibration evidence.
The local parity rules catch analyzer classes before push. The mandatory hosted proof runs after the final commit is pushed and both apps have finished:
pnpm quality:hosted-analysis
This command reads commit-scoped GitHub results for git rev-parse HEAD. It
passes only when DeepScan explicitly reports 0 new issues and CodeFactor
completes successfully with No issues found. The exact commit is authoritative.
For GitHub merge and squash commits whose apps report only on the reviewed PR
head, the gate accepts that evidence only after proving the source and target
have the same immutable Git tree. Squash commits also require one unambiguous
GitHub PR association to a closed PR merged into main. Missing, pending,
failed, skipped, stale, ambiguous, and different-tree results all fail.
pnpm release:gates includes the same non-skippable verification, so run it
only after the pushed reviewed head's hosted analyzers are terminal.
Focused Test Runs
node scripts/run-tests.mjs test -- tests/unit/output.spec.ts
node scripts/run-tests.mjs test -- tests/integration/cli.integration.spec.ts
Use focused runs while iterating, then run coverage before closure when risk or scope warrants it.
CI Retry and Timeout Diagnostics
Platform regressions from pm-hrhfgi and
pm-zk67yf have portable negative controls.
Complete source scans process at most 32 item files per batch; the descriptor
pressure fixture fails unbounded reads while requiring genuine permission
failures to remain visible. The 10,000-item aggregation fixture separately
verifies completeness before pagination. Git fixtures that assert exact bytes
declare repository-local core.autocrlf=false and core.eol=lf so host defaults
cannot change the restoration target. Send generated shell scripts through
stdin (bash -s) so their size cannot exceed Windows command-line limits.
Runtime compaction is tested through a
real directory alias as well as its physical path, including original source
mapping and repeated-compaction byte stability. These tests run in the full
suite on the Nightly Validation platform matrix.
CI retains the 30-second per-test timeout and retries one failed attempt. A test that passes only on retry is reported as flaky rather than silently folded into the pass count; a persistent assertion still fails after the bounded retry. Local runs do not retry, so deterministic failures stay immediate while iterating.
Vitest's GitHub reporter emits annotations and retry evidence. The repository
reliability reporter additionally writes
.vitest-reports/reliability-<shard>.json and appends a job-summary table with
the test identity, file, duration, effective timeout, retry count, shard, and
failure detail. Tests completing at or above 80% of their timeout are recorded
as at-risk before load turns them into timeouts. Coverage shards upload this
JSON beside their blob report, so recurrence can be measured without decoding
the coverage artifact or re-reading raw logs.
PM_TEST_SHARD supplies a stable shard identity and
PM_TEST_RELIABILITY_REPORT_DIR can redirect the JSON report for an isolated
harness. These variables affect diagnostics only; they do not change test
selection, retry count, timeout, or verdicts.
Coverage Governance
Coverage gating now targets literal all-source coverage across runtime code families:
vitest.config.tsincludes canonical authoring sources acrosssrc,packages(.ts),scripts,plugins, anddocs/examples.- Generated package JavaScript mirrors are not separately gated; coverage is enforced on their TypeScript sources.
- Thresholds are strict
100/100/100/100for lines, branches, functions, and statements. - Avoid reintroducing curated coverage allowlists; keep the full all-source corpus measurable and gated.
- Prefer extending existing test files and shared helpers so new coverage remains fast and non-duplicative.
- Prefer extracting deterministic pure helpers (and unit-testing them) when an orchestration-heavy file is difficult to cover directly.
Static quality also enforces source documentation coverage through pnpm quality:static: every src/**/*.ts source file needs a module TSDoc block,
every exported declaration needs a non-module TSDoc block, and known generated
boilerplate summaries are rejected.
Test Strength and Documentation Content
The required static gate also runs SDK mutation testing and the documentation content ratchet, tracked by pm-zclzll and pm-dvwm. These add behavioral and content checks while retaining exact 100/100/100/100 coverage and all docstring floors.
TOON Storage Round-Trip Gate
History-only lifecycle reconstruction and recovery contracts are described in History durability and recovery. Their integration suite is part of the required all-source test run and compares historical projections against independently captured item files, including after removing those files.
TOON item serialization is a fail-closed storage boundary. Before returning
bytes to any create, update, merge, migration, or package caller, pm decodes the
new @toon-format/toon output and compares it with the JSON-like canonical
payload. A decode failure or the first field-level mismatch raises
item_document_roundtrip_failed; no item bytes are written.
The property suite exercises generated and adversarial agent text, including array-header spellings, colons, quotes, backslashes, newlines, Unicode, comment prefixes, and bracketed endpoint-shaped strings:
node scripts/run-tests.mjs test -- tests/fuzz/project-boundaries.fuzz.spec.ts
Major codec upgrades additionally require a complete read/serialize/read sweep
over every tracked .toon item, strict history and storage validation, the
packed npx consumer smoke, and Bun SDK/bunx execution. A dependency-only green
unit suite is not sufficient evidence for changing the canonical storage
codec.
Directory-load cap and the tests/unit split
pnpm quality:static also caps each directory under src/, tests/, and
packages/ at 120 .ts files (--max-files-per-dir, default 120). This
keeps any single directory navigable and forces load to be partitioned by area
rather than piling into one folder. tests/unit/ is therefore split into
per-area subdirectories (tests/unit/commands/, tests/unit/core/,
tests/unit/cli/, tests/unit/mcp/, tests/unit/extensions/, …) instead of a
single flat directory.
When adding a unit test, place it in the matching tests/unit/<area>/
subdirectory (or merge into an existing spec there); never add a file directly
to tests/unit/. The
static-quality-gate directory-load contract
test asserts the live repository stays at or below the cap and that the magic
number matches the gate default, so drift is caught before CI's static gate
fails.
Search Quality Evaluation
search-advanced exposes an advisory golden-query harness for relevance drift checks.
Fixture source:
tests/search-eval/golden-queries.json
Local run:
pm package install search-advanced --project
pm reindex --mode keyword --eval --eval-fixtures tests/search-eval/golden-queries.json --json
Fixture authoring notes:
- Each fixture must include
query,expected_top_ids, and optionallymode(keyword|semantic|hybrid) andmin_ndcg_at_5(0..1). - Keep expected IDs deterministic and scoped to stable seed data so CI does not flap.
- Add new fixtures for regressions before tuning search defaults.
The repository-native pm eval corpus is a required CI and release gate:
pnpm build
pnpm quality:retrieval-eval
tests/search-eval/retrieval-gate-baseline.json enforces query count, nDCG,
MRR, precision, and recall. The corpus includes at least one intentionally
non-saturated judgment set so recall regressions remain observable. The
required context-quality command also runs an impossible perfect-score negative
control and fails if pm eval --fail-under stops returning a non-zero exit.
Refresh the baseline only with pnpm quality:retrieval-eval:update after
reviewing query-level ranking changes.
Context Quality Evaluation
The required context relevance gate proves that pm context and pm next
assemble the right bounded working set, not only that search returns relevant
documents.
Fixture and baseline sources:
tests/context-eval/golden-scenarios.json— reviewable scratch, real-shaped, synthetic-scale, and returning-agent continuity judgments.tests/context-eval/baseline.json— committed aggregate and per-scenario metrics from the accepted structural/scorer behavior.
Run the required gate locally:
pnpm build
pnpm quality:context-eval
The gate creates isolated temporary trackers through PmClient, reads them only
through the public context() / next() SDK primitives, and reports nDCG,
reciprocal rank, required-item recall, continuity coverage, token-budget
adherence, and served-item signal attribution. It fails when an explicit corpus
threshold is missed or any aggregate metric regresses below the committed
baseline.
Benchmark and evaluation populations that need realistic project structure
should use the public SDK shapes documented in
Portable Corpus Shapes. pnpm benchmark:corpus-shapes
remeasures the same SDK operations across equal-count scratch and
representative populations and records their measured profiles.
When a deliberate ranking change improves or intentionally redefines the golden judgments, review the scenario-level diff first, then refresh the baseline:
pnpm quality:context-eval -- --update
pnpm quality:context-eval
Do not update the baseline merely to make CI green. Change judgments and rationales in the corpus when product intent changes, and commit the corpus, baseline, scorer tests, and SDK documentation together.
Context-intent classification has a separate calibration receipt and one manifest-backed recovery spelling:
pnpm context:intent:calibrate
pnpm context:intent:calibrate --update
The gate verifies that package.json exposes that exact script before it reads
or refreshes scripts/release/context-intent-calibration.json. A missing or
renamed script therefore fails with the same command contributors are told to
run, and pnpm forwards --update to the calibration gate.
Hosted Gate Registry
Tracked by pm-k6t4yb and pm-b2hc4x.
Every workflow job is discovered by its stable workflow-file#job-id identity
and matched exactly against scripts/release/gate-registry.json; human-facing
step names never define the inventory. Each registry entry declares:
- a canonical pm owner;
- the enforced workflow jobs it participates in;
- actionable failure taxonomy;
- explicit bypass policy and audit rationale;
- an executable negative-control test and assertion.
Run the fail-closed inventory locally:
pnpm quality:gate-registry
node scripts/release/gate-registry.mjs --inventory
pnpm quality:static includes the registry. A new workflow job fails until it
is declared under at least one canonical gate, and a removed or renamed job id
fails until stale policy is reconciled. Display-name edits do not mutate gate
identity. Public source claims are mapped to exact evidence strings and an
enforced registry entry so documentation cannot silently advertise advisory
behavior.
The inventory output lists registry-derived registered job IDs beside the
parsed workflow_jobs; validation requires the two sets to match exactly.
Tracker Context-Quality Ratchets
Tracked by pm-ips23h, pm-kpftft, and pm-4ok4ex, with lifecycle-stable outcome reachability owned by pm-g4k74y and pm-bzmeaa.
The SDK-owned assurance registry stores tracker context-quality measurements,
floors, ceilings, lifetimes, enforcement, and executable negative controls in
.agents/pm/assurance.json. The tracker-context-quality gate covers stored
relationship kinds, validator debt, health checks, graph findings, structural
cut points, and typed reachability to outcome milestones. One workspace
assurance context reuses identical graph, validate, and health evaluations, so
a broad gate has one authoritative snapshot without repeatedly rescanning it.
Outcome enforcement uses an all-status reachable population, unreachable
ceiling, and basis-point floor. Active and terminal populations remain
diagnostics: absolute per-lifecycle floors would mistake normal close or reopen
transitions for relationship loss.
Run the same gate used by hosted CI:
pnpm quality:tracker-measurements
pm assurance run tracker-context-quality --trigger ci --dry-run --json
Every native assertion contains both a passing boundary case and an impossible
case that must fail. Changes flow through pm assurance put, which refuses a
weaker bound, scope, lifetime, or enforcement unless a verified Decision item
authorizes it. scripts/release/gate-registry.json separately inventories the
retired bespoke gate and gives every graph subcommand either a named automated
consumer or an explicit interactive-only classification.
Agent Output Token Budgets
Run the required PR gate locally:
pnpm build
pnpm quality:token-budget
The isolated fixture contains a medium-scale linked workspace. Discovery
surfaces (--help and contract projections) use reviewable ratcheted byte
baselines. Answer surfaces including activity, deps, graph, duplicates, events,
health, list, get, context, next, search, and validate are measured against
their live SDK command contracts. A deliberately full, unbounded activity query
must exceed the default contract, proving the gate can fail when a default
becomes accidentally unbounded.
Refresh scripts/release/token-budgets.json only for an intentional discovery
surface change:
node scripts/release/token-budget-gate.mjs --update
pnpm quality:token-budget
The manifest records baseline bytes and estimated tokens for visible review
deltas. Updating it cannot raise answer ceilings, which remain owned by
PM_COMMAND_OUTPUT_BUDGET_CONTRACTS.
Diagnostic ceilings share the executable refusal gate:
pnpm quality:recovery-closure
The gate replays 117 refusal contracts: 18 closed-domain rows, 88
grammar-derived required-argument omissions, seven closed positional-action
families, and four tracker-preflight states. It also ratchets ten representative
failure paths against PM_DIAGNOSTIC_OUTPUT_BUDGET_CONTRACTS. Every diagnostic
must fit its declared JSON ceiling and preserve a mechanically actionable
correction; executable retry argv is never collection-truncated. The
missing-probe negative control and the authoritative tracker-state snapshot
prove that the corpus cannot silently shrink or turn a refusal into a mutation.
The gate starts every fixture command from a closed environment allowlist. It
retains only declared process-portability inputs such as PATH, temporary and
home roots, and Windows process-launch variables, then supplies fixed locale,
timezone, author, telemetry, and isolated tracker settings. Undeclared host
values cannot reach measured output, including future harness variables that
the descriptor registry does not yet know about.
Linked Tests
Add tests to the item that owns the work:
pm test <item-id> --add command="node scripts/run-tests.mjs test -- tests/unit/output.spec.ts",timeout_seconds=240
pm test <item-id> --run --progress
For broader sweeps:
pm test-all --status in_progress --progress
Do not link pm test-all itself as an item-level test command. It creates recursive orchestration.
Use --fail-on-empty-test-run for release/readiness gates where selecting zero
linked tests should fail instead of producing an inconclusive pass.
Use --progress for long foreground sweeps; it prints parent-level
pm test-all selection, per-item start/end, and final summary lines in addition
to the linked-test command progress emitted by pm test.
Package Ecosystem Smoke
After pnpm build, external package compatibility can be checked without
touching the repository tracker:
pnpm smoke:external-packages -- --limit 10
pnpm smoke:external-packages -- --package pm-changelog
The harness creates one temporary project per package, sets sandboxed PM_PATH
and PM_GLOBAL_PATH, installs the package with pm install npm:<name> --project, runs pm package doctor --project --detail deep --trace, and probes
runtime contracts with pm contracts --runtime-only --availability-only. Use
--discover-only for the npm package list and --keep-temp only when debugging
a failing package root.
PM Context Modes
Linked PM commands default to schema context: settings and extensions are seeded, but tracker item data stays isolated.
When a linked command is a PM tracker-read such as pm validate, the default mismatch error suggests
--auto-pm-context, which keeps schema isolation for ordinary commands and routes only tracker-read PM commands
through seeded tracker data.
The runner resolves every selected command's effective context before it
creates temporary sandboxes. Runs whose effective context is schema initialize
only their schema roots; a non-PM command explicitly configured with
pm_context_mode: "tracker" still requires tracker data. Tracker roots and item
data are materialized only when at least one selected command requires tracker
context. This preserves source isolation without copying an unrelated tracker
into constrained temporary storage.
Capacity, permission, and resource failures while seeding a required tracker
surface as typed, path-redacted host-environment refusals with recovery steps.
When a legacy source tracker has settings but no _workspace history, tracker
mode creates the sandbox's initial audited settings snapshot from the exact
source bytes. Existing source workspace history is copied unchanged, including
real drift, so linked validation never masks a source integrity failure.
Source Workspace Modes
Linked tests have a separate source-workspace contract. Store a default on one
entry with workspace_context_mode, or choose a run-level mode with
--workspace-context:
pm test <item-id> --add-json '{"command":"pnpm quality:static","workspace_context_mode":"isolated"}'
pm test <item-id> --run --workspace-context snapshot --override-linked-workspace-context
source(default) runs in the source checkout and exposes its read-only source-context environment, preserving existing linked-test behavior.isolatedruns from an empty disposable directory and removesPM_SOURCE_WORKSPACE_ROOT,PM_SOURCE_PM_PATH, and the source-context access declaration. Use it only for commands that do not require checkout files.snapshotcopies the workspace into the linked-test sandbox, runs from that copy, and binds its.agents/pmpath to the selected temporary tracker..git,.agents,node_modules, coverage output, and common cache directories are excluded at every directory depth; an existing top-levelnode_modulesis linked read-only by convention. Built output remains available so linked commands such asnode dist/cli.jskeep working. Writes therefore land in the disposable snapshot rather than the source checkout.
Every result reports the requested/effective workspace mode, working
directory, exposed source root, and trust decision. Recorded test_runs retain
the effective workspace mode and trust reason beside the command.
Linked-Test Command Trust
Linked commands are stored shell programs, so merge-unioned tracker data is an
execution boundary. New command entries record author, creation time, source
branch when available, and whether the item merge driver introduced the entry.
Locally created commands keep their previous run behavior. Commands marked as
merge-unioned or carrying a different source ref fail before process creation.
Malformed provenance is sanitized to the additive provenance_invalid marker
and receives the same fail-closed treatment; it is never normalized into a
trusted legacy command.
These pre-execution refusals use the trust_refusal failure category, separate
from command or assertion failures.
Command-string shape is intentionally not treated as a security boundary.
Direct node --test, Vitest, package-manager, shell-wrapped, and non-Node
runners are accepted consistently because the runtime injects tracker
isolation for all of them. classifyLinkedTestCommandSafety exposes the same
SDK policy to package hosts and returns advisory runner classification;
provenance review and acknowledgment remain the execution trust boundary.
Choose one explicit recovery:
# Review and trust the item's current command fingerprints in this clone.
pm test <item-id> --acknowledge-linked-tests
# Or permit a single reviewed run. Both controls are required.
pm config project set untrusted-linked-test-execution enabled
pm test <item-id> --run --allow-untrusted-linked-tests
Acknowledgments live in the clone-local ignored runtime directory and bind to the full command, tracker/workspace context, environment controls, host-safety mode, and provenance fingerprint; editing any of those fields requires a new review. Enabling the project policy alone never executes an untrusted command, and the per-run flag alone is also refused. Inspect all unacknowledged entries without executing them with:
pm validate --check-command-references --verbose-diagnostics
Use explicit modes when needed:
pm test <item-id> --run --pm-context schema
pm test <item-id> --run --pm-context tracker
pm test <item-id> --run --pm-context auto --check-context --auto-pm-context
For complex linked-test commands, prefer JSON input so shell syntax survives unchanged:
pm test <item-id> --add-json '{"command":"node scripts/run-tests.mjs test -- tests/unit/output.spec.ts","timeout_seconds":240}'
To rerun a focused subset without editing linked-test metadata:
pm test <item-id> --run --match output
pm test <item-id> --run --only-index 2
pm test <item-id> --run --only-last
Linked-command stdout and stderr are captured through temporary regular files,
then read back with the 20 MiB per-stream retention bound. This keeps inherited
descriptors blocking for Bun, Rust, and other runtimes that treat EAGAIN on a
non-blocking stdout pipe as fatal. Output beyond the bound is drained to disk,
the child still completes normally, and the result records a truncation notice
instead of misclassifying a transport failure as a test assertion.
Strict governance flags:
pm test <item-id> --run \
--fail-on-context-mismatch \
--fail-on-skipped \
--fail-on-empty-test-run \
--require-assertions-for-pm
Structured quantitative evidence can be recorded and queried without parsing logs or comments:
pm test <item-id> --run \
--measure coverage=100,unit=percent,threshold=100 \
--measure p95_latency=42,unit=ms,threshold=50
pm test <item-id> --metric-below coverage=100 --metric-diff p95_latency
Measurements are stored on the producing test_runs row, retained with the
bounded run history, and exposed consistently by CLI, SDK, MCP, and contracts.
Each recorded row also keeps a bounded executions list with the exact linked
command, requested/effective pm_context_mode, effective workspace mode, and
trust reason, so tracker-backed verification remains attributable after the
transient process logs are gone.
Linked-Test Assertions
Linked tests can include assertion metadata:
pm test <item-id> --add \
command="pm list --status open --json",timeout_seconds=120,assert_json_field_gte=count:0
Common assertion keys include:
assert_stdout_containsassert_stdout_regexassert_stderr_containsassert_stderr_regexassert_stdout_min_linesassert_json_field_equalsassert_json_field_gte
Background Runs
pm test <item-id> --run --background
pm test-all --status in_progress --background
pm test-runs
pm test-runs status <run-id>
pm test-runs logs <run-id> --tail 100
pm test-runs stop <run-id>
pm test-runs resume <run-id>
Background run fingerprints prevent duplicate parallel runs for the same linked-test set.
For long test-all runs, pm test-runs status <run-id> --json includes the
latest aggregate item coordinates (item_index, item_total, item_id) plus
linked-test coordinates and current_command when the child emits progress.
Use pm test-runs logs <run-id> --stream stderr only when the compact status
message is not enough.
The bundled pm-linked-test-adapters package is the first-party package
exemplar for background run management. Install it in an isolated project when
validating package-provided test-run surfaces:
pm package install linked-test-adapters --project
pm package doctor --project --detail deep --trace
pm test-runs list --json
The package activates the test-runs command family and keeps subprocess
handling behind an explicit package permission declaration, so it is a useful
smoke target for package, permission, and command-contract changes.
Release-Readiness Checks
For substantial changes:
pnpm build
pnpm typecheck
node scripts/run-tests.mjs coverage
pm validate --check-resolution --check-history-drift
pm health --check-only
When release readiness requires external GitHub security telemetry in addition to local checks, run:
gh issue list --state open --limit 100 --json number,title,updatedAt,url
gh pr list --state open --limit 50 --json number,title,headRefName,reviewDecision,url
gh api "repos/unbraind/pm-cli/dependabot/alerts?state=open&per_page=100"
gh api "repos/unbraind/pm-cli/secret-scanning/alerts?state=open&per_page=100"
gh api "repos/unbraind/pm-cli/code-scanning/alerts?state=open&per_page=100"
code-scanning/alerts can return 404 no analysis found until at least one
CodeQL run has completed.
For documentation-only changes, at minimum run:
pnpm build
rg -n "forbidden-private-token-or-path" README.md docs
Replace the placeholder pattern with the actual sensitive term being guarded in the current task.
Contract Snapshot Gate
Tracked by pm-d6kq.
pm contracts --full --json is a public machine-readable SDK and agent surface.
Keep its committed golden snapshot current when command contracts, schemas,
aliases, or extension-provided command contracts intentionally change:
pnpm build
pnpm contracts:update
pnpm contracts:check
CI runs pnpm contracts:check in the static gate. Snapshot diffs should be
reviewed like an API change and paired with the package-owned changelog flow
when the contract surface changes intentionally.
The agent-facing output-size gate is separate from schema drift. Run
pnpm quality:token-surface after changing help, contracts, or MCP tool
registration. It measures root help, every advertised command help page, the
summary/default/full contracts family, and MCP tools/list against
scripts/agent-token-surface-baseline.json. Use
pnpm quality:token-surface:update only for an intentional reviewed change;
the baseline stores explicit byte ceilings with headroom rather than volatile
timestamps or package versions.
The CLI contract snapshot is separate from the TypeScript SDK surface snapshot. When public SDK declarations or SDK error codes change, also run:
pnpm sdk:surface:check
Use pnpm sdk:surface:update only for reviewed additive changes. Breaking
changes require the explicit --acknowledge-breaking "<release rationale>"
argument documented in SDK.