Skip to content

Latest commit

 

History

History
218 lines (202 loc) · 58.2 KB

File metadata and controls

218 lines (202 loc) · 58.2 KB

UPDATE THIS FILE when making architectural changes, adding patterns, or changing conventions.

Opcore

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.

Key Concepts

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.

Where To Look

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/

Development Tooling

  • Run npm run setup after cloning or entering a fresh worktree. It installs repository dependencies only and must leave the worktree clean.
  • Run npm run opcore:self-check after building. It requires .opcore/config to 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.sh runs 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 ci and the same local CI-equivalent command proof - WHY: humans, agents, CI, and ship clusters must exercise one repository-owned validation surface.
  • Root .npmrc sets loglevel=silent - WHY: JSON-emitting npm scripts such as npm run asp-dogfood:check -- --json must write parseable JSON to redirected stdout without npm lifecycle preambles.
  • npm run test:ci routes through scripts/run-test-ci.mjs: it runs the parallel-safe Node test files first, runs tests/validation-python.test.mjs separately because its real subprocess fixtures can exhaust CI process slots under the parallel suite, then runs tests/native-packaging-policy.test.mjs separately 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-udeps 0.1.61 with nightly-2026-07-27, selects that exact toolchain for rust.unused-deps through OPCORE_RUST_NIGHTLY_TOOLCHAIN, and provisions rust-code-analysis-cli 0.0.25 for rust.function-metrics; the unused-deps adapter defaults to the conventional nightly selector 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; --repo defaults 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/graph resolves only matching package metadata and never probes packages/graph/dist/native, sibling checkouts, or PATH.
  • Release flow is dev -> main: CI runs on dev and main, PRs to main must come from dev, and .github/workflows/release.yml auto-publishes npm package version 0.2.1 with dist-tag latest after the CI workflow succeeds on main. Each release must provide readable notes at docs/release/v<version>.md; the workflow uses that file verbatim for the GitHub release. The CI native jobs upload tarred native package directories so opcore-graph-core execute bits survive artifact transfer; aggregate CI and release publish must set OPCORE_REQUIRE_ALL_NATIVE_PACKAGES=1 after extracting all three native artifacts, and scripts/release-dry-run.mjs then 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, and Cargo.toml; retained Cargo.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; file exports[] entries must include policy and supportedSymbol - WHY: Python has no enforced export boundary.
  • #244 python.syntax resolves one concrete interpreter through the Python project resolver, executes that exact interpreter with an isolated versioned JSON compile protocol over sorted .py/.pyi after-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-python the sole dynamic owner of opcore.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 make python.types select and execute exactly one mypy or Pyright authority per canonical project. Mypy uses first-match config precedence and strict NDJSON. Pyright preserves pyrightconfig.json precedence 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 emits opcore.python.validation-capability-run evidence - 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-lint and python.ruff-format separate from python.source-hygiene and opt-in through explicit selection or .opcore/config defaults. 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 the packages/validation-python/src/python-execution-workspace.ts primitive 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 shared afterStateManifestFingerprint field 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-graph materializes supplied .py/.pyi after-state files only in an isolated temporary repo and returns canonical directed IMPORTS_FROM file 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 ValidationFileView per 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 .rs universe plus root tsconfig.json into 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 serve as the stdio/MCP hot-query replacement, not a Unix socket, with parallel independent serve sessions as the supported concurrency evidence.
  • opcore-asp-provider --stdio is the transitional provider binary for the standalone ASP Core check provider; it uses host workspace callbacks and Opcore validation only.
  • opcore asp serve --stdio is a hidden host-launched warm ASP session for inspect/edit/check under packages/opcore/src/advanced/asp-warm/; it is intercepted before the public router, omitted from opcore --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:check with a temporary ASP_HOME, a built adjacent agent-server-protocol checkout or explicit ASP_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 emits repoState plus validationResult, prints Coverage before Findings, and writes only .opcore/report.json, .opcore/history.jsonl, and bounded .opcore/telemetry.jsonl capped at 500 records or 1 MiB.
  • opcore --version, opcore -v, and opcore version are read-only runtime provenance surfaces. JSON output carries runtimeInfo with package name/version, bin, artifact source (source_checkout, installed_package, or unknown), 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 emits repoState and 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 emits runtimeInfo, opcoreDoctor, and transitional validationStatus, 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 --json is 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 structured invalid_payload JSON instead of passing zero checks or throwing plain text.
  • #31 latency telemetry contracts live in packages/contracts: CommandTiming, RepoShapeFingerprint, CommandLatencyRecord, LatencyBudget, and LatencyBudgetResult must stay source-safe, schema/validator/test aligned, and .opcore/telemetry.jsonl must remain ring-buffer bounded to 500 records or 1 MiB. Telemetry bin is the normalized public bin name and canonicalCommand is sanitized command identity, not raw argv or path operands.
  • #32 router timing wraps routeOpcoreCommand and advanced routeCommand; JSON CommandRouterResult payloads carry timing.durationMs, normalized phases, and process-local processState where first routed command in the Node process is cold and later routes are warm. Only opcore scan writes bounded .opcore/telemetry.jsonl capped at 500 records or 1 MiB; opcore status and opcore measure stay 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.json plus append-only .opcore/history.jsonl, and expose read-only opcore measure [--repo <path>] [--json] deltas through opcoreMeasure - 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 clone subcommand and @the-open-engine/opcore-validation-clone. The native subcommand speaks opcore.clone.v1, writes committed-only .opcore/clone/clone.db indexes for unscoped clean baseline analysis, and must keep scoped or hypothetical overlay analysis ephemeral. The validation adapter owns clone.duplication, sends committed source candidates as sparse paths/sourcePaths metadata, includes content only for true write overlays, uses sourceReadMode/sourceTreeRef for 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.json and are checked by npm run latency:check; the checker validates source-safe CommandLatencyRecord JSONL and emits per-command/per-phase LatencyBudgetResult evidence in default non-blocking trend mode, with --fail-on-over reserved for explicit blocking promotion - WHY: performance budgets must be drillable regression evidence, not an opaque score or live measurement runner.
  • #36 opcore measure reads bounded .opcore/telemetry.jsonl plus latency budgets and emits opcoreMeasure.latency.findings[] for slower or over-budget command/phase observations only; it must not write artifacts, run checks, or emit ok latency rows - WHY: slow actions need drillable evidence without turning measure into a runner or score.
  • #137 opcore graph serve writes one bounded CommandLatencyRecord per forwarded child frame through a product-CLI-injected telemetry writer, with canonical commands shaped as opcore graph serve <op> and per-op phase ids such as serve_query; npm run latency:check includes 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/--json is 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.json and Codex .codex/hooks.json PreToolUse wiring, a safe active .git/hooks/pre-commit when no existing hook is present, managed .opcore/ .gitignore coverage, and .opcore/init-undo.json; approved global install writes ~/.opcore/hooks/opcore-agent-gate.mjs, user-level skill files, merges ~/.claude/settings.json and ~/.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 init remains the conservative compatibility setup path with explicit --approve semantics and the separate opt-in --fail-closed-hook script.
  • opcore try [--json] is the launch demo loop. It creates local TS, Rust, mixed, and unsupported-file sample repos, runs scan/init/check/measure, returns opcoreTry.published:false, and must not publish anything.
  • opcore is the only public npm package and intentionally exposes only Opcore-owned public bins: opcore plus the bundled ASP provider bin opcore-asp-provider. The opcoreGraph/opcoreValidation and cliGraph/validateCommand/editValidation trees remain parallel internal product/advanced-router surfaces, not duplicate drift. opcore-graph remains internal allowlisted naming.
  • Launch-facing naming gates must keep README, quickstart, concepts, examples, demo, agent integration, and packages/opcore copy branded as Opcore. Any remaining old-name hit in those surfaces must be explicitly allowlisted as internal/transitional implementation naming.

Architecture Rules

  • 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/contracts before another package consumes them - WHY: package-private shape copying creates incompatible command and API surfaces.
  • ALWAYS keep packages/contracts/src/index.ts as 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, and opcore validate routes 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.exported on supported TS/JS graph symbol nodes and file-node attributes.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.graph and injected ValidationGraphProviderClient sessions - 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 PythonImportAnalyzer backed 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/config validation; active checks, thresholds, path policy, docs policy, clone policy, TypeScript policy, Rust command gates, and check packs must be parsed and composed through packages/validation-policy.
  • Repo-owned validation extensions live in .opcore/config validation.checks.packs, resolve from the target repo root, and must export current ValidationCheckDefinition objects; Opcore owns loading/registry validation, repos own policy content.
  • ALWAYS keep packages/asp-provider as 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 of packages/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: opcore is 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 install or compatibility opcore init writes 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 .rs extraction, 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-rust as 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, and Cargo.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.state aligned with failure.category in 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: canonical asp-server.json and retained provisional metadata must not imply trust, authority, gate permission, or host apply permission.
  • ALWAYS treat darwin-arm64, darwin-x64, and linux-x64 as 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 opcore package must bundle real per-target checksums, not local fallback or fabricated binaries.
  • ALWAYS keep opcore launch-facing help, README snippets, smoke output, and JSON named Opcore while preserving transitional opcore status compatibility - 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 measure is 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-over reserved for explicit promotion - WHY: latency evidence should guide regression decisions without becoming an opaque score or live measurement runner.
  • ALWAYS keep opcore install and compatibility opcore init additive, idempotent, approval-gated, and reversible through .opcore/init-undo.json where 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.

Language And Runtime

  • 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 .jsx through OXC parser crates. #25 adds syn-backed .rs extraction 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 implements opcore graph build/update/watch/status, incremental cached FileFacts updates, phase timings, daemon ping/health, and watch artifacts at .opcore/graph/daemon/{pid,state.json,daemon.log}. #11 implements read-only store-backed impact, named query, review-context, and detect-changes envelopes. #12 implements Rust graph-core FTS5 search with nodes_fts, signature projection, full and incremental index maintenance, typed failures, and canonical opcore graph search through the TypeScript graph adapter. Full build/update/status are unscoped unless --paths is passed; OPCORE_GRAPH_WATCH_PATHS scopes watch only. Pipeline failures return router status error/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 .py and .pyi through tree-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 category unresolved_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.exported plus exportKind/exportName, top-level non-function variables use Variable nodes, and file nodes record default/re-export/barrel attributes.exports[] metadata. SQLite nodes.is_exported mirrors only attributes.exported:true.
  • #47 adds the graph-owned serve transport: canonical opcore graph serve bridges JSONL opcore.graph.daemon and 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 serve state process-local: a serve session caches read-only GraphStore connections, freshness status, snapshots, and GraphIndex by canonical repo root plus snapshot generated_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-validation without 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.reportMode defaults to all, while edit/pre-write validation should use introduced so 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-validation composes normalized ValidationRequest overlays, resolved scope files, and injected workspace readFile access so opcore validate checks can read hypothetical after-state writes/deletes, before-state comparisons for introduced report mode, and before-state checksums without mutating the worktree. ValidationFileView.defaultReadState is check-visible so adapters with out-of-band readers can bind their before/after source mode to the runner pass. checksumBefore conflicts return refused/conflict before checks run.
  • #26 adds the validation-owned GraphProvider consumer boundary: ValidationGraphProviderClient, cached ValidationGraphQuerySession, 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-typescript exports 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_BY evidence 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 real tests/source-package-contracts.test.ts suite imports workspace facades through root tsconfig source aliases and runs in normal local/CI tests - WHY: unsupported .mjs runtime suites and built dist imports 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-rust exports 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-signals is graph-provider-backed evidence from ValidationGraphProviderClient only (untested public Rust surface, dead public exports, module orphans/cycles), while mechanical evidence remains owned by Cargo and the configured native tools. Missing rustdoc, cargo-depgraph, cargo-udeps, or rust-code-analysis-cli stays degraded or unsupported with requiredTool. Rust checks materialize temporary workspaces from ValidationCheckContext.fileView after-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_code cache-busting flags, and injects a persistent CARGO_TARGET_DIR outside the worktree through runTool; 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-core binary as a clone subcommand plus @the-open-engine/opcore-validation-clone. CloneAnalysisRequest/CloneAnalysisResult use opcore.clone.v1; committed analysis may refresh .opcore/clone/clone.db, while scoped or hypothetical analysis is ephemeral. The sparse request shape sends committed candidates as paths/sourcePaths plus sourceReadMode/sourceTreeRef, with full content only in write overlays. clone.duplication is 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 check implements files, staged, changed, tree, all, and manifest; tree reads committed Git tree content from --tree <ref> and scopes files from --changed-from <ref> without consuming dirty worktree files. opcore validate implements --request-file, hypothetical --request-file, pre-write --request-file --timeout-ms --json, and manifest; runtime-owned opcore status --json includes repoState, while opcore doctor --json includes typed runtimeInfo, opcoreDoctor, and transitional validationStatus payloads with adapter routes, check ids, manifest entries, graph status, and daemon readiness metadata. #58 defines opcore validate pre-write --request-file <validation-request.json> --timeout-ms 30000 --json as the hook-safe, fail-closed pre-write contract with typed PreWriteValidationReceipt output.
  • #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 status and opcore doctor; graph daemon lifecycle/status remains graph-owned under opcore graph.
  • #118 adds bundled @the-open-engine/opcore-asp-provider internals and the public opcore-asp-provider --stdio bin from the opcore package as an independently launchable ASP Core check provider facade. It handles initialize, initialized, and check/evaluate, maps ASP create/modify/delete/rename changesets into validation overlays through host workspace/listTree and workspace/readBlob callbacks, 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, binds validAsOf to baseline/changeset/read blobs, and strips host-owned decision/authority/apply fields. It does not add a public opcore asp router group.
  • #128 adds opcore status and opcore status --json as 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 is repoState; opcore status keeps the transitional validationStatus payload.
  • #129 adds opcore and the standalone opcore bin. Zero-command scan uses repoState from #128, runs validation without source mutation, prints Coverage before Findings, writes only .opcore/report.json, .opcore/history.jsonl, and bounded .opcore/telemetry.jsonl capped at 500 records or 1 MiB, exposes opcore check --changed|--staged|--all|<files...> --json with stable agent exit codes, and exposes read-only opcore --version/opcore version runtime provenance.
  • #130 adds packages/opcore/src/reporting.ts, OpcoreMetricReport, OpcoreMetricHistoryEntry, and OpcoreMeasureDelta. 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. writeOpcoreMetricArtifacts writes only under .opcore/; opcore status excludes those generated artifacts from coverage; opcore measure reads them and returns deltas without validationResult, validationStatus, scans, graph builds, setup, or source writes.
  • #131 adds packages/opcore/src/init.ts and the opcoreInit router payload. opcore init detects existing AGENTS.md, CLAUDE.md, GEMINI.md, .github/copilot-instructions.md, .codex/AGENTS.md, and .opencode/AGENTS.md, runs a read-only scan without .opcore/report.json or 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/ .gitignore line 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.json and ~/.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, calls opcore 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 .gitignore line; .gitignore undo removes only that managed line and deletes an init-created .gitignore only when empty. The managed .opcore/ ignore covers .opcore/telemetry.jsonl. The guidance must tell agents to run opcore 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.ts and the opcoreTry router payload. opcore try uses 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-edit owns 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 canonical opcore edit exact, multi, search-replace, check, and apply parsing inside the edit package, typed editPlan/editResult router payloads, and search-replace uniqueness unless replaceAll is true. #60 adds canonical opcore edit patch and tree: raw unified diff patch input through --stdin/--request-file or {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, .gitignore targets, generated/private roots, and binary content, plus editResult.rollback state for atomic apply failures. #24 routes non-empty opcore edit apply/check plans through an injected validation runner before writes, rejects validation bypass plans, preserves full ValidationResult envelopes in edit results, and keeps --dry-run as a non-validating preview. #23 implements canonical opcore edit rename, move, and signature routes 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 --stdio warm ASP session: host-launched only, process-local singleton/idle lifecycle under .opcore/asp, warm injected whole-repo ts-morph Project for inspect/references and edit/rename preview, unchanged delegated check/evaluate, session/shutdown, no source writes, no public help/manifest command group, no auto-spawned daemon, and no change to the cold opcore-asp-provider --stdio check-only capability.
  • #17 adds the graph release readiness receipt gate: npm run graph-release:check proves 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: opcore packages dist/descriptors/opcore.managed-tool.json, generated from packages/opcore/src/advanced/descriptor.ts after build. Descriptors list only the canonical opcore bin, 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:check proves the single public opcore tarball, 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:receipt refreshes docs/release/release-receipt.json, docs/release/release-receipt.summary.md, license/provenance reports, and artifact attestation docs. Secret allowlist entries live only in docs/release/secret-scan-allowlist.json and 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:check packs and installs only the public opcore package into a clean temp project, sanitizes execution paths, verifies installed canonical bins (opcore and opcore-asp-provider), validates ReleaseCutoverReceipt, and proves graph/inspect/edit/check/validate/status/doctor/pre-write plus scan/measure flows through opcore. Each command receipt id is contract-bound to its expected canonical command/status/exit. Top-level opcore inspect symbols|definition|references|signature|implementations|search is read-only CLI behavior; signature and implementations are implemented read-only language-service parity. opcore graph inspect is 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-only InspectSignatureResult and InspectImplementationResult contracts, fixture foundations, target parsing, graph freshness enforcement, and typed unsupported_route scaffolds. #101 implements opcore inspect signature <file> <symbol> --line <n> [--column <n>] and node-id targeting over fresh graph facts. #102 implements opcore inspect implementations <file> <symbol> --line <n> [--column <n>] and class/type node-id targets over graph IMPLEMENTS/INHERITS facts plus TypeScript/TSX language-service materialization.
  • #141 keeps inspect file-symbol routes useful when graph facts are missing or stale: supported TS/JS references and signature, plus existing TS/TSX implementations, return read-only language-service payloads with inspectResult.status: "degraded" and failure.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 build before npm run release-receipt:check - WHY: release receipts import ignored dist/ contracts/descriptors and require native graph artifacts from a clean checkout.

Test Rules

  • 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 runs npm run ci and then npm run opcore:self-check. Docs/agent-guidance-only changes use the repository-native fast path described above.

Commands

  • Setup: npm run setup.
  • Proof: core npm run ci, npm run opcore:self-check, targeted node --test tests/..., npm run rust:check, npm run ci:local or npm run verify; release npm 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.