UPDATE THIS FILE when making architectural changes, adding patterns, or changing conventions.
Opcore is the code-intelligence and robustness monorepo for graph context, edit planning, pre-write validation, repo robustness scanning/measurement, and the standalone ASP Core check provider for coding agents. The accepted runtime/CLI boundary is hybrid: Rust graph core with TypeScript contracts, CLI router, edit, validation, validation-typescript, validation-clone, ASP provider facade, npm/Opcore facade, and managed descriptor artifacts. See @docs/architecture/runtime-cli-ard.md and @docs/planning/opcore-alpha-roadmap.md before changing language, package, provider, product, or CLI ownership.
| Concept | Meaning |
|---|---|
| Graph provider | Owns source extraction, persistent graph facts, freshness metadata, graph query contracts, and FTS search index artifacts. |
| Edit planner | Owns symbol-aware rename, move, signature, patch, and tree edits; it must validate full edit plans, not isolated files. |
| Validation engine | Owns mechanical checks, hypothetical validation, check manifests, and failure policy. |
| Opcore product facade | Thin user-facing robustness loop over graph, validation, edit, and ASP-provider packages: read-only scan/status/check/measure by default and approval-gated init. |
| Command adapters | Package-owned graph, edit, check, and validate dispatch surfaces used by canonical opcore advanced routes. |
| Repository self-validation | Opcore validates its own changed implementation surface through npm run opcore:self-check and .opcore/config. |
| Concept | Primary File |
|---|---|
| Runtime/CLI ARD | @docs/architecture/runtime-cli-ard.md |
| Graph hub inventory | @docs/architecture/graph-hub-inventory.md |
| Opcore alpha roadmap | @docs/planning/opcore-alpha-roadmap.md |
| Opcore metrics/report/history | packages/opcore/src/reporting.ts |
| Latency budgets and trend gate | docs/performance/latency-budgets.json, scripts/check-latency-budgets.mjs |
| Public contracts | @packages/contracts/ |
| Public contracts barrel | packages/contracts/src/index.ts (API-only exports; domain modules own implementations) |
| Contract JSON schema | packages/contracts/schemas/opcore-contracts.schema.json |
| Command router package | @packages/opcore/src/advanced/ |
| Graph provider package track | @packages/graph/ |
| Graph SQLite store | crates/graph-core/src/store.rs |
| Clone graph-core subcommand | crates/graph-core/src/clone/mod.rs |
| Edit package track | @packages/edit/ |
| Validation package track | @packages/validation/ |
| Validation policy composition | @packages/validation-policy/ |
| Validation file view | packages/validation/src/overlays.ts |
| Validation graph client | packages/validation/src/graph-client.ts |
| Documentation validation composition | packages/validation-docs/src/checks.ts, packages/validation-docs/src/document-check.ts |
| Rust validation adapter | @packages/validation-rust/ |
| TypeScript validation adapter | @packages/validation-typescript/ |
| Clone validation adapter | @packages/validation-clone/ |
| Opcore product facade | @packages/opcore/ |
| Opcore scan report seam | packages/opcore/src/reporting.ts |
| ASP Core check provider facade | @packages/asp-provider/ |
| ASP warm inspect/edit session | packages/opcore/src/advanced/asp-warm/, @docs/architecture/asp-warm-session-ard.md |
| ASP provider manifest generator | scripts/write-asp-provider-manifest.mjs writes canonical asp-server.json plus retained provisional install metadata. |
| Golden fixtures and reference evidence | @packages/fixtures/ |
| Graph release fixture | packages/fixtures/graph-release/release-readiness-fixture.json |
| Graph release receipt | docs/release/graph-release-receipt.json |
| Graph release payload checksum target | docs/release/graph-release-receipt.payload.json |
| Graph release handoff | @docs/release/graph-release-handoff.md |
| Release receipt | docs/release/release-receipt.json |
| Release receipt summary | @docs/release/release-receipt.summary.md |
| Cutover receipt | docs/release/cutover-receipt.json |
| Cutover receipt summary | @docs/release/cutover-receipt.summary.md |
| ASP dogfood receipt | docs/release/asp-dogfood-receipt.json |
| ASP dogfood receipt summary | @docs/release/asp-dogfood-receipt.summary.md |
| Secret scan allowlist | @docs/release/secret-scan-allowlist.json |
| Release receipt generator | scripts/generate-release-receipt.mjs |
| Cutover receipt generator | scripts/generate-cutover-receipt.mjs |
| ASP dogfood receipt generator | scripts/generate-asp-dogfood-receipt.mjs |
| Workspace checks | scripts/check-workspace.mjs |
| Package dry-run checks | scripts/check-packages.mjs |
| Provenance checks | scripts/check-provenance.mjs |
| Opcore self-check | scripts/run-opcore-self-check.mjs, .opcore/config |
| Local CI-equivalent gate | @scripts/ci/run-local-ci-equivalent.sh |
| Zeroshot setup | @.zeroshot/settings.json |
| GitHub Actions | @.github/workflows/ |
| Tests | @tests/ |
- Run
npm run setupafter cloning or entering a fresh worktree. It installs repository dependencies only and must leave the worktree clean. - Run
npm run opcore:self-checkafter building. It requires.opcore/configto select every registered check explicitly with no disabled checks, validates changed-compatible checks in introduced mode against the configured base ref, prepares fresh graph evidence for incompatible repo-wide checks, and requires zero diagnostics across the complete manifest - WHY: self-validation must fail when a new check is not explicitly governed or any supported language loses complexity, tool, graph, docs, or clone coverage. scripts/ci/run-local-ci-equivalent.shruns normal CI plus the Opcore self-check. Its docs/agent-guidance fast path uses only repository-native workspace, provenance, build, and self-validation commands.- Zeroshot worktrees run
npm ciand the same local CI-equivalent command proof - WHY: humans, agents, CI, and ship clusters must exercise one repository-owned validation surface. - Root
.npmrcsetsloglevel=silent- WHY: JSON-emitting npm scripts such asnpm run asp-dogfood:check -- --jsonmust write parseable JSON to redirected stdout without npm lifecycle preambles. npm run test:ciroutes throughscripts/run-test-ci.mjs: it runs the parallel-safe Node test files first, runstests/validation-python.test.mjsseparately because its real subprocess fixtures can exhaust CI process slots under the parallel suite, then runstests/native-packaging-policy.test.mjsseparately with receipt gates skipped - WHY: Python compiler-truth tests need deterministic process availability, and the native packaging policy test intentionally mutates native package artifacts while exercising aggregate dry-run failures.- CI provisions
cargo-udeps0.1.61 withnightly-2026-07-27, selects that exact toolchain forrust.unused-depsthroughOPCORE_RUST_NIGHTLY_TOOLCHAIN, and provisionsrust-code-analysis-cli0.0.25 forrust.function-metrics; the unused-deps adapter defaults to the conventionalnightlyselector elsewhere - WHY: strict self-validation must execute both retained Rust tool authorities without replacing stable as the repository's default Rust toolchain or allowing either CI authority to float. - Graph-owned transitional
opcore graph serve --repo <repo>starts the graph package stdio/MCP bridge over graph-core JSONL;--repodefaults to cwd, supports ping/status/query/search/shutdown, injects missing nested query repos, and returns typed startup/frame/provider failures. - #126 ships graph-core through bundled internal Opcore native packages
@the-open-engine/opcore-graph-core-darwin-arm64,@the-open-engine/opcore-graph-core-darwin-x64, and@the-open-engine/opcore-graph-core-linux-x64;packages/graphresolves only matching package metadata and never probespackages/graph/dist/native, sibling checkouts, or PATH. - Release flow is
dev -> main: CI runs ondevandmain, PRs tomainmust come fromdev, and.github/workflows/release.ymlauto-publishes npm package version0.2.1with dist-taglatestafter theCIworkflow succeeds onmain. Each release must provide readable notes atdocs/release/v<version>.md; the workflow uses that file verbatim for the GitHub release. The CI native jobs upload tarred native package directories soopcore-graph-coreexecute bits survive artifact transfer; aggregate CI and release publish must setOPCORE_REQUIRE_ALL_NATIVE_PACKAGES=1after extracting all three native artifacts, andscripts/release-dry-run.mjsthen validates package-local executable binaries/checksums without rebuilding graph-core - WHY: aggregate and publish proof must consume runnable per-target artifacts produced by native jobs, not a local Linux rebuild or non-executable download. - #19 graph discovery excludes generated/private/dependency roots even without repo ignore files:
.git,node_modules,.pnpm,vendor,dist,target,.agents,.claude,.codex,.gemini,.lattice, and.opencode- WHY: cache/vendor/provider mirror changes must not create graph facts, freshness changes, validation input, or FTS rows. - #17/#19/#21 source/coverage policy is reconciled across graph-core, validation, and Opcore status/metrics: graph-extractable TypeScript, JavaScript, Python
.py/.pyi, and Rust.rs; validation-supported TS/JS variants, Python source/stubs, Rust source/includes, andCargo.toml; retainedCargo.lock; unsupported/degraded stacks and missing Python tools are counted honestly. - #16 Python generated/private/dependency roots are excluded from discovery and status census:
.venv,venv,env,__pycache__,.eggs,build,.tox,.mypy_cache,.pytest_cache,.ruff_cache,site-packages,*.egg-info, and*.dist-info- WHY: dependency/cache artifacts must not create graph freshness or coverage evidence. - #17 Python export metadata is best-effort:
__all__wins when present, otherwise the leading-underscore convention marks module-level public names; fileexports[]entries must include policy and supportedSymbol - WHY: Python has no enforced export boundary. - #244
python.syntaxresolves one concrete interpreter through the Python project resolver, executes that exact interpreter with an isolated versioned JSON compile protocol over sorted.py/.pyiafter-state content, and reports ranged/provenanced compiler diagnostics plus fine-grained outcomes. Parser-success overrides and hand-written grammar heuristics are forbidden; malformed output, nonzero exits, signals, and timeouts fail closed - WHY: syntax truth, target-version truth, and tool provenance must come from the same compiler invocation without mutating the source repo. - #246 makes
@the-open-engine/opcore-validation-pythonthe sole dynamic owner ofopcore.python.project-context.v1: every Python target resolves against its nearest project boundary through an injected read/list/exists/realpath workspace view, smol-toml AST config/build metadata, exact interpreter/tool/build probes, and after-state content. Missing realpath evidence is ambiguous, deleted overlays cannot remain discovery markers, and declared constraints never become invented exact versions. Validation, status, scan, init/install preview, metrics, ASP, and installed execution must reuse the resulting project key, context fingerprint, outcome, and provenance; ASP workspace/config reads must remain host-callback-only. Static descriptors advertise only the schema, outcome vocabulary, read-only behavior, and no-install guarantee - WHY: root-scoped and duplicate project/environment discovery validates nested monorepo files with the wrong interpreter and makes surfaces disagree. #256/#257 makepython.typesselect and execute exactly one mypy or Pyright authority per canonical project. Mypy uses first-match config precedence and strict NDJSON. Pyright preservespyrightconfig.jsonprecedence over[tool.pyright], recursive repo-confined extends, and config-driven source/stub semantics while consuming only complete--outputjson. Both authorities use the same isolated exact after-state, portable receipt, selected interpreter, bounded process-tree runner, and sanitized HOME/XDG/cache/temp environment. Availability never selects an authority or permits fallback. Malformed, partial, contradictory, version/count-mismatched, out-of-repo, fatal, or stderr protocol evidence fails closed, and every project attempt emitsopcore.python.validation-capability-runevidence - WHY: host config/imports, source mutation, orphaned checker descendants, availability, human-output parsing, or check-level summaries cannot prove which project/config/after-state produced type evidence. - #258 keeps
python.ruff-lintandpython.ruff-formatseparate frompython.source-hygieneand opt-in through explicit selection or.opcore/configdefaults. They execute the #246-selected Ruff over a temporary #245 after-state workspace with fixes, writes, and caches disabled; lint consumes JSON and format uses bounded exit-code refinement. Closest target-applicable.ruff.toml,ruff.toml, or[tool.ruff]configuration searches through the repository root across nested Python project boundaries, partitions project execution, requires non-symlink realpath evidence for every selected or recursively extended config, and materializes only that config closure. Python types and Ruff share thepackages/validation-python/src/python-execution-workspace.tsprimitive and sanitized HOME/XDG/TMP/PATH runtime for after-state fingerprinting, materialization, execution isolation, and cleanup while capability code selects its own support files. Ruff receipts use the sharedafterStateManifestFingerprintfield and portable executable/argv locators. Missing Ruff degrades status only while a Ruff check is active, and metrics require executed capability receipts - WHY: optional source tooling must never be probed, invoked, counted, or reported as enforced when policy did not select it, target-local configuration must not leak across files, host state must not affect results, and parallel materializers can make tool inputs diverge from receipts. - #209 makes Rust graph-core the sole parser/resolver for Python repo imports.
@the-open-engine/opcore-graphmaterializes supplied.py/.pyiafter-state files only in an isolated temporary repo and returns canonical directedIMPORTS_FROMfile edges; validation-python owns only the structural analyzer contract, visible-file enumeration, cached target/transitive closure, and edge consumption. Opcore, advanced validation, validation-policy, and ASP inject the graph adapter; missing/failed/malformed analysis is an infrastructure failure, never empty success - WHY: a second TypeScript import grammar/resolver diverges on multiline syntax, overlays, packages, stubs, namespaces, and src layouts. - #197 makes hypothetical graph evaluation exact-state: validation creates one
ValidationFileViewper before/after state and owns one disposable graph session for that view; graph materializes the complete visible TS/TSX/JS/JSX, Python.py/.pyi, and Rust.rsuniverse plus roottsconfig.jsoninto a bounded isolated root, builds graph-core once, shares the immutable session across checks, and removes it on every exit. Introduced mode must use distinct before/after snapshots, ASP listings must preserve host truncation, and exact-state construction/query failure is non-pass even when persistent graph mode is optional - WHY: a persistent target-repo graph, missing alias configuration, or incomplete listing cannot describe hypothetical file contents and must never produce a false clean pre-write result. - #19 requires graph status to preserve real WAL checkpoint evidence from the latest pipeline summary and release gates to fail missing/fabricated WAL evidence - WHY: freshness and checkpoint pressure must remain host-visible provider facts.
- #19 treats
opcore graph serveas the stdio/MCP hot-query replacement, not a Unix socket, with parallel independent serve sessions as the supported concurrency evidence. opcore-asp-provider --stdiois the transitional provider binary for the standalone ASP Core check provider; it uses host workspace callbacks and Opcore validation only.opcore asp serve --stdiois a hidden host-launched warm ASP session for inspect/edit/check underpackages/opcore/src/advanced/asp-warm/; it is intercepted before the public router, omitted fromopcore --help, keeps lifecycle state under.opcore/asp/, never auto-spawns, never stays always-on beyond its idle timeout, and never mutates source files - WHY: agents may need warm inspect/edit latency without making ASP a public human command group or changing the cold check provider.- #120 ASP dogfood uses
npm run asp-dogfood:checkwith a temporaryASP_HOME, a built adjacentagent-server-protocolcheckout or explicitASP_DOGFOOD_ASP_REPO, installed provider evidence, and provider/host authority receipts. Receipts redact the resolved manager root as<asp-repo>- WHY: dogfood proves advisory/shadow host integration without making Opcore the host, manager, or authority or embedding workstation paths. opcore [--repo <path>] [--json]is the public first-run scan. It emitsrepoStateplusvalidationResult, prints Coverage before Findings, and writes only.opcore/report.json,.opcore/history.jsonl, and bounded.opcore/telemetry.jsonlcapped at 500 records or 1 MiB.opcore --version,opcore -v, andopcore versionare read-only runtime provenance surfaces. JSON output carriesruntimeInfowith package name/version, bin, artifact source (source_checkout,installed_package, orunknown), package root, and entrypoint - WHY: agents and humans must know which Opcore binary/artifact is actually running.opcore status [--repo <path>] [--json]is the runtime-owned activation/readiness entrypoint. It emitsrepoStateand must stay read-only: no graph build/update/watch, validation checks, package installs, ASP setup, or source writes.opcore doctor [--repo <path>] [--json]is the runtime-owned diagnostic entrypoint. It emitsruntimeInfo,opcoreDoctor, and transitionalvalidationStatus, reporting version/provenance, config found/missing/unreadable state for.opcore/config, loaded check ids, graph freshness, generated-state ignore guidance, and next actions without building graphs, running checks, installing packages, setup, wrappers, or source writes.opcore check --changed --jsonis the agent gate and defaults to--base HEAD.opcore check --staged,opcore check --all, and explicit file operands are native check scopes; explicit missing files and blank check ids must return structuredinvalid_payloadJSON instead of passing zero checks or throwing plain text.- #31 latency telemetry contracts live in
packages/contracts:CommandTiming,RepoShapeFingerprint,CommandLatencyRecord,LatencyBudget, andLatencyBudgetResultmust stay source-safe, schema/validator/test aligned, and.opcore/telemetry.jsonlmust remain ring-buffer bounded to 500 records or 1 MiB. Telemetrybinis the normalized public bin name andcanonicalCommandis sanitized command identity, not raw argv or path operands. - #32 router timing wraps
routeOpcoreCommandand advancedrouteCommand; JSONCommandRouterResultpayloads carrytiming.durationMs, normalized phases, and process-localprocessStatewhere first routed command in the Node process iscoldand later routes arewarm. Onlyopcorescan writes bounded.opcore/telemetry.jsonlcapped at 500 records or 1 MiB;opcore statusandopcore measurestay read-only and surface timing in JSON only. - #130 Opcore metrics aggregate named, drillable signals from supplied validation and graph evidence, write only
.opcore/report.jsonplus append-only.opcore/history.jsonl, and expose read-onlyopcore measure [--repo <path>] [--json]deltas throughopcoreMeasure- WHY: reports must show honest coverage/signals/degradations/history without scores, source edits, setup writes, validation runs, or graph builds. - #151/#214 clone detection is owned by the existing
opcore-graph-core clonesubcommand and@the-open-engine/opcore-validation-clone. The native subcommand speaksopcore.clone.v1, writes committed-only.opcore/clone/clone.dbindexes for unscoped clean baseline analysis, and must keep scoped or hypothetical overlay analysis ephemeral. The validation adapter ownsclone.duplication, sends committed source candidates as sparsepaths/sourcePathsmetadata, includes content only for true write overlays, usessourceReadMode/sourceTreeReffor staged/tree/before-state reads, requiresGraph:false, emits line-free duplicate-code diagnostics, and must avoid SAST/security language, blended scores, new daemons, and new native packages - WHY: clone parity needs a small proofable native path without widening launch claims, graph requirements, or Node memory to full repo source bytes. - #34 Opcore latency budgets live in
docs/performance/latency-budgets.jsonand are checked bynpm run latency:check; the checker validates source-safeCommandLatencyRecordJSONL and emits per-command/per-phaseLatencyBudgetResultevidence in default non-blocking trend mode, with--fail-on-overreserved for explicit blocking promotion - WHY: performance budgets must be drillable regression evidence, not an opaque score or live measurement runner. - #36
opcore measurereads bounded.opcore/telemetry.jsonlplus latency budgets and emitsopcoreMeasure.latency.findings[]for slower or over-budget command/phase observations only; it must not write artifacts, run checks, or emitoklatency rows - WHY: slow actions need drillable evidence without turning measure into a runner or score. - #137
opcore graph servewrites one boundedCommandLatencyRecordper forwarded child frame through a product-CLI-injected telemetry writer, with canonical commands shaped asopcore graph serve <op>and per-op phase ids such asserve_query;npm run latency:checkincludes serve and inspect budgets in non-blocking trend mode - WHY: long-lived serve/inspect performance claims need before/after evidence without reintroducing a daemon or bypassing the existing telemetry contract. opcore install [--repo <path>] [--local|--global] [--yes] [--json]is the recommended scan-first repo/agent setup path and interactive wizard. It runs read-only scan output before setup, prompts in an interactive Git repo to choose repo or global write-gate scope when neither scope nor--yes/--jsonis supplied, keeps JSON/non-TTY preview runs plan-only, and approved repo install writes additive.opcore/config, delimited guidance, Opcore agent skills,.opcore/hooks/opcore-agent-gate.mjs, Claude Code.claude/settings.jsonand Codex.codex/hooks.jsonPreToolUse wiring, a safe active.git/hooks/pre-commitwhen no existing hook is present, managed.opcore/.gitignorecoverage, and.opcore/init-undo.json; approved global install writes~/.opcore/hooks/opcore-agent-gate.mjs, user-level skill files, merges~/.claude/settings.jsonand~/.codex/hooks.json, and records undo in~/.opcore/init-undo.json.opcore uninstall [--repo <path>] [--local|--global] [--yes] [--json]removes/restores only recorded Opcore-owned entries.opcore initremains the conservative compatibility setup path with explicit--approvesemantics and the separate opt-in--fail-closed-hookscript.opcore try [--json]is the launch demo loop. It creates local TS, Rust, mixed, and unsupported-file sample repos, runs scan/init/check/measure, returnsopcoreTry.published:false, and must not publish anything.opcoreis the only public npm package and intentionally exposes only Opcore-owned public bins:opcoreplus the bundled ASP provider binopcore-asp-provider. The opcoreGraph/opcoreValidation and cliGraph/validateCommand/editValidation trees remain parallel internal product/advanced-router surfaces, not duplicate drift.opcore-graphremains internal allowlisted naming.- Launch-facing naming gates must keep README, quickstart, concepts, examples, demo, agent integration, and
packages/opcorecopy branded as Opcore. Any remaining old-name hit in those surfaces must be explicitly allowlisted as internal/transitional implementation naming.
- ALWAYS keep graph, edit, and validation as separate ownership boundaries - WHY: graph facts, code mutation, and policy checks evolve at different correctness boundaries - Consequence: a single mixed engine makes parity and cutover unverifiable.
- ALWAYS put shared wire/types/contracts in
packages/contractsbefore another package consumes them - WHY: package-private shape copying creates incompatible command and API surfaces. - ALWAYS keep
packages/contracts/src/index.tsas an API-only export barrel; place implementations in domain modules, preserve the root export surface during internal splits, and keep contracts source modules below 300 lines - WHY: the public package needs one stable import surface without returning to a monolithic implementation file. - ALWAYS update
packages/contracts/schemas/opcore-contracts.schema.json, contract tests, fixture metadata, package exports, and packlists together when changing shared contracts - WHY: Rust/native graph-core consumers and TypeScript packages must consume the same wire artifacts. - ALWAYS dispatch implemented canonical
opcore graph,opcore edit,opcore check, andopcore validateroutes through public package-owned adapters - WHY: package entrypoints must be able to run without importing the aggregate CLI. - NEVER import package implementation internals across package tracks - WHY: graph, edit, and validation must be releasable and testable independently - Consequence: router composition hides runtime coupling until package publishing.
- ALWAYS route symbol edits through graph-backed discovery and whole-plan validation - WHY: declaration-only rewrites leave dangling imports and broken call sites.
- ALWAYS emit boolean
attributes.exportedon supported TS/JS graph symbol nodes and file-nodeattributes.exports[]for default/re-export/barrel forms - WHY: dead-export metrics must distinguish unsupported export coverage from zero dead exports. - ALWAYS make validation checks read file content through
ValidationCheckContext.fileView- WHY: validation overlays are hypothetical and checks must see the same before/after file state without mutating disk. - ALWAYS make validation checks consume GraphProvider facts through
ValidationCheckContext.graphand injectedValidationGraphProviderClientsessions - WHY: validation must depend only on public contracts, not graph package internals, CLI execution, or store layouts. - ALWAYS bind every hypothetical graph-backed check to the disposable exact-state graph session owned by its
ValidationFileView, and share one session per state across all selected checks - WHY: request-scoped or persistent sessions make graph facts disagree with the contents read by the check; optional graph policy must not hide exact-state failures. - ALWAYS make Python import-dependent validation consume an injected
PythonImportAnalyzerbacked by graph-core and derive closure from its directed after-state edges - WHY: validation-owned parsing or module candidates create a second semantic owner and cannot represent overlays consistently. - ALWAYS preserve validation diagnostic source ranges, tool provenance, and fine-grained check outcomes across contracts, manifests, sorting/fingerprints, reporting, and ASP mapping when an adapter supplies them - WHY: transport layers must not collapse actionable compiler evidence or turn tool failures into clean passes.
- Native repo validation policy lives under
.opcore/configvalidation; active checks, thresholds, path policy, docs policy, clone policy, TypeScript policy, Rust command gates, and check packs must be parsed and composed throughpackages/validation-policy. - Repo-owned validation extensions live in
.opcore/configvalidation.checks.packs, resolve from the target repo root, and must export currentValidationCheckDefinitionobjects; Opcore owns loading/registry validation, repos own policy content. - ALWAYS keep
packages/asp-provideras a provider-process facade over ASP Core check/evaluate only - WHY: ASP hosts own decisions, authority, gate semantics, workspace grants, and apply behavior. - ALWAYS keep warm ASP inspect/edit composition inside
packages/opcore/src/advanced/asp-warm/and out ofpackages/asp-provider- WHY: only the advanced Opcore router may combine ASP JSON-RPC with ts-morph inspect/edit state, while the standalone provider must remain cold and check-only. - ALWAYS keep the Opcore product facade thin over public package adapters - WHY:
opcoreis first-run UX, not a second implementation of graph, validation, edit, or ASP host authority. - ALWAYS make Opcore scan/status/check/measure read-only with respect to source files and require explicit approval before
opcore installor compatibilityopcore initwrites guidance, hooks, or config - WHY: first-run trust depends on showing value before mutating a repo. - ALWAYS put coverage honesty before Opcore metrics - WHY: the graph engine currently supports TypeScript/JavaScript, Python source/stub files, and syn-backed Rust
.rsextraction, while unsupported stacks must be counted instead of silently ignored. - NEVER ship a blended quality score, security/SAST claim, all-stack claim, AI-authorship claim, automatic-fix claim, or ASP-standard claim from Opcore alpha - WHY: every claim must survive skeptical drill-down through current receipts.
- NEVER add new launch-facing old-name branding - WHY: the public/product name is Opcore. Existing old-name package/bin/repo references are transitional implementation debt to remove or hide before alpha.
- ALWAYS keep Rust validation in
packages/validation-rustas provider assessment checks composed by the CLI, not host decisions - WHY: Cargo, rustfmt, clippy, rustdoc, import/dead-code, unused dependency, and function-metric evidence must remain package-owned and overlay-safe. - ALWAYS treat Cargo.lock-only changes as retained compatibility unless a later decision expands Rust adapter ownership - WHY: current parity covers
.rs,.inc, andCargo.toml; lockfile-only policy needs an explicit cutover decision before old guardrails move. - NEVER add public CLI behavior outside @docs/architecture/runtime-cli-ard.md canonical routing - WHY: early command shapes become accidental API promises.
- ALWAYS keep
GraphProviderStatus.statealigned withfailure.categoryin TypeScript validators and JSON schema - WHY: consumers branch on both fields for required graph failure policy; contradictory pairs make provider handling ambiguous. - ALWAYS reject blank validation check names before normalization deduplicates or trims them - WHY: blank checks can otherwise become an empty no-check validation request and hide caller mistakes.
- ALWAYS update
.opcore/config, CI, and this file in the same change when adding a new implementation language or validation gate surface - WHY: language support without repo-wide and scoped self-validation lets agents ship unverified code paths. - NEVER add backward-compatibility shims for removed internal paths - WHY: this is a clean release line; migrate the caller or delete the old path.
- ALWAYS keep generated provider/runtime trees out of Git - WHY: descriptors and scripts are source of truth; generated trees drift by machine.
- ALWAYS keep staged graph optional-analysis classifications sourced from
graphReleaseOptionalAnalysisSurfaces- WHY: #13 coverage, #14 flows, #15 communities, and #16 read-only suggestions are non-release-blocking #17 deferred/staged surfaces and must not drift across contracts, fixtures, receipts, or docs. - ALWAYS update
packages/opcore/src/advanced/descriptor.ts,scripts/write-cli-descriptor.mjs, descriptor fixtures, package packlists, and descriptor validation together when changing managed artifact metadata - WHY: installed consumers must resolve package artifacts, not workspace-local paths. - ALWAYS update release receipt contracts,
scripts/generate-release-receipt.mjs, docs/release receipts, CI, and package/provenance/secret negative tests together when changing release evidence ownership - WHY: #29 is the maintainer release proof gate for the alpha line. - ALWAYS update cutover receipt contracts,
scripts/generate-cutover-receipt.mjs, docs/release cutover receipts, CI, and cutover negative tests together when changing installed-artifact release behavior - WHY: #30 proves canonical Opcore artifacts replace current external dev tools without fallback. - ALWAYS record installed package file paths and checksums in cutover receipts, including ASP provider manifests - WHY: cutover proof must show packaged artifacts survived installation, not only tarball and package.json evidence.
- ALWAYS keep ASP dogfood advisory/shadow and isolated to temp
ASP_HOME, and represent inspect/edit gaps as degraded or parity blockers - WHY: #120 proves standalone ASP manager integration without authorizing rollout. - ALWAYS update
packages/asp-provider/src/manifest.ts,scripts/write-asp-provider-manifest.mjs, package exports/packlists, release receipts, installed-bin tests, and claim scrub together when changing ASP provider manifest/install metadata - WHY: canonicalasp-server.jsonand retained provisional metadata must not imply trust, authority, gate permission, or host apply permission. - ALWAYS treat
darwin-arm64,darwin-x64, andlinux-x64as the only supported Opcore alpha graph-core native targets until CI aggregate evidence expands the set - WHY: local single-platform builds cannot prove clean public installs for other targets. - ALWAYS require CI aggregate and release publish workflows to download all three Opcore native package artifacts before release receipts, cutover receipts, or npm publish claim cross-platform graph-core readiness - WHY: the public
opcorepackage must bundle real per-target checksums, not local fallback or fabricated binaries. - ALWAYS keep
opcorelaunch-facing help, README snippets, smoke output, and JSON named Opcore while preserving transitionalopcore statuscompatibility - WHY: first-run activation must not leak internal implementation names into the public readiness flow. - ALWAYS keep Opcore metrics finding-only and evidence-backed, with no opaque score or blended quality number - WHY:
opcore measureis a trend report over concrete counts, not a scoring system. - ALWAYS keep clone detection split between the existing graph-core native subcommand and the injected TypeScript validation-clone adapter - WHY: duplicate-code detection needs native indexing without a daemon, graph-provider dependency, security claim, or extra native package.
- ALWAYS keep latency budget gates finding-only and non-blocking by default, with
--fail-on-overreserved for explicit promotion - WHY: latency evidence should guide regression decisions without becoming an opaque score or live measurement runner. - ALWAYS keep
opcore installand compatibilityopcore initadditive, idempotent, approval-gated, and reversible through.opcore/init-undo.jsonwhere supported - WHY: it is the only alpha command allowed to write repo guidance/hooks/config, and it must never weaken existing lint/test/CI/pre-commit or agent guardrails.
- Node >=22 and TypeScript are the current scaffold baseline.
- The accepted boundary is hybrid: Rust graph core owns extraction, persistence, watch refresh, hot graph queries, and clone index analysis; TypeScript owns contracts, router-core helpers, CLI composition, package command adapters, edit orchestration, validation policy, validation-typescript and validation-clone adapters, npm facade, and managed descriptors.
- #21 adds the Cargo workspace,
crates/graph-core, Rust sidecar protocol, installed native artifacts, checksums, npm Rust gate scripts, workspace Rust/clippy lint policy, and GitHub Actions Rust setup. - #8 adds Wave 1 Rust graph-core source extraction for
.ts,.tsx,.js, and.jsxthrough OXC parser crates. #25 adds syn-backed.rsextraction through graph-core facts for File, Module, Struct, Enum, Trait, Impl, Function/Method, TypeAlias, Const/Static, Test, Macro, CONTAINS, IMPORTS_FROM, CALLS, IMPLEMENTS, and DEPENDS_ON with Rust language/signature/span/export metadata. #9 adds the SQLite GraphProvider store at.opcore/graph/graph.db, freshness metadata, and #19 direct-reader reference evidence. #10 implementsopcore graph build/update/watch/status, incremental cached FileFacts updates, phase timings, daemonping/health, and watch artifacts at.opcore/graph/daemon/{pid,state.json,daemon.log}. #11 implements read-only store-backedimpact, namedquery,review-context, anddetect-changesenvelopes. #12 implements Rust graph-core FTS5 search withnodes_fts, signature projection, full and incremental index maintenance, typed failures, and canonicalopcore graph searchthrough the TypeScript graph adapter. Full build/update/status are unscoped unless--pathsis passed;OPCORE_GRAPH_WATCH_PATHSscopes watch only. Pipeline failures return router statuserror/exit 1 without fabricated summaries; status, health, query, and search paths are read-only when the store is missing or stale. Long-tail parser coverage remains follow-up graph work. - #17 adds Python graph-core extraction for
.pyand.pyithroughtree-sitter-python, emitting File/Module/Class/Function/Variable nodes plus CONTAINS/IMPORTS_FROM/CALLS/INHERITS/TESTED_BY edges. Python imports are repo-local best-effort over absolute, relative, package initializer, and stub candidates; unresolved relative or repo-local imports emit warning categoryunresolved_import; validation support remains absent. - The Rust graph fact-model foundation makes Rust node/edge kinds canonical and confirms SQLite store schema v1 already persists Rust fact columns used by #25 Rust extraction.
- #127 emits TS/JS export metadata from graph-core: supported symbol declarations carry boolean
attributes.exportedplusexportKind/exportName, top-level non-function variables useVariablenodes, and file nodes record default/re-export/barrelattributes.exports[]metadata. SQLitenodes.is_exportedmirrors onlyattributes.exported:true. - #47 adds the graph-owned serve transport: canonical
opcore graph servebridges JSONLopcore.graph.daemonand MCP-style JSON-RPC stdio frames to graph-core, with typed invalid repo, stale store, schema mismatch, bad frame, and sidecar startup failures. - #139 keeps
opcore graph servestate process-local: a serve session caches read-only GraphStore connections, freshness status, snapshots, and GraphIndex by canonical repo root plus snapshotgenerated_at/DB mtime; stale status clears cached graph data; search must not force snapshot loads, and no socket/background daemon is introduced - WHY: repeated frames need hot queries without changing one-shot or hypothetical overlay behavior. - Validation contracts are owned by
@the-open-engine/opcore-validationwithout runner or CLI behavior: ValidationScope supports files, changed, staged, all, repo, and package; hypothetical overlays are write/delete only, with rename-style edit preflight represented as delete old path plus write new path;ValidationRequest.reportModedefaults toall, while edit/pre-write validation should useintroducedso only after-state diagnostics absent from before-state fingerprints block edits; graph config distinguishes optional and required provider modes with typed required_missing, stale, schema_mismatch, daemon_unavailable, incompatible_provider, and provider_error failures; @the-open-engine/opcore-validation owns request normalization and result skeleton helpers while depending only on @the-open-engine/opcore-contracts. - #55 adds the dependency-injected validation runner, check registry, scope resolver, aggregation helpers, check manifest metadata, run summaries, skipped-check records, and timing metadata; it still must not import graph, edit, CLI, validation-typescript, graph-core/native, or raw SQLite internals.
- #56 adds the validation file view:
@the-open-engine/opcore-validationcomposes normalizedValidationRequestoverlays, resolved scope files, and injected workspacereadFileaccess soopcore validatechecks can read hypothetical after-state writes/deletes, before-state comparisons for introduced report mode, and before-state checksums without mutating the worktree.ValidationFileView.defaultReadStateis check-visible so adapters with out-of-band readers can bind their before/after source mode to the runner pass.checksumBeforeconflicts return refused/conflict before checks run. - #26 adds the validation-owned GraphProvider consumer boundary:
ValidationGraphProviderClient, cachedValidationGraphQuerySession, graph requirement preloading, status/query failure mapping, and helper access for metadata, file checksums, IMPORTS_FROM, CALLS, and TESTED_BY facts. - #57 adds the TypeScript validation adapter:
@the-open-engine/opcore-validation-typescriptexports package-owned syntax, type, import-graph, dead-code, and relevant-tests check definitions. Syntax/type checks use the validation file view and an overlay-aware compiler host, including tsconfig path aliases for repo files and deterministic node_modules/package declaration resolution for external package imports; graph checks require #26 graph sessions and batched IMPORTS_FROM, CALLS, and TESTED_BY fact requirements. - Opcore self-validation records file-level
TESTED_BYevidence when a conventional TS/JS test imports a source file, while retaining symbol-level call evidence. The TypeScript relevant-test adapter emits diagnostics only for missing evidence; positive evidence is a clean check result. The realtests/source-package-contracts.test.tssuite imports workspace facades through root tsconfig source aliases and runs in normal local/CI tests - WHY: unsupported.mjsruntime suites and builtdistimports cannot prove source-level relevant-test coverage, and successful evidence is not a finding. - #20 adds the Rust validation adapter:
@the-open-engine/opcore-validation-rustexports package-owned source hygiene, fmt, cargo-check, clippy, rustdoc, import-graph, dead-code, graph-signals, unused-deps, file-length, and function-metrics checks.rust.graph-signalsis graph-provider-backed evidence fromValidationGraphProviderClientonly (untested public Rust surface, dead public exports, module orphans/cycles), while mechanical evidence remains owned by Cargo and the configured native tools. Missingrustdoc,cargo-depgraph,cargo-udeps, orrust-code-analysis-clistays degraded or unsupported withrequiredTool. Rust checks materialize temporary workspaces fromValidationCheckContext.fileViewafter-state content for Cargo tools and add no validation daemon or hidden cache. #138 shares cargo-check JSON with dead-code, forbids a second dead-code cargo compile or-Ddead_codecache-busting flags, and injects a persistentCARGO_TARGET_DIRoutside the worktree throughrunTool; cache keys must derive from generic repo, scope, overlay, platform, and toolchain inputs and cleanup must remain TTL/size bounded - WHY: Rust validation must be fast without leaking hypothetical after-state into real worktrees or tuning behavior to one repository. - Rust Cargo/native checks share one environment-keyed materialized workspace per validation file-view state through runner-owned disposable resources; the runner removes it on every exit - WHY: exact staged/tree/overlay semantics require state isolation, while per-check whole-repo copies create unbounded filesystem-event churn.
- #151/#214 adds clone detection through the existing
opcore-graph-corebinary as aclonesubcommand plus@the-open-engine/opcore-validation-clone.CloneAnalysisRequest/CloneAnalysisResultuseopcore.clone.v1; committed analysis may refresh.opcore/clone/clone.db, while scoped or hypothetical analysis is ephemeral. The sparse request shape sends committed candidates aspaths/sourcePathsplussourceReadMode/sourceTreeRef, with full content only in write overlays.clone.duplicationis a validation adapter check with injected native invocation, no graph requirement, no line-level identity, no daemon, and no SAST/security or score claim. - #27 adds canonical validation CLI surfaces:
opcore checkimplementsfiles,staged,changed,tree,all, andmanifest;treereads committed Git tree content from--tree <ref>and scopes files from--changed-from <ref>without consuming dirty worktree files.opcore validateimplements--request-file,hypothetical --request-file,pre-write --request-file --timeout-ms --json, andmanifest; runtime-ownedopcore status --jsonincludesrepoState, whileopcore doctor --jsonincludes typedruntimeInfo,opcoreDoctor, and transitionalvalidationStatuspayloads with adapter routes, check ids, manifest entries, graph status, and daemon readiness metadata. #58 definesopcore validate pre-write --request-file <validation-request.json> --timeout-ms 30000 --jsonas the hook-safe, fail-closed pre-write contract with typedPreWriteValidationReceiptoutput. - #69 removes public runtime lifecycle command groups: top-level start and stop are unsupported unless a later architecture decision adopts them. Runtime readiness remains
opcore statusandopcore doctor; graph daemon lifecycle/status remains graph-owned underopcore graph. - #118 adds bundled
@the-open-engine/opcore-asp-providerinternals and the publicopcore-asp-provider --stdiobin from theopcorepackage as an independently launchable ASP Core check provider facade. It handlesinitialize,initialized, andcheck/evaluate, maps ASP create/modify/delete/rename changesets into validation overlays through hostworkspace/listTreeandworkspace/readBlobcallbacks, runs the same TypeScript and Rust validation checks as Opcore validation composition, reports degraded/unsupported coverage for missing graph/toolchain/provider surfaces, emits provider-owned diagnostics, bindsvalidAsOfto baseline/changeset/read blobs, and strips host-owned decision/authority/apply fields. It does not add a publicopcore asprouter group. - #128 adds
opcore statusandopcore status --jsonas the read-only repo-aware activation command. It resolves repo/Git state, coverage, graph status/action, validation adapter/check availability, degraded Rust tools, cheap ASP enrollment hints, warnings, blockers, and next actions without running builds, checks, installs, setup, wrappers, or writes. Its JSON payload isrepoState;opcore statuskeeps the transitionalvalidationStatuspayload. - #129 adds
opcoreand the standaloneopcorebin. Zero-command scan usesrepoStatefrom #128, runs validation without source mutation, prints Coverage before Findings, writes only.opcore/report.json,.opcore/history.jsonl, and bounded.opcore/telemetry.jsonlcapped at 500 records or 1 MiB, exposesopcore check --changed|--staged|--all|<files...> --jsonwith stable agent exit codes, and exposes read-onlyopcore --version/opcore versionruntime provenance. - #130 adds
packages/opcore/src/reporting.ts,OpcoreMetricReport,OpcoreMetricHistoryEntry, andOpcoreMeasureDelta. Reports aggregate TS/JS syntax/type/test/dead-export diagnostics, graph structure/fan-in evidence when supplied, Rust source hygiene/file length/module/toolchain diagnostics, unsupported stack census, and honest degradations for unavailable checks/tools/facts.writeOpcoreMetricArtifactswrites only under.opcore/;opcore statusexcludes those generated artifacts from coverage;opcore measurereads them and returns deltas without validationResult, validationStatus, scans, graph builds, setup, or source writes. - #131 adds
packages/opcore/src/init.tsand theopcoreInitrouter payload.opcore initdetects existingAGENTS.md,CLAUDE.md,GEMINI.md,.github/copilot-instructions.md,.codex/AGENTS.md, and.opencode/AGENTS.md, runs a read-only scan without.opcore/report.jsonor history writes, emits scan/settings/interaction/timing payloads, presents a plan before writing, prompts on TTY only, and now chooses repo/global write-gate scope by flag or interactive Git prompt. Approved repo init upserts a single<!-- BEGIN OPCORE INIT -->block, writes additive.opcore/config, appends one managed.opcore/.gitignoreline only in Git repos that do not already ignore it, installs.opcore/hooks/opcore-agent-gate.mjs, and merges Claude Code plus Codex PreToolUse hook settings without clobbering existing hooks. Approved global init installs the same adapter under~/.opcore/hooks/, merges~/.claude/settings.jsonand~/.codex/hooks.json, and records undo under~/.opcore/init-undo.json. The adapter maps Write/Edit/MultiEdit and Codex apply_patch payloads to hypothetical validation overlays, callsopcore validate pre-write --request-file <json> --timeout-ms 30000 --json, exits 2 on non-ok receipts or validation command failure, and fail-opens only when the adapter cannot parse/map the harness payload. Approved writes refuse symlink targets or symlink ancestors for repo and global paths. Undo refuses metadata whose recorded root does not match or whose entries are outside Opcore-owned config/hooks/agent guidance paths plus the managed.gitignoreline;.gitignoreundo removes only that managed line and deletes an init-created.gitignoreonly when empty. The managed.opcore/ignore covers.opcore/telemetry.jsonl. The guidance must tell agents to runopcore check --changed, preserve existing safeguards, report unsupported/degraded coverage honestly, and not rely on ASP host authority for direct Opcore. - #133 adds
packages/opcore/src/try.tsand theopcoreTryrouter payload.opcore tryuses generated local sample repos only, keeps output coverage-first with named findings/deltas, includes unsupported-file census evidence, and records clean-room launch proof without public announcement or package publishing. - #22 adds the edit-core library foundation:
@the-open-engine/opcore-editowns deterministic exact, multi-edit, and literal search-replace planners, edit checksums, plan hashes, validation overlay construction, preview mode, repo path policy, Node workspaces, and all-or-nothing atomic apply/rollback. #59 adds canonicalopcore edit exact,multi,search-replace,check, andapplyparsing inside the edit package, typededitPlan/editResultrouter payloads, and search-replace uniqueness unlessreplaceAllis true. #60 adds canonicalopcore edit patchandtree: raw unified diff patch input through--stdin/--request-fileor{patch}JSON, tree payloads{repo?,validation?,fileContains?,files:[{path,content,checksumBefore?}|{path,delete:true,checksumBefore?}]}, patch/tree-only forbidden target policy for absolute paths, parent traversal, UNC paths, symlink escapes,.gitignoretargets, generated/private roots, and binary content, pluseditResult.rollbackstate for atomic apply failures. #24 routes non-emptyopcore editapply/check plans through an injected validation runner before writes, rejects validation bypass plans, preserves fullValidationResultenvelopes in edit results, and keeps--dry-runas a non-validating preview. #23 implements canonicalopcore edit rename,move, andsignatureroutes as graph-backed, validation-required edit plans: GraphProvider contract status/query/search evidence is required for targeting/freshness, TypeScript/JavaScript language-service materialization stays edit-owned, and apply/check refuses graph freshness changes before validation or writes. - #149 makes
packages/edit/src/typescript-project/the shared owner of ts-morph project discovery, tsconfig selection, import resolution, source listing, scope materialization, and injected-project snapshot composition consumed by edit, CLI-owned inspect, and warm ASP sessions. Cold inspect signatures and graph-backed implementations default to target import-closure loading; references and symbol edits load the target import closure plus reverse importers instead of whole-repo Projects when that preserves correctness; graphless implementation paths keep whole-repo fallback where reverse dependents cannot be bounded safely; and both inspect/edit accept injected Project plus snapshot/revert hooks without introducing a daemon - WHY: inspect and warm sessions must not maintain a second TypeScript project scanner or import resolver that diverges from symbol edits. - #153 adds the hidden
opcore asp serve --stdiowarm ASP session: host-launched only, process-local singleton/idle lifecycle under.opcore/asp, warm injected whole-repo ts-morph Project forinspect/referencesandedit/renamepreview, unchanged delegatedcheck/evaluate,session/shutdown, no source writes, no public help/manifest command group, no auto-spawned daemon, and no change to the coldopcore-asp-provider --stdiocheck-only capability. - #17 adds the graph release readiness receipt gate:
npm run graph-release:checkproves canonical graph commands, direct SQLite queries, serve transport, package inspection, provenance/license receipts, benchmark metrics, and handoff data for #7/#28/#29. - #28 adds the aggregate Opcore managed descriptor contract and artifact:
opcorepackagesdist/descriptors/opcore.managed-tool.json, generated frompackages/opcore/src/advanced/descriptor.tsafter build. Descriptors list only the canonicalopcorebin, command groups graph/inspect/edit/check/validate/status/doctor, package-relative artifact/checksum paths, GraphProvider query/search/native capabilities, edit validation dependency, validation graph optional/required modes, and deferred optional surfaces as metadata. - #29 adds the repo-wide release receipt gate:
npm run release-receipt:checkproves the single publicopcoretarball, bundled internal implementation/native/runtime dependencies, exact packlists, sha256 checksums, descriptor/provider manifest artifact resolution, canonical Opcore command groups, native graph artifact checksum evidence, production and bundled dependency licenses, provenance scans, release hygiene, graph #17 input evidence, and current-tree plus git-history secret scans.npm run release-receipt:receiptrefreshesdocs/release/release-receipt.json,docs/release/release-receipt.summary.md, license/provenance reports, and artifact attestation docs. Secret allowlist entries live only indocs/release/secret-scan-allowlist.jsonand must include reviewed path or commit scope, reviewer, reason, expiry, and optional fingerprint/kind narrowing; remove real findings instead of allowlisting them. - #30 adds the installed-artifact cutover gate:
npm run cutover:checkpacks and installs only the publicopcorepackage into a clean temp project, sanitizes execution paths, verifies installed canonical bins (opcoreandopcore-asp-provider), validatesReleaseCutoverReceipt, and proves graph/inspect/edit/check/validate/status/doctor/pre-write plus scan/measure flows throughopcore. Each command receipt id is contract-bound to its expected canonical command/status/exit. Top-levelopcore inspect symbols|definition|references|signature|implementations|searchis read-only CLI behavior; signature and implementations are implemented read-only language-service parity.opcore graph inspectis not an advertised release route. - #72 adds typed inspect reference results and
opcore inspect references <file> <symbol> --line <n> [--column <n>]over fresh graph facts plus an inspect-owned TypeScript/JavaScript language-service seam. #100 adds shared read-onlyInspectSignatureResultandInspectImplementationResultcontracts, fixture foundations, target parsing, graph freshness enforcement, and typedunsupported_routescaffolds. #101 implementsopcore inspect signature <file> <symbol> --line <n> [--column <n>]and node-id targeting over fresh graph facts. #102 implementsopcore inspect implementations <file> <symbol> --line <n> [--column <n>]and class/type node-id targets over graphIMPLEMENTS/INHERITSfacts plus TypeScript/TSX language-service materialization. - #141 keeps inspect file-symbol routes useful when graph facts are missing or stale: supported TS/JS
referencesandsignature, plus existing TS/TSXimplementations, return read-only language-service payloads withinspectResult.status: "degraded"andfailure.category: "graph_unavailable"instead of hard failure; unsupported paths and graph-only node-id targets remain hard failures or unsupported as before. - The provenance GitHub workflow must install stable Rust and run
npm run buildbeforenpm run release-receipt:check- WHY: release receipts import ignoreddist/contracts/descriptors and require native graph artifacts from a clean checkout.
- ALL tests live in @tests/ until a package-specific test harness is explicitly introduced by an issue.
- Add contract tests before implementation tests for GraphProvider, EditPlan, ValidationRequest, and canonical CLI behavior.
- Add golden/reference fixtures before changing established behavior.
- Keep release hygiene, conformance metadata, and package packlist gates executable when changing package or release surfaces - WHY: maintainer release receipts must fail before public alpha assumptions drift.
- Add #29 negative fixtures for release evidence regressions: high-confidence secrets, unexpected package files, descriptor artifact drift, and missing native checksum evidence.
- Add #30 negative fixtures for cutover regressions: advertised unimplemented command receipts, missing cutover command receipts, and invalid installed package/bin surfaces.
- Local proof for agent work is
npm run ci:local; for source/package/native/release changes it runsnpm run ciand thennpm run opcore:self-check. Docs/agent-guidance-only changes use the repository-native fast path described above.
- Setup:
npm run setup. - Proof: core
npm run ci,npm run opcore:self-check, targetednode --test tests/...,npm run rust:check,npm run ci:localornpm run verify; releasenpm run graph:artifact,npm run descriptor:artifact,npm run asp-provider:manifest,npm run graph-release:check,npm run release-receipt:check,npm run cutover:check,npm run asp-dogfood:check,npm run pack:check,npm run release:hygiene. - Public scan/readiness:
opcore --repo . --json,opcore status --repo . --json,opcore --version --json,opcore doctor --repo . --json,opcore measure --repo . --json,opcore try --json. - Public setup/check/provider:
opcore install --repo . --json,opcore install --repo . --yes --json,opcore uninstall --repo . --yes --json,opcore check --changed --json,opcore-asp-provider --stdio.