Repository navigation
Made an unchanged sync start far fewer processes and added sync --check - #54
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Executable-mode changes can be missed, and several check failures violate the documented single-status-line API.
Review effort: Balanced
Findings: 3
Open (3)
What changed in this PR
Adds a read-only sync --check mode and substantially reduces process startup overhead on unchanged syncs.
Changes:
- Adds cached and strict render-based sync checks.
- Consolidates manifest parsing, adapter contracts, and fingerprinting.
- Updates tests, documentation, decisions, and versioned examples to 0.19.0.
| File | Description |
|---|---|
README.md |
Documents sync --check. |
packages/sync/references/conventions.md |
Defines check semantics and status. |
intelligence/rules/engine.md |
Documents engine check transaction. |
intelligence/rules/cli.md |
Records cache performance conventions. |
intelligence.yaml |
Updates schema and package pin. |
intelligence.lock |
Updates engine and package lock. |
examples/with-remote-skills/intelligence.yaml |
Updates version pins. |
examples/platform-with-submodules/intelligence.yaml |
Updates version pins. |
examples/platform-with-submodules/intelligence.lock |
Updates lock version. |
examples/go-api/intelligence.yaml |
Updates version pins. |
examples/go-api/intelligence.lock |
Updates lock version. |
examples/go-api-with-pi-and-codex/intelligence.yaml |
Updates version pins. |
examples/go-api-with-pi-and-codex/intelligence.lock |
Updates lock version. |
examples/go-api-with-opencode/intelligence.yaml |
Updates version pins. |
examples/go-api-with-opencode/intelligence.lock |
Updates lock version. |
examples/go-api-with-antigravity/intelligence.yaml |
Updates version pins. |
examples/go-api-with-antigravity/intelligence.lock |
Updates lock version. |
examples/dotnet-api-with-react-frontend/intelligence.yaml |
Updates version pins. |
examples/dotnet-api-with-react-frontend/intelligence.lock |
Updates lock version. |
examples/cli-project/intelligence.yaml |
Updates version pins. |
engine/VERSION |
Bumps engine to 0.19.0. |
engine/sync.sh |
Adds snapshot comparison and restoration. |
engine/lib/contract.sh |
Adds out-of-date return contract. |
engine/lib/common.sh |
Adds combined manifest parsing. |
engine/lib/adapter-contract.sh |
Batches built-in contract reads. |
engine/adapters/pi.sh |
Avoids redundant common-library loading. |
engine/adapters/opencode.sh |
Avoids redundant common-library loading. |
engine/adapters/cursor.sh |
Avoids redundant common-library loading. |
engine/adapters/copilot.sh |
Avoids redundant common-library loading. |
engine/adapters/codex.sh |
Avoids redundant common-library loading. |
engine/adapters/claude.sh |
Avoids redundant common-library loading. |
engine/adapters/antigravity.sh |
Avoids redundant common-library loading. |
engine/adapters/agents.sh |
Optimizes loading and output lookup. |
docs/cli.md |
Documents check behavior and environment contract. |
decisions/0015-check-whether-sync-is-needed.md |
Records the check design. |
decisions/0010-skip-unchanged-local-sync.md |
Records fingerprint optimization results. |
decisions/0002-consolidate-intelligence-cli-lifecycle.md |
Adds the lifecycle amendment. |
cli/tests/verify.sh |
Registers the new check suite. |
cli/tests/unit-manifest.sh |
Tests qmap preloading. |
cli/tests/unit-engine.sh |
Tests combined manifest views. |
cli/tests/e2e-sync-check.sh |
Covers check behavior end to end. |
cli/tests/e2e-sync-cache.sh |
Extends cache fallback coverage. |
cli/lib/sync-lock.sh |
Optimizes locking and adds scratch paths. |
cli/lib/sync-cache.sh |
Implements v2 fingerprints and checks. |
cli/lib/qmap.awk |
Supports batched document reads. |
cli/lib/manifest.sh |
Adds qmap memoization and preloading. |
cli/lib/lockfile.sh |
Uses preloaded lock reads. |
cli/lib/cli-common.sh |
Consolidates lifecycle preflight reads. |
cli/intelligence |
Sources sync in the dispatcher process. |
cli/commands/sync.sh |
Adds check option and orchestration. |
CHANGELOG.md |
Records the 0.19.0 changes. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…ed its decision to 0018
Code review - CLEANhead: 2c803bc - base: main - files 50, +2118/-327 Critical(none) Warning(none) Suggestion
Claims axis (PR body vs. diff)
Sibling drift
Summary
|
Code review - CLEANhead: 0bcc635 - base: main - files 34, +2095/-287 Critical(none) Warning(none) Suggestion
Claims axis (PR body vs. diff)
Sibling drift
Summary
|
Verification - PASShead: 0bcc635 - steps: sha1:52f816a43d90 (Verification section: checklist + Steps 1-10; docs/qa-checks.md absent, no standing checks matched) - env: local (fresh clones of the PR head and main from GitHub into a scratch dir; no preview/app_url exists for this CLI project) Setup per the PR shared start state (Windows 11, Git Bash, CI unset): cloned feature/fast-sync-check as cli-src (HEAD 0bcc635 confirmed before and after the run) and main as cli-main; built the scratch project via git -C cli-src archive HEAD | tar -x -C proj, then git init, add, commit base, then $CLI sync - exit 0, package store restored, git status --porcelain empty.
Negative probes (skill step 5; not PR-declared, carry no separate verdict)
No defects found by any of the three probes above. |
Outcome - MANUALhead: 0bcc635 CI is green with 21/21 checks, and
|
Verification - FAILhead: 2b80adb - steps: sha1:52f816a43d90 (Verification section: checklist + Steps 1-10, unchanged since the 0bcc635 report; docs/qa-checks.md absent at head, no standing checks matched) - env: local (fresh clones of the PR head and of main 3adf722 from GitHub into a scratch dir; no preview or app_url exists for this CLI project) Setup per the PR's shared start state (Windows 11, Git Bash 5.3.9,
Failures
Negative probes (skill step 5) were not run in this pass, because the run was scoped to the declared steps. |
Code review - BLOCKhead: 2b80adb - base: main - files 34, +2095/-287 Critical
Warning
Suggestion
Claims axis
|
Verification - PASShead: 0aece34 - steps: sha1:52f816a43d90 (Verification section: checklist + Steps 1-10, unchanged since the 0bcc635 and 2b80adb reports; docs/qa-checks.md absent at head, no standing checks matched) - env: local (fresh clones of the PR head and of main b1113b0 from GitHub into a scratch dir; no preview or app_url exists for this CLI project) Setup per the PR's shared start state (Windows 11, Git Bash 5.3.9,
FailuresNone. The caller scoped this run to the declared steps, so it did not run the skill's step-5 negative probes. |
Code review - PASS-WITH-WARNINGShead: 0aece34 - base: main - files 51, +2240/-336 CriticalNone. Warning
Suggestion
Merge of #48 (b1113b0)
Claims axis
Gates
|

Summary
Save hooks, editor tasks and CI need one cheap answer: would
intelligence syncchange a generated file? The only way to ask was to run sync, and even its cheapest path, an unchanged run answered from the cache, took 3.9–4.9 s on Windows/Git Bash. Nearly all of that went on starting processes, at 40–120 ms each, not on hashing.intelligence sync [adapter] --checkchanges no generated file and prints oneIS_STATUSline. Exit codes:0when generated files are up to date;2(new statusout-of-date) when sync would change them or the project needs alignment, which the check never applies; the failure's own code otherwise. When the record from the last sync or check was made by the same tooling, it answers straight from that record, without rendering, and says which side changed. Without such a record, and always with--check --force, it renders inside the engine's snapshot transaction, compares, and restores every path. A clean answer is recorded, so the next check is fast.Unchanged
syncis faster, with byte-identical output:find | awk | git hash-objectpipeline replaces two fingerprint runs;syncinstead of starting another bash.Median on this repository's own project: 3.90 s on
main, 0.74 s on this branch. The check answers from its record in 0.73 s, or 0.58 s when sources changed.Merging #48 (package-named sources, decision 0019) extended the single-pass manifest readers: package references expand the way
read_yaml_listexpands them, so the cache fingerprints such sources at their store path. Decision 0018 item 3 and both test suites cover it.Design and rejected alternatives: decision 0018. The measured cache follow-up is appended to 0010, and 0002 gains the flag.
Type of change
packages/sync/references/conventions.md: the command line and theout-of-datestatus row)Public CLI check
init,sync,update,upgrade,package,source,adapter,status,registry(a flag onsync)out-of-datenamingintelligence init --apply, with or withoutCI)intelligence sync(the check restores a missing or mis-recorded store through the same locked path, because the comparison needs it)Verification
bash cli/tests/verify.shreportsverify okand skipped nothing this change needed (all, through WSL, on this head)intelligence status --checksucceeds in the relevant fixture/project (this repository's root project, on this head)intelligence syncproduces no unexpected diff (syncthensync --checkexits 0 andgit statusstays empty)main, step 10)Steps. Shared start state: Windows 11, Git Bash,
CIunset. Clone the PR head (git clone --branch feature/fast-sync-check https://github.com/ainova-systems/intelligence.git cli-src) andmain(git clone --branch main https://github.com/ainova-systems/intelligence.git cli-main);CLI="bash $PWD/cli-src/cli/intelligence". Scratch project:mkdir proj && git -C cli-src archive HEAD | tar -x -C proj && cd proj && git init -q && git add -A && git commit -qm base && $CLI sync(exit 0; the first run fetches@ainova-systems/corefrom GitHub). "Reset" =git checkout -- . && git clean -fdq && $CLI sync.$CLI sync --check; echo $?prints one line saying generated files are up to date and0;git status --porcelainstays empty. Five runs oftime $CLI sync --check >/dev/null: medianreal≤ 1.0 s.f=intelligence/rules/product.md; t=$(stat -c %Y "$f"); sed -i 's/^# Intelligence product repository$/# Intelligencf product repository/' "$f"; touch -d "@$t" "$f".$CLI sync --checkexits2and says sources changed; five runs median ≤ 1.0 s;git status --porcelainlists onlyintelligence/rules/product.md.echo '<!-- hand edit -->' >> AGENTS.md.$CLI sync --checkexits2and says generated files changed;tail -1 AGENTS.mdis still the hand edit andgit status --porcelainlists onlyAGENTS.md. Then$CLI syncleavesgit status --porcelainempty and$CLI sync --checkexits0.rm -rf .intelligence/sync-cache.$CLI sync --checkexits0after rendering;git status --porcelainempty. A second$CLI sync --checkexits0with a five-run median ≤ 1.0 s.rm -rf .intelligence/sync-cache,echo extra >> intelligence/rules/product.md.$CLI sync --checkexits2;git status --porcelainlists onlyintelligence/rules/product.md.rm -rf .intelligence.$CLI sync --checkrestores the package store fromintelligence.lockand exits0;git status --porcelainempty.sed -i 's/^schema_version: .*/schema_version: "0.17.3"/' intelligence.yaml.$CLI sync --checkexits2and namesintelligence init;git diff --statshows onlyintelligence.yamlwith that one line changed.CI=true $CLI sync --checkbehaves the same.sed -i 's/^lockfile_version: 1$/lockfile_version: 99/' intelligence.lock;$CLI sync --checkexits1with the lock error. In an empty temporary directory$CLI sync --checkexits1.$CLI sync --check --forcerenders and exits0withgit status --porcelainempty; with the criterion-2 edit it exits2.bash ../cli-main/cli/intelligence sync --force && git add -A && git commit -qm main-render, then$CLI sync --force:git status --porcelainempty. On two copies of the scratch project, one synced by each CLI, five alternating cache-hitsyncruns: the branch's medianrealis lower thanmain's.Automated coverage
e2e-sync-check(new, inSUITES):--force, adapter filters, and old-format or damaged records;CI=true;e2e-sync-cacheadds file names the fingerprint cannot carry, which must fall back to ordinary sync.unit-manifest: preloaded answers equal the ordinary reader, a write clears the preload, and partial output is rejected.unit-engine: the combined manifest pass equals the single readers.bash cli/tests/verify.sh allpasses on this head through WSL. Natively under Git Bash (INTELLIGENCE_VERIFY_NATIVE=1),e2e-sync-check(113 checks) ande2e-sync-cache(245 checks) passed on e0a7523 (e2e-sync-cachedropped from ~635 s to ~465 s); that native result predates the merges of Made status --check decide .gitignore presence with the writer's CR-blind test #55 and Added a tool-neutral effort field and stopped deriving Codex reasoning effort from the tier #46 and the link case added toe2e-sync-check, which this host cannot run natively because Git Bash here cannot create symlinks.Versioned artifacts
CHANGELOG.mdversion; there is no[Unreleased]section or duplicated release dateengine/VERSIONrelease state was checked: append while pending, or select the next SemVer after publication (v0.19.0is published without this change, so it selects0.20.0, a minor for the new flag, in a new## [0.20.0]section; everything from## [0.19.0]down is byte-identical tomain)schema_versionand exact@ainova-systems/syncpin changed with it (with their lock rows; the root project was aligned byinit --apply)Notes for reviewers
Postponed by the owner: the review at 2b80adb found that the
sync --checkrender path compares through symlinks. That fix, plus the review's warnings and suggestions, is tracked in sync --check follows symlinks when comparing rendered output with its snapshot #60.Fast answers can over-report. A
2answered from the record compares content, not rendered output, so an edit that renders identically, such as a comment inintelligence.yaml, reports "sources changed".--check --forcegives the exact answer. This was a deliberate trade for speed.When the record does not answer.
PATH, locale, umask, the adapter filter and CLI/engine code are part of the tooling fingerprint. A check from an environment other than the last sync's renders once, about 8 s on Windows, and records its own answer. An upgrade therefore renders instead of claiming that sync is needed.Cache format. The record moves to
intelligence-sync-cache-v2: tooling, inputs and outputs as separate fingerprints, sealed by its own hash. Earlier records are ignored, so the first sync after upgrading renders once.Exit code 2. Under
--check,2means only "sync needed".config-missing, which shares code 2, cannot reach a check, and any other failure that would end in 2 is reported as 1.The 1-second target is met on a quiet host but has little margin. With other sessions loading the machine, the record answer measured about 1.2 s, while
main's cache hit took 6 s.Not run locally: macOS bash 3.2. CI's
cli-e2ecovers it. Under mawk,e2e-sync-cachefails one test identically onmain; that is pre-existing and not touched here.