Skip to content

Latest commit

 

History

History
916 lines (630 loc) · 48 KB

File metadata and controls

916 lines (630 loc) · 48 KB

Local Validation

This document records the current local verification contract and the known environment-specific gotchas that contributors have already hit.

Baseline Command

The baseline sprint closeout command is:

./scripts/verify-local.sh

Sprint 77 also makes the browser-shell smoke a CI-owned gate. Run it locally with:

pnpm run test:e2e

Playwright starts and stops Vite through webServer; no separately running dev server is required. The smoke deliberately asserts that native Tauri IPC is absent, so it proves only the limited browser shell. Native workspace, asset-protocol, CSP enforcement, and PDF-preview behavior require a desktop smoke.

When the host disk is near capacity, fresh Rust target directories under /var/folders/.../T can fail with No space left on device even when the repo itself is healthy. If a rerun fails that way after frontend or docs-only changes, inspect df -h, clean stale verifier target dirs, and prefer reusing a previously successful CARGO_TARGET_DIR before treating the failure as a product regression.

Use npm run maintainer:temp-hygiene before ad hoc shell cleanup when the likely problem is stale 900project-* verifier or sprint artifacts under the temp roots. That command reports and can remove only repo-prefixed temp artifacts; it is the reviewed repo-owned path for this class of disk-pressure triage.

Use npm run maintainer:artifact-hygiene before manual repo-root cleanup when the likely problem is generated evidence or release directories inside the checkout. That command reports and can remove only managed repo-local artifact paths; it does not touch tracked content or workspace-state directories.

Use npm run maintainer:duplicate-copy-hygiene before deleting suspicious untracked * 2.* or * 3.* files when stale duplicate snapshots may be shadowing tracked repo content inside the checkout.

Fresh clones need dependencies installed before this script can work because it calls the local node_modules/.bin tools directly. In a new healthy clone, run:

npx pnpm install --frozen-lockfile

The repo tracks pnpm-workspace.yaml with allowBuilds.esbuild: true because the reviewed Vite/Svelte toolchain needs the esbuild postinstall step. If that file is missing or reverted to a placeholder, pnpm install --frozen-lockfile will stop at pnpm's build-approval gate before ./scripts/verify-local.sh can run.

If you validate from a secondary git worktree, that worktree also needs access to the dependency tree. The simplest options are:

npx pnpm install --frozen-lockfile

or, when a healthy sibling checkout already has a complete install:

ln -s /path/to/healthy-clone/node_modules node_modules

The script runs frontend tools through local node_modules/.bin binaries by default. That keeps local closeout focused on the actual compiler, linter, test runner, and bundler instead of the package-runner layer that can stall in this Codex desktop environment.

When ./scripts/verify-local.sh has to create its own 900project-verify-* Cargo target, it now removes that auto-created target on exit by default. To keep the auto-created target for one deliberate rerun, set:

VERIFY_KEEP_CARGO_TARGET_DIR=1 ./scripts/verify-local.sh

The repo contract remains pnpm for dependency installation and lockfile policy. If a contributor needs to validate through package scripts, use:

VERIFY_FRONTEND_RUNNER=pnpm ./scripts/verify-local.sh

That runner reads package.json and tries to run the repository-pinned pnpm version from the local pnpm store before falling back to PATH-level pnpm or npm. To force a specific pnpm script path, use:

VERIFY_FRONTEND_RUNNER=pnpm VERIFY_PNPM_SCRIPT=/absolute/path/to/pnpm.cjs ./scripts/verify-local.sh

If the Codex desktop environment stalls on the default local-binary path without diagnostics, the script also supports npm runners:

VERIFY_FRONTEND_RUNNER=npm-exec ./scripts/verify-local.sh

The default script path runs:

  • ./node_modules/.bin/svelte-check --tsconfig ./tsconfig.json
  • ./node_modules/.bin/eslint src/lib src/main.ts vite.config.ts vitest.config.ts playwright.config.ts eslint.config.js scripts/*.js scripts/release/*.js scripts/maintainers/*.js scripts/contributors/*.js
  • ./node_modules/.bin/vitest run
  • node --test scripts/e2e-config.test.js scripts/public-safe-artifacts.test.js scripts/release/native-bundle-identity.test.js ... plus the maintained release, maintainer, and contributor Node suites from package.json
  • ./node_modules/.bin/vite build
  • cargo fmt --check --manifest-path src-tauri/Cargo.toml
  • cargo check --manifest-path src-tauri/Cargo.toml
  • cargo test --lib --bins --tests --manifest-path src-tauri/Cargo.toml

Audit Hardening Validation

After portability, CSP, release-boundary, or native packaging changes, also run the relevant focused gates:

npm run test:release
npm run test:maintainers
npm run release:boundary
cargo audit --file src-tauri/Cargo.lock
pnpm run test:e2e

On macOS, after producing an app bundle, verify that Tauri selected the desktop executable rather than an auxiliary Cargo binary:

npm run release:verify:native-bundle

The command skips clean checkouts with no built app, but fails a present bundle unless both Info.plist and Contents/MacOS/ identify nine-hundred-project.

The Sprint 77 audit closed RUSTSEC-2026-0190, RUSTSEC-2026-0194, and RUSTSEC-2026-0195 with lock-only updates. Cargo audit may still report informational unmaintained/unsound warnings; record them separately rather than calling the vulnerability gate clean without qualification.

Vitest now resolves the browser condition in vitest.config.ts so Svelte component tests can use the public mount(...) API under jsdom. If App-level component tests start failing with mount(...) is not available on the server, check the Vitest resolve conditions before changing the application code.

With VERIFY_FRONTEND_RUNNER=pnpm, the frontend half uses:

  • repository-pinned pnpm run check when available, otherwise PATH pnpm run check, otherwise npm run check
  • repository-pinned pnpm run lint when available, otherwise PATH pnpm run lint, otherwise npm run lint
  • repository-pinned pnpm run test when available, otherwise PATH pnpm run test, otherwise npm run test
  • repository-pinned pnpm run build when available, otherwise PATH pnpm run build, otherwise npm run build

With VERIFY_FRONTEND_RUNNER=npm-exec, the frontend half uses:

  • npm exec -- svelte-check --tsconfig ./tsconfig.json
  • npm exec -- eslint src/lib src/main.ts vite.config.ts vitest.config.ts playwright.config.ts eslint.config.js scripts/*.js scripts/release/*.js scripts/maintainers/*.js scripts/contributors/*.js
  • npm exec -- vitest run
  • node --test scripts/release/release-artifacts.test.js scripts/release/release-verification.test.js scripts/release/release-evidence-ledger.test.js scripts/release/release-publish-assets.test.js scripts/release/release-boundary-regressions.test.js scripts/release/release-witness-pack.test.js scripts/release/release-candidate-preflight.test.js scripts/maintainers/rotation-drill.test.js scripts/maintainers/issue-reproduction-kit.test.js scripts/maintainers/evidence-freshness.test.js scripts/maintainers/durability-stewardship.test.js scripts/maintainers/temp-artifact-hygiene.test.js scripts/maintainers/repo-artifact-hygiene.test.js scripts/maintainers/recovery-incident-fixtures.test.js scripts/maintainers/validation-receipts.test.js scripts/maintainers/fixture-provenance-ledger.test.js scripts/maintainers/review-dossier-pack.test.js scripts/contributors/starter-kit.test.js scripts/contributors/validation-sandbox.test.js
  • npm exec -- vite build

Transfer Fixture Validation

Sprint 40 adds a public transfer-fixture library with its own maintainer smoke path:

pnpm run fixtures:transfer:refresh
pnpm run fixtures:transfer:smoke

If package-runner behavior is noisy in the current environment, the direct Rust fallback is:

cargo run --manifest-path src-tauri/Cargo.toml --bin transfer-fixtures -- refresh --force
cargo run --manifest-path src-tauri/Cargo.toml --bin transfer-fixtures -- smoke

The generated artifacts land in artifacts/transfer-fixtures/ and are intentionally not committed.

Performance Gate Validation

Sprint 42 adds a repo-owned performance harness with explicit fixture refresh and gate-run commands:

npm run performance:gates:refresh
npm run performance:gates:run

The direct Rust fallback is:

cargo run --manifest-path src-tauri/Cargo.toml --bin performance-gates -- refresh --force
cargo run --manifest-path src-tauri/Cargo.toml --bin performance-gates -- run

The harness writes ignored artifacts under artifacts/performance-gates/:

  • catalog.json
    • fixture inventory and scenario metadata
  • report.json
    • machine-readable pass/fail output with actual timings and threshold values
  • generated fixture directories for:
    • workspace-scale
    • import-conflict-scale
    • attachment-preview-scale
    • export-scale

These gates are intentionally not part of the baseline ./scripts/verify-local.sh contract yet. They are heavier than routine sprint closeout checks and should stay opt-in until maintainers decide they belong in a broader local or CI budget.

Release Evidence Validation

Sprint 41 adds a repo-owned release evidence ledger:

pnpm run release:ledger -- \
  --downloads-root release-downloads \
  --asset-directory release-publish \
  --release-tag v0.1.0 \
  --repo 900Labs/900Project \
  --sign-updater true

In normal release recovery flows, pnpm run release:publish:assets ... rewrites the same release-publish/release-evidence-ledger.json automatically after verification.

Support Bundle Validation

Sprint 44 adds a Rust-owned support-bundle contract with focused local coverage:

CARGO_TARGET_DIR=/tmp/900project-sprint44-cargo cargo test --manifest-path src-tauri/Cargo.toml support_bundle -- --nocapture

That target currently covers:

  • deterministic JSON output from the same input state
  • settings redaction, including the app_lock.pin_hash case that lives inside app_settings
  • missing and unparseable repo-evidence diagnostics

The current bundle button and save-path wiring ride on the normal shell validation path (svelte-check, vite build, and baseline app smoke). Sprint 44 does not yet add a dedicated frontend test for that button flow.

Workspace Integrity Audit Validation

Sprint 45 adds a backend-owned integrity report plus one explicit repair action for orphaned attachment blobs:

CARGO_TARGET_DIR=/tmp/900project-sprint45-cargo cargo test --manifest-path src-tauri/Cargo.toml audits_ -- --nocapture

That target currently covers:

  • a healthy workspace returning a clean audit
  • a deliberately corrupted workspace surfacing graph, attachment, timer, and time-entry findings
  • deterministic orphan-blob cleanup removing only the repairable blob finding

The current shell surface for the audit is maintainer-facing and rides on the normal Svelte typecheck and build path. Sprint 45 does not yet add a dedicated frontend test for the audit panel.

Compatibility Matrix Validation

Sprint 46 adds a repo-owned compatibility matrix with one maintainer rerun command:

npm run compatibility:matrix:run

The direct Rust fallback is:

cargo run --manifest-path src-tauri/Cargo.toml --bin compatibility-matrix -- run --force

The command writes ignored artifacts under artifacts/compatibility-matrix/:

  • report.json
    • supported workspace schema upgrade results for schema versions 1 through current schema 6
    • supported .900proj import results for bundle schema versions 1 through 6
    • explicit expected-failure output for the unsupported schema-1 placeholder recurring-rule case
  • generated case directories for:
    • workspace-schema-v1
    • workspace-schema-v2
    • workspace-schema-v3
    • workspace-schema-v4
    • workspace-schema-v5
    • workspace-schema-v6
    • workspace-schema-v1-legacy-recurring-rules
    • bundle-schema-v1
    • bundle-schema-v2
    • bundle-schema-v3
    • bundle-schema-v4
    • bundle-schema-v5
    • bundle-schema-v6

Sprint 46 also adds focused Rust coverage under the compatibility_matrix test target, but the maintainer-facing command is the source of truth for the compatibility report artifact.

Print-Ready PDF Validation

Sprint 66 keeps the focused validation path narrow and backend-heavy:

  • run cargo fmt --manifest-path src-tauri/Cargo.toml plus CARGO_TARGET_DIR=/tmp/900project-sprint66-cargo cargo test --lib --bins --tests --manifest-path src-tauri/Cargo.toml plus npm run check for Sprint 66
cargo fmt --manifest-path src-tauri/Cargo.toml
CARGO_TARGET_DIR=/tmp/900project-sprint66-cargo cargo test --lib --bins --tests --manifest-path src-tauri/Cargo.toml
npm run check
git diff --check

This lane upgrades the Rust PDF exporter and the shell copy around it. If the host disk is nearly full, prefer reusing an existing successful CARGO_TARGET_DIR instead of creating a fresh verifier target for every rerun.

Final Closeout Validation

Sprint 67 keeps the focused validation path narrow and maintainer-surface-only:

  • run git ls-files --error-unmatch docs/sprints/sprint-67-final-closeout.md plus node --test scripts/maintainers/evidence-freshness.test.js plus npm run maintainer:evidence:freshness plus git diff --check for Sprint 67
git ls-files --error-unmatch docs/sprints/sprint-67-final-closeout.md
node --test scripts/maintainers/evidence-freshness.test.js
npm run maintainer:evidence:freshness
git diff --check

This lane changes status and drift-guard files only. The Sprint 67 note must be tracked before the focused guard can pass. If a branch updates closeout wording again, keep README.md, the roadmap set, maintainer docs, the Sprint 67 note, and the guard in the same patch set instead of carrying partial status updates across branches.

Temp Artifact Hygiene Validation

Sprint 68 adds one standalone maintainer-operability follow-on for repo-prefixed temp cleanup:

  • run node --test scripts/maintainers/temp-artifact-hygiene.test.js plus npm run maintainer:temp-hygiene plus git diff --check for Sprint 68
node --test scripts/maintainers/temp-artifact-hygiene.test.js
npm run maintainer:temp-hygiene
git diff --check
  • focused command contract: npm run maintainer:temp-hygiene

Use this route when the maintainer question is "are stale 900project-* temp artifacts the real cause of the failure?" rather than "did the product or portable workspace state regress?"

Repo Artifact Hygiene Validation

Sprint 69 adds one standalone maintainer-operability follow-on for generated repo-local evidence and release cleanup:

  • run node --test scripts/maintainers/repo-artifact-hygiene.test.js plus npm run maintainer:artifact-hygiene plus git diff --check for Sprint 69
node --test scripts/maintainers/repo-artifact-hygiene.test.js
npm run maintainer:artifact-hygiene
git diff --check

Iframe Warning Cleanup Validation

Sprint 70 adds one standalone maintainer-operability follow-on for the remaining attachment-preview iframe warnings in src/App.svelte:

  • run ./node_modules/.bin/svelte-check --tsconfig ./tsconfig.json plus ./node_modules/.bin/vite build plus ./node_modules/.bin/vitest run src/App.test.ts src/lib/attachments.test.ts plus git diff --check for Sprint 70
./node_modules/.bin/svelte-check --tsconfig ./tsconfig.json
./node_modules/.bin/vite build
./node_modules/.bin/vitest run src/App.test.ts src/lib/attachments.test.ts
git diff --check
  • focused command contract: npm run maintainer:artifact-hygiene

Use this route when the maintainer question is "did generated evidence or release directories inside the repo root build up?" rather than "did system temp roots fill up?" or "did portable workspace state regress?"

Duplicate Copy Hygiene Validation

Sprint 71 adds one standalone maintainer-operability follow-on for suspicious untracked duplicate-copy shadows of tracked repo files:

  • run node --test scripts/maintainers/duplicate-copy-hygiene.test.js plus npm run maintainer:duplicate-copy-hygiene plus git diff --check for Sprint 71
node --test scripts/maintainers/duplicate-copy-hygiene.test.js
npm run maintainer:duplicate-copy-hygiene
git diff --check
  • focused command contract: npm run maintainer:duplicate-copy-hygiene

Use this route when the maintainer question is "did stale untracked duplicate copies shadow tracked repo content?" rather than "did generated artifacts build up?" or "did temp roots fill up?"

Release Boundary Regression Validation

Sprint 47 adds a repo-owned boundary regression command:

npm run release:boundary

Focused command-level coverage lives in:

node --test scripts/release/release-boundary-regressions.test.js

The broader validation path is:

  • focused command contract: node --test scripts/release/release-boundary-regressions.test.js
  • release-script suite: npm run test:release
  • baseline repo verifier: ./scripts/verify-local.sh

Public Release Foundation Validation

Sprint 72 adds public repository licensing, governance, support, security, package metadata, and release workflow script-path validation:

  • run node --test scripts/release/release-boundary-regressions.test.js plus npm run release:boundary plus git diff --check for Sprint 72
node --test scripts/release/release-boundary-regressions.test.js
npm run release:boundary
git diff --check
  • focused command contract: npm run release:boundary

Use this route when the maintainer question is "does the public release metadata stay aligned with the release workflow script surface?" rather than "did product runtime behavior change?"

The command prints one machine-readable JSON report to stdout on both success and failure. Maintainer tooling and review notes should treat that JSON plus the process exit status as the source of truth for Sprint 47 boundary status rather than paraphrasing the command from memory.

This boundary pack proves:

  • the capability baseline across src-tauri/capabilities/default.json, src-tauri/tauri.conf.json, src-tauri/src/lib.rs, and the reviewed Tauri dependency surface
  • updater build gating for unsigned/dev-style builds, signed builds with no endpoint source, and the windows-offline variant through the real build invocation path
  • workflow-step and child-build env scoping for updater signing/runtime env and Apple notarization inputs
  • the continued absence of generic Tauri shell/filesystem/process/opener/store/CLI plugin surfaces the repo does not need

Runtime-side updater disabled reasons are still covered by the Rust updater tests and the broader baseline verifier. The Sprint 47 command itself is the build-path and release-boundary check.

Expected fail conditions include:

  • capability permissions widening past core:default plus dialog:default
  • generic Tauri shell/filesystem/process/open/reveal style plugins being added
  • updater signing env leaking into standard or offline child builds
  • Apple signing env leaking into non-notarized workflow steps or child builds
  • signed updater builds no longer failing when neither explicit endpoints nor GITHUB_REPOSITORY is configured

Release Candidate Gate Validation

Sprint 74 adds a repo-owned release candidate preflight for the first public v0.1.0 tag:

npm run release:candidate -- --release-tag v0.1.0 --allow-private true --check-remote-tags false --repo-visibility private

Focused command-level coverage lives in:

node --test scripts/release/release-candidate-preflight.test.js

The broader validation path is:

  • focused command contract: node --test scripts/release/release-candidate-preflight.test.js
  • release-script suite: npm run test:release
  • baseline repo verifier: ./scripts/verify-local.sh

Use --allow-private true only for pre-tag dry runs while the GitHub repository is intentionally still private. The focused local dry-run command injects --repo-visibility private and disables only the remote tag lookup so local validation does not depend on gh or network access. The JSON report should show repo visibility as action_required with the action to make the repo public before creating or pushing the release tag. The final pre-tag run should omit --allow-private true, --repo-visibility private, and --check-remote-tags false after maintainer approval makes the repo public.

Maintainer Rotation Drill Validation

Sprint 48 adds a repo-owned maintainer continuity command:

npm run maintainer:rotation:drill

Focused command-level coverage lives in:

node --test scripts/maintainers/rotation-drill.test.js

The broader validation path is:

  • focused command contract: node --test scripts/maintainers/rotation-drill.test.js
  • maintainer drill suite: npm run test:maintainers
  • baseline repo verifier: ./scripts/verify-local.sh

The command prints one machine-readable JSON report to stdout on both success and failure. Maintainer continuity notes should treat that JSON report plus the process exit status as the source of truth for whether the repo still exposes the required drill surface.

This drill proves:

  • the required maintainer docs and shell/package entrypoints still exist together
  • issue intake, fixture selection, validation entrypoints, release lookup, rollback choice, and support interpretation still route through repo-owned docs and commands
  • the current maintainer surface still points at the active Sprint 65 post-polish continuation lane instead of private handoff context

Issue Reproduction Kit Validation

Sprint 49 adds a repo-owned issue handoff command:

npm run maintainer:issue-kit -- \
  --support-bundle /path/to/exported.support-bundle.json \
  --output-dir /path/to/issue-kit

Focused command-level coverage lives in:

node --test scripts/maintainers/issue-reproduction-kit.test.js

The broader validation path is:

  • focused command contract: node --test scripts/maintainers/issue-reproduction-kit.test.js
  • maintainer suite: npm run test:maintainers
  • baseline repo verifier: ./scripts/verify-local.sh

The command prints one machine-readable JSON report to stdout on both success and failure. Treat that JSON plus the process exit status as the source of truth for whether the issue-kit contract succeeded. Focused coverage now also proves that malformed support-bundle JSON is rejected, same-directory reruns do not leak stale broader evidence, and the manifest stays deterministic for the same input state.

Release Witness Pack Validation

Sprint 50 adds a repo-owned release provenance command:

npm run release:witness -- \
  --ledger-path release-publish/release-evidence-ledger.json \
  --output-dir release-witness

Focused command-level coverage lives in:

node --test scripts/release/release-witness-pack.test.js

The broader validation path is:

  • focused command contract: node --test scripts/release/release-witness-pack.test.js
  • release-script suite: npm run test:release
  • baseline repo verifier: ./scripts/verify-local.sh

Focused coverage now also proves that witness output cannot be written into the publish directory and that reruns clear stale managed optional evidence before rewriting the witness pack.

Maintainer Evidence Freshness Validation

Sprint 53 adds a repo-owned maintainer evidence checker:

npm run maintainer:evidence:freshness

Focused command-level coverage lives in:

node --test scripts/maintainers/evidence-freshness.test.js

The broader validation path is:

  • focused command contract: npm run maintainer:evidence:freshness
  • focused test coverage: node --test scripts/maintainers/evidence-freshness.test.js
  • baseline repo verifier: ./scripts/verify-local.sh

The checker prints one machine-readable JSON report to stdout on both success and failure. Treat that JSON plus the process exit status as the source of truth for whether the current maintainer docs, evidence names, and continuation-status contract still match the repo-owned contract.

Recovery Incident Fixture Pack Validation

Sprint 54 adds a repo-owned replay-pack command for drill-derived recovery incidents:

npm run maintainer:recovery:fixtures

Focused command-level coverage lives in:

node --test scripts/maintainers/recovery-incident-fixtures.test.js

The broader validation path is:

  • focused command contract: npm run maintainer:recovery:fixtures
  • focused test coverage: node --test scripts/maintainers/recovery-incident-fixtures.test.js
  • maintainer suite: npm run test:maintainers
  • baseline repo verifier: ./scripts/verify-local.sh

The command prints one machine-readable JSON report to stdout and writes artifacts/recovery-incident-fixtures/report.json. Treat that JSON plus the process exit status as the source of truth for whether the repo can still publish public-safe recoverable, blocked, and manual-intervention replay cases from the maintained drill output.

Contributor Starter Validation

Sprint 52 adds a repo-owned contributor starter checker:

npm run contributor:starter:check

Focused command-level coverage lives in:

node --test scripts/contributors/starter-kit.test.js

The broader validation path is:

  • focused command contract: npm run contributor:starter:check
  • focused test coverage: node --test scripts/contributors/starter-kit.test.js
  • baseline repo verifier: ./scripts/verify-local.sh

The checker prints one machine-readable JSON report to stdout on both success and failure. Treat that JSON plus the process exit status as the source of truth for whether the contributor-safe command and guardrail surface still matches the documented first-contribution lane.

Contributor Validation Sandbox

Sprint 55 adds one repo-owned contributor validation sandbox checker:

npm run contributor:validation:sandbox

Focused command-level coverage lives in:

node --test scripts/contributors/validation-sandbox.test.js

The broader validation path is:

  • focused command contract: npm run contributor:validation:sandbox
  • focused test coverage: node --test scripts/contributors/validation-sandbox.test.js
  • contributor starter boundary: npm run contributor:starter:check
  • baseline repo verifier: ./scripts/verify-local.sh

The checker prints one machine-readable JSON report to stdout on both success and failure. Treat that JSON plus the process exit status as the source of truth for whether the contributor-safe validation profiles, evidence paths, and maintainer-only stop boundaries still match the documented sandbox.

Validation Receipt Validation

Sprint 57 adds one repo-owned validation handoff command:

npm run maintainer:validation:receipt -- \
  --profile closeout \
  --output-path artifacts/validation-receipts/closeout.json

If GitHub Actions failed before runner startup for billing reasons, rerun the same closeout receipt path with the documented caveat:

npm run maintainer:validation:receipt -- \
  --profile closeout \
  --caveat ci-billing-blocked \
  --output-path artifacts/validation-receipts/closeout.json

Focused command-level coverage lives in:

node --test scripts/maintainers/validation-receipts.test.js

The broader validation path is:

  • focused command contract: npm run maintainer:validation:receipt -- --profile <id> --output-path <path>
  • focused test coverage: node --test scripts/maintainers/validation-receipts.test.js
  • contributor profile owner: npm run contributor:validation:sandbox
  • maintainer route owners: npm run maintainer:evidence:freshness, npm run maintainer:durability:check, and npm run maintainer:rotation:drill
  • baseline repo verifier: ./scripts/verify-local.sh

Use this route when the question is "what exactly did we run, what artifact proves it, and what environment caveat still matters?" The receipt is a local declaration over the maintained command surface, not another validation runner and not execution telemetry.

Fixture Provenance Ledger Validation

Sprint 58 adds one repo-owned artifact-ownership command:

npm run maintainer:provenance:ledger

That command writes artifacts/fixture-provenance-ledger/report.json by default. To redirect it elsewhere:

npm run maintainer:provenance:ledger -- \
  --output-path /tmp/900project-fixture-provenance.json

Focused command-level coverage lives in:

node --test scripts/maintainers/fixture-provenance-ledger.test.js

The broader validation path is:

  • focused command contract: npm run maintainer:provenance:ledger
  • focused test coverage: node --test scripts/maintainers/fixture-provenance-ledger.test.js
  • maintainer routing owners: npm run maintainer:evidence:freshness and npm run maintainer:rotation:drill
  • baseline repo verifier: ./scripts/verify-local.sh

Use this route when the real question is "which repo-owned family owns this public-safe artifact, how do I rerun it, and is the missing artifact expected?" The ledger documents ownership and retention; it does not replace the underlying fixture, release, recovery, or validation command.

Review Dossier Validation

Sprint 59 adds one repo-owned cross-surface reviewer handoff command:

npm run maintainer:review:dossier -- \
  --validation-receipt artifacts/validation-receipts/closeout.json \
  --issue-kit-dir /tmp/900project-issue-kit \
  --output-dir /tmp/900project-review-dossier

Focused command-level coverage lives in:

node --test scripts/maintainers/review-dossier-pack.test.js

The broader validation path is:

  • focused command contract: npm run maintainer:review:dossier -- --validation-receipt <path> --issue-kit-dir <dir> --output-dir <dir>
  • focused test coverage: node --test scripts/maintainers/review-dossier-pack.test.js
  • maintainer routing owners: npm run maintainer:evidence:freshness and npm run maintainer:rotation:drill
  • baseline repo verifier: ./scripts/verify-local.sh

Use this route when one reviewer handoff needs validation receipts, issue or fixture context, and multiple repo-owned evidence families in one public-safe folder. The dossier is a composition layer over reviewed evidence, not a generic archive builder.

Recovery And Durability Drill Validation

Sprint 51 adds a repo-owned recovery composition command:

npm run maintainer:recovery:drill

Focused Rust coverage lives in:

CARGO_TARGET_DIR=/tmp/900project-sprint51-cargo cargo test --manifest-path src-tauri/Cargo.toml recovery_drill -- --nocapture
CARGO_TARGET_DIR=/tmp/900project-sprint51-cargo cargo test --manifest-path src-tauri/Cargo.toml --bin recovery-drill -- --nocapture

The broader validation path is:

  • focused core coverage: cargo test --manifest-path src-tauri/Cargo.toml recovery_drill -- --nocapture
  • focused CLI coverage: cargo test --manifest-path src-tauri/Cargo.toml --bin recovery-drill -- --nocapture
  • command contract: npm run maintainer:recovery:drill
  • baseline repo verifier: ./scripts/verify-local.sh

The command prints one machine-readable JSON report to stdout and writes artifacts/recovery-drill/report.json. That report should point at:

  • compatibility-matrix/report.json under the drill root
  • one recoverable round-trip scenario
  • one recoverable repair-bounded orphan-blob scenario
  • one blocked newer-bundle scenario
  • one manual-intervention checksum-mismatch scenario

Focused coverage now also proves that the recoverable backup path stays inside SQLite-backed workspace durability, while attachment durability remains validated through bundle import and integrity-audit artifacts instead of pretending the backup alone preserved attachment blobs.

Durability Stewardship Validation

Sprint 56 adds one repo-owned durability stewardship checker:

npm run maintainer:durability:check

Focused command-level coverage lives in:

node --test scripts/maintainers/durability-stewardship.test.js

The broader validation path is:

  • focused command contract: npm run maintainer:durability:check
  • focused test coverage: node --test scripts/maintainers/durability-stewardship.test.js
  • recovery evidence anchor: npm run maintainer:recovery:drill
  • compatibility evidence anchor: npm run compatibility:matrix:run
  • baseline repo verifier: ./scripts/verify-local.sh

Use this route when the question is about backup rotation, restore-verification cadence, .900proj retention, or issue-safe recovery evidence retention for long-lived offline workspaces.

Do not use it as a substitute for local machine troubleshooting. If the real problem is disk pressure, temp-directory cleanup, placeholder checkout hydration, or a stalled local toolchain, stay in the environment-specific guidance in this file and the maintainer issue-triage path.

Maintainer Frontend Surface Validation

Sprint 61 adds focused frontend regression coverage for the maintainer-facing transfer and integrity surfaces:

./node_modules/.bin/vitest run src/lib/maintainer-panel.test.ts src/lib/file-dialog.test.ts
./node_modules/.bin/svelte-check --tsconfig ./tsconfig.json
./node_modules/.bin/eslint src/lib/maintainer-panel.ts src/lib/maintainer-panel.test.ts src/lib/file-dialog.test.ts

Focused coverage now proves:

  • support-bundle output-path validation and save-filter wiring stay explicit
  • import-review handoff output-path derivation stays deterministic and user overrides are preserved
  • workspace-integrity audit finding formatting, evidence summarization, and orphan-blob repair availability stay testable through pure helpers rather than ad hoc component-only assertions

The broader validation path is:

  • focused command contract: ./node_modules/.bin/vitest run src/lib/maintainer-panel.test.ts src/lib/file-dialog.test.ts
  • shell typecheck: ./node_modules/.bin/svelte-check --tsconfig ./tsconfig.json
  • focused lint coverage: ./node_modules/.bin/eslint src/lib/maintainer-panel.ts src/lib/maintainer-panel.test.ts src/lib/file-dialog.test.ts
  • baseline repo verifier: ./scripts/verify-local.sh

Work Calendar And Capacity Profile Validation

Sprint 63 adds one portable schedule contract for reports, utilization, and calendar highlighting:

CARGO_TARGET_DIR=/tmp/900project-sprint63-cargo cargo test --manifest-path src-tauri/Cargo.toml --lib --bins --tests
./node_modules/.bin/vitest run src/lib/schedule.test.ts src/lib/calendar.test.ts
./node_modules/.bin/svelte-check --tsconfig ./tsconfig.json

Focused coverage now proves:

  • work calendars and per-member capacity overrides persist through the backend schema and command surface
  • report snapshots, CSV output, and utilization summaries explain their working-day and holiday basis from local data
  • the month calendar highlights non-working days and configured holidays from the same project-local schedule contract

The broader validation path is:

  • focused Rust contract: CARGO_TARGET_DIR=/tmp/900project-sprint63-cargo cargo test --manifest-path src-tauri/Cargo.toml --lib --bins --tests
  • focused frontend coverage: ./node_modules/.bin/vitest run src/lib/schedule.test.ts src/lib/calendar.test.ts
  • shell typecheck: ./node_modules/.bin/svelte-check --tsconfig ./tsconfig.json
  • baseline repo verifier: ./scripts/verify-local.sh

Budget Actuals And Expense Tracking Validation

Sprint 64 extends the portable budget model with expense entries, actual-versus-plan report fields, and bundle-portable budget actuals:

CARGO_TARGET_DIR=/tmp/900project-sprint64-cargo cargo test --manifest-path src-tauri/Cargo.toml --lib --bins --tests
./node_modules/.bin/vitest run src/lib/budget.test.ts
./node_modules/.bin/svelte-check --tsconfig ./tsconfig.json

Focused coverage now proves:

  • expense entries persist through the backend schema, command surface, and change-log-aware bundle contract
  • project, category, and donor-linked budget actuals stay integer-exact in report snapshots and export artifacts
  • the shell keeps budget planning and expense-entry UX aligned with the same portable budget snapshot

The broader validation path is:

  • focused Rust contract: CARGO_TARGET_DIR=/tmp/900project-sprint64-cargo cargo test --manifest-path src-tauri/Cargo.toml --lib --bins --tests
  • focused frontend coverage: ./node_modules/.bin/vitest run src/lib/budget.test.ts
  • shell typecheck: ./node_modules/.bin/svelte-check --tsconfig ./tsconfig.json
  • baseline repo verifier: ./scripts/verify-local.sh

Pointer Drag/Drop And Dependency Visuals Validation

Sprint 65 adds pointer-first board ergonomics and richer Gantt dependency cues without changing the backend mutation contract:

./node_modules/.bin/vitest run src/App.test.ts src/lib/task-board.test.ts src/lib/gantt.test.ts
./node_modules/.bin/svelte-check --tsconfig ./tsconfig.json

Focused coverage now proves:

  • Kanban pointer-drop planning still reuses the deterministic ordering model instead of inventing a second task-move API
  • pointer drag is withheld when filtered board state would hide project tasks from persisted ordering decisions
  • Gantt dependency visuals derive from existing dependency type, lag, and critical-path facts without widening backend contracts

The broader validation path is:

  • focused frontend coverage: ./node_modules/.bin/vitest run src/App.test.ts src/lib/task-board.test.ts src/lib/gantt.test.ts
  • shell typecheck: ./node_modules/.bin/svelte-check --tsconfig ./tsconfig.json
  • evidence drift guard: npm run maintainer:evidence:freshness
  • evidence drift tests: node --test scripts/maintainers/evidence-freshness.test.js
  • baseline repo verifier: ./scripts/verify-local.sh

The focused App test stubs document.elementFromPoint directly because jsdom does not provide browser hit-testing. Keep that stub in pointer-drop component tests instead of weakening the application code.

Rust Validation Notes

  • Rust validation can block on stale Cargo build-directory locks in this environment.
  • The verification script now forces Rust checks into an isolated CARGO_TARGET_DIR per run to avoid unrelated lock contention.
  • If you need to run commands manually, prefer setting CARGO_TARGET_DIR explicitly when there are other cargo sessions on the machine.

Example:

CARGO_TARGET_DIR=/tmp/900project-manual-check cargo check --manifest-path src-tauri/Cargo.toml
CARGO_TARGET_DIR=/tmp/900project-manual-check cargo test --lib --bins --tests --manifest-path src-tauri/Cargo.toml
  • In this environment, plain cargo test --manifest-path src-tauri/Cargo.toml reached a quiet rustdoc --test phase after the unit-test banner and did not return promptly. Use the explicit --lib --bins --tests form for reliable sprint closeout unless you are intentionally validating doc tests.

Frontend Validation Notes

  • The repo contract remains pnpm, and the repo now carries a committed pnpm-lock.yaml so CI and release workflows can use --frozen-lockfile.
  • Local validation defaults to local tool binaries because package runners have repeatedly stalled in this Codex desktop environment even when the underlying tools return cleanly.
  • When a package-runner validation is needed, prefer the packageManager-pinned pnpm script over a global Homebrew/Corepack shim. A broken global shim should not make the repository look broken.
  • A local pnpm store can have metadata for the pinned version while still missing tarballs needed by node_modules. In that case, rerun the pinned install path with network access rather than editing package policy.
  • After any dependency-specifier change in package.json, rerun a frozen install path before pushing. pnpm install --frozen-lockfile will fail if the importer specifier: values in pnpm-lock.yaml still reflect the old range or pin, even when the resolved package version did not change.
  • This machine did not initially have pnpm installed. Early bootstrap validation used npm without changing repo policy.
  • If frontend validation appears to hang in the Codex desktop execution environment, rerun the same commands in a normal terminal session before treating the result as a code failure. This has occurred intermittently even for simple Node-based commands.
  • compressed,dataless placeholders can exist inside node_modules as well as repo source files on this Mac. If svelte-check, eslint, vitest, vite build, or even node -e "import('./vite.config.ts')" idles with no diagnostics, inspect both the repo tree and the dependency tree:
ls -lO src/App.svelte src/lib/i18n.ts
find node_modules -flags +dataless | head
  • If placeholders are present, hydrate them before retrying the same validation command:
brctl download src
find node_modules -flags +dataless -print0 | xargs -0 brctl download
  • Sprint 3 repeated the same behavior for npm run build, npm run lint, and npm run test, with timed subprocess runs printing only the command banner before stalling. Record that exact outcome in sprint notes when it happens.
  • Sprint 8 repeated the pattern for npm run test, npm run check, Node-20 npm run check, targeted npx eslint, and single-file npx vitest. At that point the issue is broader than one script or one Node major version, so do not waste sprint closeout time pretending a local green run is available in this execution environment.
  • Sprint 9 repeated the pattern again for npm run check, which printed only the svelte-check --tsconfig ./tsconfig.json startup banner before manual interruption. Treat that as the same known environment limitation, not as a new repo-specific failure, unless a normal terminal reproduces it.
  • Sprint 10 repeated the same behavior for npm exec tsc -- -p tsconfig.json --noEmit, which stayed attached with no diagnostics until manual interruption. Record it as the same Codex-local Node stall family unless a normal terminal reproduces the hang.
  • Sprint 11 repeated the same behavior for npm run check, npm run test -- src/lib/i18n.test.ts, and npm exec prettier -- --write ..., all of which printed their startup banner and then remained attached without diagnostics. Treat that as the same Codex-local Node stall family unless a normal terminal reproduces it.
  • Sprint 12 confirmed a more reliable local fallback in the same environment: npm exec -- svelte-check --tsconfig ./tsconfig.json, npm exec -- eslint ..., npm exec -- vitest run, and npm exec -- vite build all returned cleanly while pnpm run ... still behaved inconsistently. Use VERIFY_FRONTEND_RUNNER=npm-exec instead of pretending the pnpm run path is the only local workflow.
  • Sprint 13 hit a different post-repair variant: after replacing broken git metadata, ./scripts/verify-local.sh stalled in the pnpm run check -> svelte-check --tsconfig ./tsconfig.json phase without diagnostics, npm exec -- svelte-check --tsconfig ./tsconfig.json failed with ERR_INVALID_PACKAGE_CONFIG inside the local svelte-check package, and both npm exec -- vitest run src/lib/i18n.test.ts and npm exec -- vite build hung again without diagnostics. Treat that as another local toolchain integrity problem first; rerun from a normal terminal and prefer CI before assuming the repo change itself is broken.
  • Sprint 20 showed the stall pattern again on both fallback paths: ./node_modules/.bin/vitest run src/lib/i18n.test.ts stayed attached with no output, and npm exec -- eslint src/App.svelte src/lib/i18n.ts src/lib/i18n.test.ts did the same until manual interruption. When both local-bin and npm-exec stall silently, stop spending sprint time on local frontend retries and use CI or a normal terminal instead.
  • Sprint 24 exposed a second local-binary failure mode on this machine: ./node_modules/.bin/svelte-check, ./node_modules/.bin/eslint, and ./node_modules/.bin/tsc can fail immediately under Node 22 with ERR_INVALID_PACKAGE_CONFIG while resolving pnpm-installed tool packages. Treat that as local toolchain integrity noise first, then retry through a normal terminal or CI instead of attributing it to the repo change by default.
  • Do not quietly remove or skip frontend validation from sprint closeout; record the behavior and keep the docs current if the environment constraint changes.

Closeout Expectations

Before merging a sprint branch:

  1. Run the baseline verification script.
  2. Run the sprint-specific checks introduced by the sprint; keep the newest additions explicit below so closeout remains auditable without copying stale local paths.
  3. Keep the newest merge-closeout additions explicit in the checklist:
    • run npm run contributor:starter:check for Sprint 52
    • run npm run contributor:validation:sandbox for Sprint 55
    • run npm run maintainer:durability:check for Sprint 56
    • run npm run maintainer:validation:receipt -- --profile closeout --output-path artifacts/validation-receipts/closeout.json for Sprint 57
    • run npm run maintainer:provenance:ledger for Sprint 58
    • run npm run maintainer:review:dossier -- --validation-receipt <path> --issue-kit-dir <dir> --output-dir <dir> for Sprint 59
    • run npm run maintainer:evidence:freshness plus node --test scripts/maintainers/evidence-freshness.test.js for Sprint 60
    • run ./node_modules/.bin/vitest run src/lib/maintainer-panel.test.ts src/lib/file-dialog.test.ts for Sprint 61
    • run node --test scripts/release/release-artifacts.test.js scripts/release/release-verification.test.js scripts/release/release-evidence-ledger.test.js scripts/release/release-publish-assets.test.js scripts/release/release-boundary-regressions.test.js scripts/release/release-witness-pack.test.js plus npm run release:boundary for Sprint 62
    • run CARGO_TARGET_DIR=/tmp/900project-sprint63-cargo cargo test --manifest-path src-tauri/Cargo.toml --lib --bins --tests plus ./node_modules/.bin/vitest run src/lib/schedule.test.ts src/lib/calendar.test.ts for Sprint 63
    • run CARGO_TARGET_DIR=/tmp/900project-sprint64-cargo cargo test --manifest-path src-tauri/Cargo.toml --lib --bins --tests plus ./node_modules/.bin/vitest run src/lib/budget.test.ts plus ./node_modules/.bin/svelte-check --tsconfig ./tsconfig.json for Sprint 64
    • run ./node_modules/.bin/vitest run src/App.test.ts src/lib/task-board.test.ts src/lib/gantt.test.ts plus ./node_modules/.bin/svelte-check --tsconfig ./tsconfig.json plus npm run maintainer:evidence:freshness plus node --test scripts/maintainers/evidence-freshness.test.js for Sprint 65
    • run cargo fmt --manifest-path src-tauri/Cargo.toml plus CARGO_TARGET_DIR=/tmp/900project-sprint66-cargo cargo test --lib --bins --tests --manifest-path src-tauri/Cargo.toml plus npm run check for Sprint 66
    • run git ls-files --error-unmatch docs/sprints/sprint-67-final-closeout.md plus node --test scripts/maintainers/evidence-freshness.test.js plus npm run maintainer:evidence:freshness plus git diff --check for Sprint 67
    • run node --test scripts/maintainers/temp-artifact-hygiene.test.js plus npm run maintainer:temp-hygiene plus git diff --check for Sprint 68
    • run node --test scripts/maintainers/repo-artifact-hygiene.test.js plus npm run maintainer:artifact-hygiene plus git diff --check for Sprint 69
    • run ./node_modules/.bin/svelte-check --tsconfig ./tsconfig.json plus ./node_modules/.bin/vite build plus ./node_modules/.bin/vitest run src/App.test.ts src/lib/attachments.test.ts plus git diff --check for Sprint 70
    • run node --test scripts/maintainers/duplicate-copy-hygiene.test.js plus npm run maintainer:duplicate-copy-hygiene plus git diff --check for Sprint 71
    • run node --test scripts/release/release-boundary-regressions.test.js plus npm run release:boundary plus git diff --check for Sprint 72
    • run npm run check plus npm test -- --run plus npm run build plus git diff --check for Sprint 73
    • run node --test scripts/release/release-candidate-preflight.test.js plus npm run release:candidate -- --release-tag v0.1.0 --allow-private true --check-remote-tags false --repo-visibility private plus git diff --check for Sprint 74
    • run ./node_modules/.bin/vitest run src/App.test.ts plus npm run check plus npm run build plus git diff --check for Sprint 75
    • add --caveat ci-billing-blocked when GitHub Actions failed before runner startup for billing reasons and local closeout proof surfaces carry the merge handoff
  4. Update the relevant docs.
  5. Add new learnings to LEARNINGS.md.
  6. Record any validation exceptions explicitly in the sprint notes.