Global sync CLI foundations: checkable fingerprints, CONFLICT state, pdd reconcile (#1926/#1927/#1929/#1938)#1969
Open
Serhan-Asad wants to merge 39 commits into
Open
Global sync CLI foundations: checkable fingerprints, CONFLICT state, pdd reconcile (#1926/#1927/#1929/#1938)#1969Serhan-Asad wants to merge 39 commits into
Serhan-Asad wants to merge 39 commits into
Conversation
…-fresh (#1938) pdd sync regenerated mature modules "rebirth-shaped" (full regeneration), dropping declared public symbols. PDD already ships edit-shaped generation (incremental_code_generator + code_patcher_LLM), but sync hardcoded force_incremental_flag=False, so it deferred to the deliberately-conservative diff_analyzer_LLM ("prefer complete regeneration"), which rebirthed modules on ordinary small prompt deltas and lost symbols. Make sync prefer surgical generation for mature modules, with a --fresh opt-out: - New `pdd sync --fresh` flag (default off), threaded sync -> sync_main -> sync_orchestration and the one-session generate loop. - Both sync generate call sites now pass force_incremental_flag=(not fresh): default -> surgical/edit-shaped (existing code + prompt delta -> minimal edit, declared symbols preserved); --fresh -> standard generation. - Reuses existing infra only. Safety nets preserved: new/empty modules still full-generate; undeterminable original prompt falls back to full generation; conformance repair retries still force full regeneration (#1724); the public-surface / declared-interface gate (#1900) is unchanged and remains the guarantee. - --fresh is single-module only: raises UsageError on global/agentic sync paths (mirrors --snapshot-context) instead of silently no-op'ing. Prompt sources edited in tandem with generated .py (pdd is self-hosted); sync_main's architecture.json signature aligned; README documents the flag. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ctions Add a terse Prompt-First Workflow block near the top of AGENTS.md, CLAUDE.md, and GEMINI.md so coding agents edit prompts first, regenerate with `pdd sync`, run `pdd update --sync-metadata` to back-propagate direct code edits and re-stamp the fingerprint before a PR, never hand-edit `.pdd/meta/*.json` or `architecture.json`, and never delete passing tests. Removes the contradiction where agent docs steered edits into the doctrine's #1 anti-pattern, Prompt Drift. Part of the global-sync program (Issue C). Co-Authored-By: Claude <noreply@anthropic.com>
Point Core Philosophy at AGENTS.md/CLAUDE.md/GEMINI.md and the doctrine Anti-Patterns section, and align the "If editing code directly" step with the agent rules (`pdd update --sync-metadata` re-stamp; no hand-editing metadata) so human and agent docs agree and no longer contradict each other. Part of the global-sync program (Issue C). Co-Authored-By: Claude <noreply@anthropic.com>
…es (Issue C) Reviewed against Issue C acceptance criteria: surgical blocks in AGENTS/CLAUDE/GEMINI, CONTRIBUTING aligned to pdd update --sync-metadata, no contradictions. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
architecture.json is the registry that drives project-wide `pdd sync` (no-arg sync enumerates modules from it via _architecture_sync_modules). 27 top-level pdd/*.py modules that have BOTH a prompt and code were absent, so global sync and dependency-ordered heal were structurally blind to them (construct_paths, load_prompt_template, config_resolution, cli_theme, one_session_sync, provider_manager, reasoning, edit_file, ...). Entries are appended (no reflow of existing bytes) with: - reason: prompt <pdd-reason> tag, else module docstring first sentence - description: module docstring first paragraph, else prompt reason - interface: derived from code AST (public classes + functions with signatures/returns), mirroring the existing module-interface schema - dependencies: the prompt's own <include>/<pdd-dependency> declarations only, so `pdd checkup --validate-arch-includes` stays green (import-derived deps would register as declaration drift and fail that gate) - priority: max(existing)+1..; tags: []; position omitted (54 entries omit it) Coverage of top-level pdd modules: 152 -> 179. Sync enumeration: 188 -> 215. Co-Authored-By: Claude <noreply@anthropic.com>
…entry Registering load_prompt_template (previous commit) surfaced a latent inconsistency: agentic_test_orchestrator's architecture entry listed load_prompt_template_python.prompt as a dependency, but its prompt only references load_prompt_template via a context-example include (context/load_prompt_template_example.py), never via <pdd-dependency> or a module-prompt <include>. Per the validator's own model (context/example artifacts are not module dependencies), that dependency edge is spurious; it stayed invisible only because load_prompt_template had no entry to map to. Removing it keeps `pdd checkup --validate-arch-includes` green (0 -> 0 non-strict warnings). If maintainers consider it a real module dependency, the alternative fix is a prompt-side <pdd-dependency> declaration (prompts are out of scope for this change). Co-Authored-By: Claude <noreply@anthropic.com>
tests/test_architecture_completeness.py asserts a module<->entry bijection:
every top-level pdd/*.py module (after .pddignore) has exactly one
architecture.json entry, unless waived in architecture_waivers.json. Also
checks every entry's filepath (code) and filename (prompt) exist on disk, and
ratchets the adjacent orphan gaps (prompt-no-code, code-no-prompt,
code-no-test) so new gaps must be documented, not silent. Two meta-tests prove
the gate has teeth (a removed entry / an unwaived new module both fail it).
architecture_waivers.json documents:
- modules_without_architecture_entry: 20 hand-written utilities / CLI wiring
with no generating prompt (json_atomic, drift_main, __main__, ...), each with
a one-line reason — these are exempt from the bijection.
- orphans.{prompt_without_code(16), code_without_prompt(21), code_without_test(22)}
- known_registry_exceptions: 2 pre-existing double-registrations
(user_story_tests, coverage_contracts; merged by sync at runtime) and 2
entries predating the description field, documented for ratchet-down.
Reuses pdd's own helpers (_load_pddignore/_is_pddignored, extract_modules,
_basename_from_architecture_filename) so the gate tracks production semantics.
Co-Authored-By: Claude <noreply@anthropic.com>
Run tests/test_architecture_completeness.py as an explicit named step in the Unit Tests job, alongside the existing validate-arch-includes checks. The full `pytest tests/` run already collects it; this dedicated step makes the module<->architecture.json bijection gate visible and fast-failing. Co-Authored-By: Claude <noreply@anthropic.com>
scripts/stamp_fingerprints.py recomputes every dev unit's fingerprint from disk (composite prompt_hash + include_deps + code/example/test hashes) and writes it byte-identically to how `pdd sync` persists it. It is stdlib-only (no pdd import, no LLM): the hashing is vendored verbatim from sync_determine_operation.py, and code/example/test paths are resolved by the .pddrc convention plus architecture.json overrides (issue #225 filepath, issue #1677 ambiguous-leaf stem disambiguation), so recomputed hashes match the CLI for every unit. --check recomputes and diffs against the committed metas, exiting non-zero on drift or a missing/hand-edited fingerprint. This is the primitive the CI gate and audits reuse. scripts/fingerprint_waivers.json lists the units `pdd sync` itself cannot fingerprint (ambiguous bare leaves cli/gate; core_dump_smoke and server/routes/session have no code file), so --check excludes them. tests/test_stamp_fingerprints.py pins hash parity against pdd's own calculate_current_hashes for representative units (flat, subdir, architecture-overridden, ambiguous-leaf), the no-trailing-newline byte format, --check drift detection on a tampered meta, and waiver/coverage classification. Co-Authored-By: Claude <noreply@anthropic.com>
The committed .pdd/meta/*.json set is the oracle `pdd sync` trusts for every decision, but it was a hand-maintained `!`-allowlist pinning only ~42 of 223 units — the stalest artifact in the repo. Remove the blanket `.pdd/meta/*.json` ignore and its per-file allowlist so every dev unit's fingerprint is tracked. Only transient files stay ignored: atomic-write temp files (`.pdd/meta/*.tmp`) and sync logs (via the global `*.log` rule). Run-report tracking (`*_run.json`) is left exactly as-is (out of scope). Document the policy in CONTRIBUTING.md: never hand-edit `.pdd/meta`; regenerate the whole set with scripts/stamp_fingerprints.py, which CI verifies via --check. Co-Authored-By: Claude <noreply@anthropic.com>
One-time epoch stamp (scripts/stamp_fingerprints.py). Declares the current tree the agreed sync baseline: recompute every unit's prompt/code/example/test hashes so the committed .pdd/meta is a trustworthy three-way merge-base. Refreshes 42 stale fingerprints (some pinned at 0.0.234 from May) and adds 181 that were never committed. Pre-existing prompt/code divergence is accepted here by design (back-propagation is a follow-up); what matters is that FUTURE drift is detected against a true base. Verified: a mature module that previously resolved to `fail_and_request_manual_merge` against its stale fingerprint now reports a benign decision, and no module resolves to a phantom generate/auto-deps/update. Co-Authored-By: Claude <noreply@anthropic.com>
Add a step to the unit-tests job that fails when any committed .pdd/meta fingerprint is stale or missing, so the epoch stamp cannot silently rot again. The check is stdlib-only and needs no pdd import or network. Co-Authored-By: Claude <noreply@anthropic.com>
…mp (Issue A) Reviewed: 0 cross-validation mismatches vs pdd's own hashing across 223 units, --check re-run independently (exit 0), 200 tests green, gitignore allowlist gone (run-report policy untouched), waivers minimal and justified. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…n gate (Issue B) Reviewed: 27 entries backfilled (surgical append, existing entries byte-identical), 20 code-only modules waived, bijection gate with teeth-proving meta-tests, deps authored prompt-declared to keep validate-arch-includes green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…-fresh (pdd#1938) Wave-2 dependency: the repair bot's PROMPT_AHEAD leg must not full-regen mature modules. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…on, maintenance) The commit-all fingerprint gate flagged exactly the units #1940 touched; restamped with scripts/stamp_fingerprints.py per the new CONTRIBUTING policy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…1929) The prompt+derived co-edit branch already returns a non-destructive fail_and_request_manual_merge / CONFLICT decision (landed in #1954). This makes its reason self-actionable: it names the unit, states which artifacts moved, and gives the exact 'pdd resolve <basename> --accept-current / --prompt-wins / --code-wins' commands. details now carries basename, language, changed_files, and a resolution_commands map for machine consumers. analyze_conflict_with_llm is documented as reserved (not wired into the decision path) so it is no longer a parallel auto-resolver. Prompt prose realigned: removes the stale unlink/delete/recurse description of the old destructive branch and describes the actionable CONFLICT contract. Co-Authored-By: Claude <noreply@anthropic.com>
pdd resolve <basename> --accept-current deterministically stamps the current
working tree as the agreed baseline (re-fingerprint via continuous_sync's
save_fingerprint core), turning a CONFLICT unit IN_SYNC without any LLM call.
Command-level transactional: re-classifies after stamping and only reports
success when the unit lands IN_SYNC (exit 0), else non-zero.
--prompt-wins / --code-wins are documented previews of the LLM strategies
(regenerate from prompt / back-propagate to prompt): they print what WOULD run
and exit non-zero ('not yet automated'). Exactly one strategy is required.
Modeled on commands/reconcile.py (commands/ dir, no prompt) so it is exempt
from the architecture-completeness and fingerprint-stamper gates, both of which
stay green.
Co-Authored-By: Claude <noreply@anthropic.com>
Enumerate every python unit (reusing stamp_fingerprints unit resolution) and rank the code-ahead ones -- code committed more recently than its prompt -- by drift churn: added+deleted lines on the code file since 2026-04-01 over commits that touched code but NOT the prompt. 75 of 229 units are code-ahead. 43 are conflict_risk: the prompt's most recent (non-merge, in-window) commit touched the prompt but NOT the code, i.e. a standalone prompt edit never reconciled with code by a joint commit -- pdd update (code->prompt) there could clobber deliberate prompt intent, so these are flagged for human review and must NOT be auto-updated. The remaining 32 are pure staleness (prompt last synced WITH code by a joint commit, then code drifted): safe to back-propagate. conflict_risk uses the pathspec-free per-commit file map from the window log; a per-unit 'git log -- <prompt>' cannot be used because the pathspec filters --name-only down to just the prompt, hiding whether the same commit also touched code. scripts/build_prompt_catchup_queue.py regenerates scripts/prompt_catchup_queue.json. Co-Authored-By: Claude <noreply@anthropic.com>
pdd update (agentic, provider=google) back-propagated code->prompt for the code-ahead unit server/token_counter (queue rank 28, non-conflict: prompt last synced with code by joint commit c1db8fc, then code drifted 32d). Prompt gains a structured interface covering all 8 public functions + CostEstimate/TokenMetrics; internal NamedTuple ModelPricing stays undeclared (was never in the prompt, not dropped). Code untouched; tests/server/test_token_counter.py 42 passed. Re-stamped via scripts/stamp_fingerprints.py to the subdir-qualified meta .pdd/meta/server_token_counter_python.json (pdd update itself wrote a stray leaf-named .pdd/meta/token_counter_python.json -- removed; see report). --check clean. Co-Authored-By: Claude <noreply@anthropic.com>
pdd update (agentic, provider=google) back-propagated code->prompt for the code-ahead unit commands/modify (queue rank 22, non-conflict). Detector marks it non-conflict because its most recent RAW prompt touch is the joint commit 7f9e46c (code+prompt together); note git log -- <prompt> hides that commit via history simplification, so raw per-commit numstat is the correct signal. All 3 public commands (split, change, update) retained. Code untouched; tests/commands/test_modify.py 46 passed. Re-stamped to subdir-qualified .pdd/meta/commands_modify_python.json; removed the stray leaf-named .pdd/meta/modify_python.json pdd update wrote. --check clean. Co-Authored-By: Claude <noreply@anthropic.com>
A dry-run previously only replayed the operation log, so a freshly-created CONFLICT (prompt AND a derived artifact both changed since the fingerprint) was invisible until a real sync ran. The dry-run branch now computes the current decision read-only (log_mode=True, read_only=True — no lock, no fingerprint/metadata mutation) via a new _display_dry_run_decision helper and prints a 'Current analysis:' line, prefixing a CONFLICT with its actionable resolution message. test_dry_run_mode updated deliberately: dry-run now makes exactly one read-only sync_determine_operation call (asserted read_only/log_mode). Adds test_dry_run_surfaces_conflict_without_side_effects (real path, fingerprint byte-identical after) and test_conflict_reason_surfaces_actionable_resolve_command (the reason with 'pdd resolve' reaches result['errors']). Prompt + meta realigned for the new dry-run behavior; both gates green. Co-Authored-By: Claude <noreply@anthropic.com>
test_sync_determine_operation.py: assert the CONFLICT reason names the unit, what moved, and the exact pdd resolve commands, and that details carries basename/language/resolution_commands; a helper test covers the --language suffix and 3-way co-edit phrasing. (Unit test_hash re-stamped since these tests live in the unit's tracked test file.) test_resolve_command.py (new): pdd resolve --accept-current turns a CONFLICT IN_SYNC and stamps the CHANGED code (not the old baseline), preserving the fingerprint; --json reports before/after; --prompt-wins/--code-wins are documented stubs that exit non-zero and do not mutate the fingerprint; exactly-one-strategy and unknown-unit guards. Co-Authored-By: Claude <noreply@anthropic.com>
pdd update (agentic, provider=google) back-propagated code->prompt for the code-ahead unit agentic_test_generate (queue rank 32, non-conflict, code 36d ahead -- the most-stale non-conflict unit). Public entry run_agentic_test_generate retained. Code untouched; tests/test_agentic_test_generate.py 44 passed. Re-stamped: pdd update's meta write NULLED example_hash/test_hash/test_files (it maintains only prompt_hash/code_hash), which fails --check; the stamper restores the full fingerprint. --check clean. Co-Authored-By: Claude <noreply@anthropic.com>
…1927) Replace continuous_sync's discover_units/get_pdd_file_paths path logic with the Wave-0 stamper's resolution (pdd/prompts rglob + architecture.json filepath overrides + slash-basenames, each unit -> its own .pdd/meta), while keeping pdd's real hash functions (calculate_current_hashes / save_fingerprint) so a reconcile stamp is byte-identical to `pdd sync`. This is the single implementation issue #1927 asks for; scripts/stamp_fingerprints.py becomes a thin wrapper over it in a follow-up commit. Fixes both classification false positives on the clean tree (the same tree the CI stamper reports as fully current): - commands/firecrawl: was FAILURE "incomplete metadata: test_hash" because the underscore meta-derived basename resolved the test to the stray flat tests/test_commands_firecrawl.py. Correct resolution -> IN_SYNC. - core/remote_session vs remote_session: was DOC_CHANGED because both collapsed to one safe-basename and cross-wired fingerprints. Each now maps to its own meta -> IN_SYNC. Stamping is idempotent: a unit whose content hashes already match its stored fingerprint is not rewritten (timestamp preserved, zero writes), so a repo-wide restamp touches only genuinely-changed units (pdd_cloud restamp-churn addendum). Machine-readable verdicts gain the issue #884 shape (status / reasons / affected_artifacts / remediation) alongside the existing classification fields. CONFLICT keeps its definition (prompt-side AND code/derived-side both moved) to stay aligned with the sync decision path (#1929). build_report's public signature/report shape is preserved for existing callers (ci_drift_heal, maintenance, modify dry-runs); adds accept_current/backfill. Co-Authored-By: Claude <noreply@anthropic.com>
pdd update (agentic, provider=google) back-propagated code->prompt for the code-ahead unit checkup_prompt_apply (queue rank 30, non-conflict). All public symbols (ApplyFindingRecord, ApplyRunResult, apply_approved_patches) retained. Code untouched; tests/test_checkup_prompt_apply.py 14 passed. Re-stamped; --check clean. Co-Authored-By: Claude <noreply@anthropic.com>
…kfill (part of #1927) - positional [BASENAME] (keep --module as an alias) scopes a run to one unit. - --check: read-only verification with the CI stamper's contract (exit non-zero on any missing/stale/no-code unit; waived+ignored excluded). - --accept-current: stamp CONFLICT units only (explicit human acceptance of the current tree as the agreed baseline). - --backfill: stamp UNBASELINED units only (missing/invalid fingerprint). - --heal keeps stamping single-sided drift; each stamping flag is scoped to exactly its class (_stampable_now now gates drift on --heal). - --json carries the issue #884 verdict shape already produced by the core. Co-Authored-By: Claude <noreply@anthropic.com>
Reviewed: destructive both-changed branch was already neutralized upstream (#1954); this adds the actionable message, deterministic pdd resolve --accept-current, dry-run CONFLICT surfacing, and demotes the dead LLM conflict path. 202 tests green on the branch; gates green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> # Conflicts: # .pdd/meta/metadata_sync_python.json # .pdd/meta/pre_checkup_gate_python.json # .pdd/meta/sync_determine_operation_python.json # .pdd/meta/sync_orchestration_python.json
Per the team-lead boundary note, continuous_sync.py and commands/reconcile.py are owned by the sibling #1927 effort this wave. Rework pdd resolve so it no longer imports them: classification now reuses sync_determine_operation's own _changed_artifacts_from_hashes (keeping the CONFLICT definition — prompt-side AND derived-side both moved vs the stored fingerprint — identical to the sync decision path), and stamping uses the shared runtime save_fingerprint writer directly. Tests likewise drop the continuous_sync import and assert via the command's own --json output (before/after) plus fingerprint inspection. Behavior and CLI surface unchanged; 8 resolve tests green, pylint 10/10, both gates green. Any overlap with reconcile --accept-current is left for merge-time consolidation. Co-Authored-By: Claude <noreply@anthropic.com>
…dary fix) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lot (Issue A2) Reviewed: prompts+metas only (no code churn), 75-unit ranked backlog with 43 conflict-flagged units excluded from auto-update, symbol-drop checks passed, two upstream pdd-update meta bugs documented for follow-up. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> # Conflicts: # .pdd/meta/agentic_test_generate_python.json # .pdd/meta/checkup_prompt_apply_python.json # .pdd/meta/commands_modify_python.json # .pdd/meta/server_token_counter_python.json
#1927) The stamper no longer vendors a stdlib copy of pdd's hashing; it imports the shared core (resolve_units / hashes_for / stamp_units / run_check) so the CI gate and `pdd reconcile` can never diverge. The CLI contract is unchanged: `--check` prints the same "checked N stampable units..." lines and the same exit codes CI depends on, and the default stamp is now idempotent (unchanged units are skipped). Adds a small public API to continuous_sync (resolve_unit/resolve_units/ hashes_for/stamp_units) so the wrapper needs no protected-member access. test_stamper_is_stdlib_only is inverted into test_stamper_delegates_to_ continuous_sync: the stdlib-only invariant is intentionally lifted (the team lead's call: CI installs the package), and the new test guards that the script imports the shared core and re-vendors no hashlib hashing. The other 15 stamper tests pass unchanged. `stamp_fingerprints.py --check` stays green (223 current). Co-Authored-By: Claude <noreply@anthropic.com>
…part of #1927) tests/test_continuous_sync.py covers the four reconcile verdicts (current / stamped / conflict / unbaselined), the --accept-current (CONFLICT-only) and --backfill (unbaselined-only) stamping scopes, the issue #884 --json verdict shape, idempotency (second run is a no-op; a single changed unit touches only its own fingerprint), the two resolution regressions #1954 got wrong (commands/firecrawl, core/remote_session vs remote_session), the reconcile CLI (--check exit codes, BASENAME + --json), and script<->command parity on the committed tree. Removes the now-satisfied "TODO add tests/test_continuous_sync.py" orphan waiver from architecture_waivers.json. Co-Authored-By: Claude <noreply@anthropic.com>
…single impl) Reviewed: stamper resolution ported into continuous_sync (real pdd hash fns), two #1954 false positives fixed with regression tests, script now a thin wrapper with byte-identical CLI contract, idempotent writes, --accept-current/--backfill scoped. Follow-up flagged: .pddrc-driven resolution for consumer repos before any pdd release ships this. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Merged 25 upstream commits; main's code changes + new story_regression units restamped to the merged tree via scripts/stamp_fingerprints.py. Both gates green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nding 1) commands/checkup_simplify and core/remote_session resolved to their same-named LEAF files (pdd/checkup_simplify.py, pdd/remote_session.py) because architecture.json had no path-qualified entry, so the resolver fell back to the leaf — the fingerprint tracked the wrong file and edits to the real command/core file were invisible to the gate. Add the 2 missing architecture.json entries + restamp; edits now flag. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, docs Finding 2: 'pdd resolve --accept-current' now REQUIRES a CONFLICT — single-sided (code-only/prompt-only) drift is refused with a redirect to pdd update/pdd sync/ pdd reconcile --heal, so it can't silently baseline real drift. Added --force escape hatch + IN_SYNC no-op. New tests cover refuse/force/no-op. Finding 3: the CONFLICT message no longer advertises the --prompt-wins/--code-wins preview stubs as resolutions; it points at the real runnable commands (pdd update / pdd sync) plus pdd resolve --accept-current. Updated the prompt spec + tests. Docs: README no longer tells users to delete .pdd/meta/*.json (contradicted the never-hand-edit policy) — points to pdd reconcile --heal. Documented the 6 prompt-less pdd/commands wrappers (incl. resolve/reconcile) in architecture_waivers. Restamped affected fingerprints. Gates + resolver/resolve/sync/orchestration tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ll, reconcile no-match guard Finding 1: the CONFLICT message and pdd resolve guidance emitted invalid commands for non-Python units — pdd sync/pdd update/pdd reconcile reject --language (only pdd resolve accepts it), and pdd update takes the CODE FILE path, not a basename. Fixed all sites (sync_determine_operation conflict message, resolve.py guard + stub previews) to emit valid shapes; tests lock in no-suffix sync/update + code-path. Finding 2: README recovery advice said 'pdd reconcile --heal', but a deleted/ invalid fingerprint is UNBASELINED and only --backfill stamps it; --heal leaves it broken. README now points at --backfill (missing/invalid) vs --heal (drifted). Finding 3: 'pdd reconcile <typo> --check' exited 0/ok:true with 0 units, so CI/ runbook checks could silently skip the intended unit. A targeted run that matches no unit now errors (nonzero) with a spelling hint. New test covers it. Restamped; gates + resolve/sync/continuous_sync/orchestration suites + lint green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Global sync — CLI foundations: make prompt↔code drift checkable, and repairs path-independent
Part of the global-sync program (pdd#1932 cluster). Goal: a PR made by hand/agent and a PR made through
pddboth leave the repo in agreement — and "in agreement" is a deterministic, checkable property, not a hope.What's in here
1. Complete, committed fingerprints + epoch stamp (Issue A)
.pdd/metafingerprint (223 units), replacing the hand-maintained.gitignoreallowlist (~48 files) that had frozen at pdd versions weeks behind the tree.scripts/stamp_fingerprints.py(stdlib, no LLM): stamp all units +--checkmode. Cross-validated to 0 hash mismatches vs pdd's own hashing across all units. Writes are idempotent (unchanged unit → zero file writes, timestamp preserved).unit-tests.yml:stamp_fingerprints.py --checkfails on any stale fingerprint.scripts/fingerprint_waivers.jsondocuments the 4 legitimately-unstampable units (ambiguous leaf / no code file).2. architecture.json completeness + bijection gate (Issue B)
tests/test_architecture_completeness.pyasserting module ↔ architecture.json bijection (witharchitecture_waivers.jsonfor justified orphans).pdd syncnow enumerates previously-invisible modules.3. Prompt-first agent instructions (Issue C)
AGENTS.md/CLAUDE.md/GEMINI.mdnow mandate: behavior change → edit the prompt first & regenerate; direct code edit →pdd update --sync-metadata+ re-stamp before the PR; never hand-edit.pdd/metaorarchitecture.json. Closes the gap where agent instructions produced the doctrine'spdd install_completion:install_completion()got unexpected keyword argument 'quiet' #1 anti-pattern (Prompt Drift).CONTRIBUTING.mdcross-referenced.4. Surgical regeneration default (pdd#1938 / PR#1940 folded in)
pdd syncdefaults to edit-shaped regeneration (force_incremental_flag=(not fresh)) with a new--freshflag, instead of full "rebirth" regen that dropped declared symbols on mature modules.5. Explicit CONFLICT state +
pdd resolve(pdd#1929)pdd resolve <unit> --accept-currentdeterministically stamps the current tree as the agreed baseline;--prompt-wins/--code-winsare documented stubs.6.
pdd reconcileunified onto one implementation (pdd#1927)pdd reconcile(fix(sync): add deterministic continuous sync reconcile #1954) to use a single hashing/resolution core (pdd's real hash functions + correct unit/path resolution), fixing two pre-existing false positives.scripts/stamp_fingerprints.pyis now a thin wrapper over it (CLI contract unchanged). Adds[BASENAME],--check,--accept-current,--backfill.7. Prompt catch-up queue + pilot (Issue A2)
scripts/build_prompt_catchup_queue.pyranks code-ahead units; 4 units back-propagated as a pilot. (Surfaced two upstreampdd updatemeta bugs — subdir meta path + nulled test hashes — noted for follow-up.)Verification
stamp_fingerprints.py --check,test_architecture_completeness.py).--checkdetects →pdd resolve --accept-current→ green.pdd reconcile/stamper idempotency verified: re-run after merging main restamped only the 25 units main changed (198 untouched).origin/mainin; deterministic restamp reconciled it cleanly.Notes for review
.pdd/metaJSON files (the epoch stamp) — the code surface isscripts/+pdd/commands/{resolve,reconcile}.py+continuous_sync.py+ the sync decision path.--checknow importspdd(was stdlib-only); fine in CI. Follow-up flagged: makepdd reconcileresolution.pddrc-driven for full consumer-repo generality before a release ships it.🤖 Generated with Claude Code