# Pre-Work Error Ledger Purpose: read this file before substantial project work. It exists to stop repeat mistakes caused by multiple Codex windows, WorkBuddy mirrors, local drafts, backup folders, and partial cloud-git visibility. ## Mandatory Pre-Work Check Run or consciously verify: ```bash sed -n '1,220p' AGENTS.md sed -n '1,260p' docs/research/pre_work_error_ledger.md git status --short --branch git remote -v python3 scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45 ``` The one-command gate must cover: - `tests/test_runtime_import_boundaries.py` - `tests/test_project_fragment_governance.py` - `tests/test_preflight_fragment_scan.py` - `tests/test_remote_repo_visibility_check.py` - `tests/test_pre_work_check.py` For large architecture or release work, also read: - `docs/research/whole_machine_fragment_sweep_round25_2026_06_25.md` - `docs/research/whole_machine_fragment_sweep_2026_07_05.md` - `docs/research/unique_main_chain_map_2026_07_01.md` - `docs/research/local_drafts_2026_06_disposition.md` ## Error Ledger | ID | Error / Risk | Current Status | Required Guard | |---|---|---|---| | ERR-001 | Runtime code pulled modules from `.workbuddy` distribution mirror. | resolved | Keep `tests/test_runtime_import_boundaries.py`; `.workbuddy` is reference only. | | ERR-002 | `mcp_server.py` documentation implied `.workbuddy` was a runtime path. | resolved | MCP top docs must point to main repo runtime; mirror wording must say distribution/reference only. | | ERR-003 | `local_drafts` mixed high-value research with disposable drafts. | mitigated | Use `docs/research/local_drafts_2026_06_disposition.md`; do not delete or promote drafts ad hoc. | | ERR-004 | Multiple local folders contain Jyotish fragments, older adapters, and WorkBuddy mirrors. | active | Read latest fragment sweep before changing adapters, oracle paths, or skill runtime boundaries. | | ERR-005 | Terminal git access to GitHub can fail even when the browser can open the repo. | active | Use `python3 scripts/remote_repo_visibility_check.py`; do not claim cloud sync unless status is `verified`. | | ERR-006 | Whole-machine `find` can time out when run too broadly. | active | Use split scans by directory and bounded `-maxdepth`; record timeouts as findings. | | ERR-007 | `.workbuddy/skills/jyotish-vedic-astrology` is a dirty historical mirror. | active | Never copy it over main repo. Use only for read-only comparison. | | ERR-008 | Current main workspace may be dirty with user/Codex changes. | active | Never reset or checkout. Read touched files before editing. | | ERR-009 | Astrology interpretation can drift into story-fitting from conversation history. | active | For blind technical reports, use only declared evidence packets/PDF and mark MEVG/real-case gaps. | | ERR-010 | VedAstro official/cloud evidence can be partial or dasha-conflicting. | active | Mark official closure partial unless exact endpoint/settings and raw output are verified. | | ERR-011 | Bare `pytest` command may be missing from PATH even when pytest module exists. | active | Use `python3 -m pytest ...` in acceptance commands. | | ERR-012 | Governance tests can fail if wording is narrower than the actual guardrail. | observed 2026-07-05 | Keep tests tied to explicit user-facing terms such as `开工前` and the ledger path. | | ERR-013 | GitHub API can fail from terminal Python even when browser/Web can open GitHub. | active | Treat `remote_repo_visibility_check.py` status `blocked` as authoritative for terminal parity; browser visibility alone is not sync proof. | | ERR-014 | Pre-work checks can be skipped when split across several manual commands. | mitigated | Use `python3 scripts/pre_work_check.py` as the one-command pre-work gate. | | ERR-015 | One-command pre-work can exceed desktop outer timeout if child command timeout is too wide or scan runs twice. | observed 2026-07-05 | Keep pytest child timeout bounded at 45s; let `pre_work_check.py` cache `preflight_fragment_scan.py` output for `tests/test_preflight_fragment_scan.py`. | | ERR-016 | Full `tests/test_api_server_security.py` can exceed the desktop outer timeout. | observed 2026-07-05 | Use focused API test slices during development; reserve full API file run for longer verification windows. | | ERR-017 | Pre-work gate could pass without checking the older Round 25 fragment sweep or aggregate external-engine adapter diagnostics. | mitigated 2026-07-05 | `scripts/pre_work_check.py` must require both whole-machine sweep docs and run `scripts/diagnose_external_engine_adapters.py --json` before substantial work. | | ERR-018 | External engine blockers can be described verbally but not carried into diagnostics. | mitigated 2026-07-05 | `diagnose_external_engine_adapters.py` must expose VedAstro closure plan and PyJHora/JHora install/license/ephemeris boundary; keep `docs/research/external_engine_blocker_research_2026_07_05.md` current. | | ERR-019 | WorkBuddy/cloud/local acceptance summaries can invent pass counts, stale asset counts, non-existent error docs, or wrong dasha windows. | mitigated 2026-07-06 | Read `docs/research/user_invocation_acceptance_error_log_2026_07_06.md`; run `scripts/user_invocation_acceptance_check.py` and `tests/test_user_invocation_acceptance_contract.py` before accepting ordinary-user skill invocation validation claims. | | ERR-020 | VedAstro official raw responses can be archived but hard to audit if no manifest/API listing exposes them. | mitigated 2026-07-08 | Keep `list_official_raw_response_archives()` and `GET /api/vedastro_gateway/archives`; tests must prove archived official raw responses are enumerable. | | ERR-021 | VedAstro raw archive manifests can exist outside the high-rigor evidence packet, leaving final reports unable to prove whether official raw evidence was archived. | mitigated 2026-07-08 | Keep `vedastro_official_raw_archive_manifest` in `machine_evidence_packet.sections` for API and MCP strict workflows. | | ERR-022 | Technique Audit Table can show VedAstro cloud state but omit whether archived official raw evidence is actually auditable. | mitigated 2026-07-08 | Keep `VedAstro Raw Archive Manifest` as a first-class Technique Audit Table row immediately after `VedAstro Cloud State`. | | ERR-023 | `professional_reading` can require a Technique Audit Table while omitting the user-visible VedAstro raw archive row. | mitigated 2026-07-08 | Keep `VedAstro Raw Archive Manifest` in `professional_reading.technique_audit_table_required_rows`. | | ERR-024 | VedAstro gateway status can choose `local_fallback` before `.env` is loaded, even when official endpoint/network settings are present. | mitigated 2026-07-08 | `gateway_status()` must load official readiness before resolving active backend; `run_gateway_packet()` must expose `official_closure_state` separately from legacy `status`. | | ERR-025 | VedAstro gateway can report legacy `status=ok` from catalog availability even when no official raw response is present. | mitigated 2026-07-08 | `official_closure_state=official_verified` requires `official_raw_response`; otherwise expose `official_closure_reason=official_raw_response_missing`. | | ERR-026 | VedAstro service adapter can obtain an official full-snapshot raw response while the user entrypoint drops it, leaving gateway official closure permanently blocked. | mitigated 2026-07-09 | `vedastro_user_entrypoint` must expose `vedastro_official_full_snapshot.raw_response_available` and root `official_raw_response` when explicitly requested; gateway tests must prove raw propagation reaches `official_verified`. | | ERR-027 | External engine readiness diagnostics can be mistaken for a completed same-chart parity comparison. | mitigated 2026-07-09 | `diagnose_external_engine_adapters.py` must expose `same_chart_parity_contract.required_outputs`, per-engine expected oracle fields, and `tested=false` until a real same-chart comparison runs. | | ERR-028 | Active birth-time rectification can stop at question generation and never narrow candidate clusters from user answers. | mitigated 2026-07-09 | `active_rectification_questions.score_answers()` must turn A/B/C/D answers into cluster rankings, next-round questions, and an explicit boundary that final rectification still needs candidate chart differences. | | ERR-029 | Basic git and premium cloud-drive skill packages can blur contents, privacy exclusions, and external-engine promises. | mitigated 2026-07-09 | `scripts/skill_release_manifest.py` must define edition contents, excluded private material, acceptance commands, and external-engine runtime boundaries before packaging. | | ERR-030 | Release packaging can misread non-ASCII tracked filenames when parsing quoted `git ls-files` output. | mitigated 2026-07-09 | Package builders must use `git ls-files -z` and decode NUL-separated paths before writing zip archives. | | ERR-031 | Premium skill zip can ship without user install prompts or replay schemas, leaving users and future oracle imports without a contract. | mitigated 2026-07-09 | `skill_release_package.py` must inject `INSTALL.md` and `USER_PROMPTS.md`; replay contracts must live in `references/real_case_calibration/` and `references/oracle/`. | | ERR-032 | Full smoke files can time out while focused slices pass; `test_full_reading_reports_ayanamsa_metadata_and_ai_prompt_pack` currently exposes `external_oracle_gap_summary=null`. | observed 2026-07-10 | Do not claim full `tests/test_cli_smoke.py` or full `tests/test_vedastro_external_technique_evidence.py` passed unless run to completion; use focused slices for related changes and track the prompt-pack gap separately. | | ERR-033 | Premium skill zip validation can accidentally depend on a parent Git repository, so a cloud-drive user may fail in a clean unzip directory. | mitigated 2026-07-10 | Release acceptance must include `tests/test_skill_release_clean_trial.py`; scripts such as `public_release_privacy_scan.py` must support non-Git unpacked zip directories. | | ERR-034 | A single `historical_event_backtest.build_report()` strict replay can exceed 120 seconds before returning a case result. | observed 2026-07-11 | Use `scripts/public_real_case_benchmark.py` for bounded batch evidence replay; keep strict workflow as a separately timed probe and report timeout as blocked. | | ERR-035 | `benchmarks/jyotish/scripts/run_pyjhora_compare.py --help` executes the benchmark and crashes when canonical fixtures are absent. | observed 2026-07-11 | Do not claim PyJHora parity from readiness. Generate canonical fixtures or harden the runner before the next same-chart batch. | | ERR-036 | `public_real_case_benchmark.py --rule-version compare` originally replayed both rule versions and exceeded the 120-second command budget. | mitigated 2026-07-11 | Compare mode must read precomputed `--comparison-v1` and `--comparison-v2` reports; never duplicate engine replay inside comparison. | | ERR-037 | `scripts/muntha.py` failed at import because `List` was used in an annotation but not imported. | resolved 2026-07-11 | Keep `tests/test_muntha_module.py`; a technique file does not count as available unless it imports and runs independently. | | ERR-038 | Real-case scoring counted the same planet twice when MD and AD had the same lord, inflating strong-hit scores and duplicating signals. | mitigated 2026-07-11 | V2.1 must deduplicate active lords before `_planet_score`; keep the same-MD/AD regression test and preserve legacy V2 reports for audit only. | | ERR-039 | `exact_label_rate` looked like classification accuracy even though the benchmark already knew the event domain and assigned the expected label at the strong threshold. | mitigated 2026-07-11 | Use `known_event_activation_rate` and `strong_activation_rate`; keep old names deprecated and never present them as predictive accuracy. | | ERR-040 | `.gitignore` excluded only parts of `scratch/`, leaving local helper files and `.serena/` visible to `git add .`. | resolved 2026-07-11 | Ignore `/scratch/` and `/.serena/` at repo root; keep a regression test for both private workspace directories. | | ERR-041 | Positive-event replay scores were interpreted as timing evidence even though nearby non-target dates could receive equal or higher scores. | mitigated 2026-07-11 | Keep the negative-control date-ranking pilot and `timing_precision_gate`; block exact-day/month claims while Top-3 ranking remains below the gate. | | ERR-042 | REST duplicated natal chart, Vimshottari and Sade Sati calculations, so True Node was ignored, the first Dasha balance drifted, and Saturn transit was fabricated. | resolved 2026-07-11 | Keep `tests/test_calculation_p0_regressions.py`; domain/CLI/REST must share `domain_calculation_service.py`, effective parameters and `result_hash`. | | ERR-043 | Localhost POST requests trusted CORS response headers as an execution guard; report Chromium could load external/local resources; async job IDs were predictable and persisted without capability authentication or TTL. | mitigated 2026-07-11 | Keep `tests/test_runtime_security_p0.py`; enforce Origin/Host/JSON, sandbox report resources, use random capability tokens, `0600` atomic records, TTL deletion and a bounded worker queue. Run an isolated Chromium network PoC before declaring the renderer fully hardened. | | ERR-044 | Focused selections that include legacy full chart API tests can still exceed the 120-second desktop command budget even after pure calculation tests pass. | observed 2026-07-11 | Keep P0 calculation/security tests pure and fast; profile the legacy chart fixture separately before using the full API file as a blocking CI gate. | | ERR-045 | Three-engine readiness was mistaken for completed same-chart parity. Public replay on 2026-07-13 captured jyotishganit raw and found only a PyJHora dasha artifact; VedAstro still had no official raw response. | active external blocker | Keep `three_engine_parity_runner.py`; status remains `blocked`/`partial` until all required raw artifacts are normalized into comparison rows. Latest blocker: `official_vedastro_raw_missing_or_unverified`. | | ERR-046 | Report-renderer SSRF/file PoC was blocked until a Playwright Chromium binary was installed. | mitigated 2026-07-13 | Keep route/JS-denial tests and run `scripts/report_renderer_isolation_poc.py`; only `status=pass` with zero HTTP probe requests and blocked file/http resources proves isolated rendering. Verified 2026-07-13: `status=pass`, `http_probe_requests=0`, blocked schemes `file/http`. | | ERR-047 | Initial `slow` marker partition for `test_api_server_security.py` still exceeded the 120-second desktop budget; heavy paths extend beyond VedAstro/high-rigor prefix groups. | active profiling blocker | Profile test node IDs in bounded subprocess batches, mark only measured heavy tests, and keep fast-security acceptance separate from long CI integration coverage. | | ERR-048 | Candidate-time scanner assumed all documented D4/D24/D30 divisions were exposed by `jyotish_engine.py varga`; actual `--d4` failed at runtime. | mitigated 2026-07-12 | Candidate scans must record unsupported Varga flags as `unavailable_vargas`; only successfully computed D1/D9/D10 fields may drive local sensitivity output until a unified Varga contract exists. | | ERR-049 | PyJHora benchmark runner executed on `--help`, used a wrong repository-root path in `run_skill_baseline.py`, and failed when reused without pre-created output directories. | mitigated 2026-07-12 | Keep `tests/test_pyjhora_compare_cli.py`; require explicit `--build-local`, safe argparse help, correct repo root, and directory creation inside `run_sample()`. | | ERR-050 | Prashna CLI/API/UI could synthesize or accept a non-question chart; legacy Tajika/Saham/Sphuta/Kunda paths also exposed approximate values as usable evidence. | mitigated 2026-07-14 | Require backend Swiss `PrashnaContext` with question text/time/location/timezone; reject client planets/ascendant. The engine's deterministic fallback branch has been removed. Block legacy Sphuta/Kunda/Gulika/Panchavargiya and no-location Saham paths; keep seven-planet Tajika interactions partial until named-yoga golden cases and formula parity exist. | | ERR-051 | Privacy redaction can replace executable numeric test fixtures with bare placeholder identifiers such as `REDACTED_YEAR`, causing `NameError` before a regression reaches its target. | observed 2026-07-12 | Public tests must use generic fixtures (for example 1990) or quoted placeholders only; run `rg -n "REDACTED_YEAR" tests` before release and repair executable occurrences. | | ERR-052 | Text-only privacy scanning cannot distinguish a harmless quoted placeholder from a bare Python identifier that will fail at runtime. | mitigated 2026-07-13 | `public_release_privacy_scan.py` parses shipped Python files and rejects executable `REDACTED_*` names; keep the AST regression test. | | ERR-053 | A parity manifest could label an external engine `official_verified` without a raw artifact, hash, or calculation settings, making claimed oracle closure unverifiable. | mitigated 2026-07-13 | `three_engine_parity_replay_validator.py` requires raw artifact existence, SHA-256 and settings for verified/imported external engines; otherwise parity is `invalid`. | | ERR-054 | Candidate-time sensitivity scanning used the legacy `varga` CLI, so D4/D24/D30 could appear unavailable despite being supported by `varga-full`. | resolved 2026-07-13 | Scanner calls `varga-full --divisions D4,D9,D10,D24,D30` once per candidate and reads its canonical `Ascendant.sign` fields. | | ERR-055 | The full-reading path called `calc_all_sahams()` without lat/lon/tz, so an otherwise computable Swiss day/night context was silently blocked. | resolved 2026-07-14 | Pass the calculation arguments' lat/lon/tz into the Saham layer; keep Saham formula maturity `partial` until oracle parity exists. | | ERR-056 | A WorkBuddy checkout of the same remote diverged substantially from the active source branch and can be mistaken for a mergeable mirror. | active | Read `whole_machine_fragment_sweep_2026_07_14.md`; do not copy or merge it without explicit commit-level review on a separate branch. | | ERR-057 | The release quality profile checked untracked files but did not execute the privacy AST scan or the real Chromium report-isolation probe. | mitigated 2026-07-14 | `release_hygiene_check()` now requires `public_release_privacy_scan.py --json` and `report_renderer_isolation_poc.py --strict`; parity manifest validation also runs as a contract check. | | ERR-058 | Formula-based Sahams used the day/night operand rules but omitted the documented zodiacal-order `+30°` exception. | mitigated 2026-07-14 | `_calc_formula_saham()` applies the `references/saham_rules.json` forward-arc condition and one-sign correction; keep external numeric oracle parity as a separate `partial` requirement. | | ERR-059 | Gulika was either an approximate fallback or falsely implied as a chart module output. | mitigated 2026-07-14 | `scripts/gulika.py` computes Prasna Marga Ghatika segment Ascendant with Swiss sunrise/sunset and Lahiri sidereal houses. It is exposed only as `prashna_context.supporting_indicators.gulika`, remains `partial`, and cannot unlock Sphuta or verdict layers until external numeric parity exists. | | ERR-060 | Legacy Sphuta functions combined approximate Gulika with interpretive signals, while the exact formula could not be inspected in the production question context. | mitigated 2026-07-14 | `prashna_sphuta.py` exposes formula-only Trisphuta/Catusphuta/Pancasphuta from the partial Gulika evidence. It is supporting-only; Kunda, life-sensitive Sphutas and Prashna verdicts remain blocked pending external numeric parity. | | ERR-061 | Full-reading passed longitude-only data to the Tajika layer, permanently blocking its speed-dependent seven-planet interaction evidence. | mitigated 2026-07-14 | Pass actual Swiss longitude/speed pairs. The output may expose only partial Ithasala/Easarapha candidates; named chains and event verdicts stay blocked pending golden cases. | | ERR-062 | A release gate could validate a parity manifest's shape without requiring all external engines to actually match, allowing “contract valid” to be mistaken for “oracle verified.” | mitigated 2026-07-14 | `three_engine_parity_replay_validator.py --require-pass` fails unless parity status is pass; `run_quality_gate.py --require-external-parity` exposes this as an explicit high-standard release requirement. | | ERR-063 | High-rigor API output could omit the three-engine parity state, especially on plan-only responses, allowing downstream UI or MCP callers to overstate verification. | mitigated 2026-07-14 | Every high-rigor execution and plan response carries `high_rigor_external_parity`; `require_external_parity=true` sets `success=false` unless parity is pass. | | ERR-064 | Western cross-system support accepted external JSON but did not calculate a tropical natal chart from standard birth input, inviting agents to treat missing Western data as a completed cross-check. | mitigated 2026-07-14 | `western_chart_engine.py` computes Swiss Ephemeris tropical natal evidence for direct-chart/rectification only. It remains `partial` until separately materialized timing evidence exists; Prashna and external-payload precedence are regression-tested. | | ERR-065 | A newly added release-critical script can be absent from a zip before its first Git commit because the package enumerates tracked files only. | mitigated 2026-07-14 | List `scripts/western_chart_engine.py` in `REQUIRED_CONTRACTS`; the release-package test proves both editions include it before commit. | | ERR-066 | The pre-work fragment sweep invoked a retired `audit-capabilities --mode strict` contract, so governance tests and the mandatory preflight failed before real checks ran. | mitigated 2026-07-14 | Invoke the supported `--mode validate`; `tests/test_preflight_fragment_scan.py` and `pre_work_check.py` must remain green before substantive work. | | ERR-067 | A generic “Western timing” label can imply techniques that have not been computed. | mitigated 2026-07-15 | Native timing requires explicit fields for each layer. Current native layers cover transit, solar-return, secondary-progression, solar-arc, converse, midpoint, lunar-return and daily duration scan; progressed angles, parans and interpretation remain explicitly blocked/partial. | | ERR-068 | PyJHora comparison reports hard-coded `2026-06-03` as generation time, making fresh external benchmark artifacts appear stale and weakening audit traceability. | mitigated 2026-07-15 | `write_report()` records an injected-or-current UTC ISO timestamp; keep the deterministic timestamp regression. | | ERR-069 | Yoga validation tests and helper runner still imported rules from a `.workbuddy` mirror, so full pytest could fail or silently validate a divergent checkout. | mitigated 2026-07-15 | Resolve repo root from each file location; retain runtime-boundary and focused Yoga regressions. | | ERR-070 | PyJHora parity for D2/D4/BAV/SAV can pass while Shadbala total virupas still mismatch, so a row-filled Shadbala oracle packet can be mistaken for absolute-value parity. | active external formula blocker | Keep `docs/research/pyjhora_d2_d4_ashtakavarga_shadbala_parity_2026_07_15.md`; do not claim Shadbala external absolute closure until component-level formulas reconcile with PyJHora/JHora raw values. | | ERR-071 | `runtime-truth` required an untracked `scratch/local/pdf_review_123456` JHora packet, so a clean public checkout failed before it could report the actual external-oracle boundary. | resolved 2026-07-16 | Release truth reads `references/evidence_manifests/jhora_master_evidence_manifest.json`; scratch is optional and may be repaired only through explicit `sync_final_evidence_packet_status.py --sync-local`. Manifest must retain `external_raw_required_for_official_verified=true`. | | ERR-072 | The 2026-07-14 sweep did not enumerate two `.workbuddy/backups` Jyotish Git snapshots, a Codex `audit_tmp` extraction, or the Kimi training archive, so a later window could mistake them for undiscovered production truth. | active 2026-07-16 | Read `whole_machine_fragment_sweep_2026_07_16.md`; classify every candidate by Git ancestry, relative-path diff, content, privacy, and supersession before any import. Never bulk-copy a backup or archive. | | ERR-073 | The external article warehouse contains 50 Jyotish source artifacts whose techniques can be absent from the repo even when broad labels such as Jaimini, Arudha, or Tajika are already marked covered. | active 2026-07-16 | Before technique expansion, build a source-ingestion manifest with hashes, provenance, extracted formula IDs, variant identity, copyright boundary, production coverage, and validation state. Broad registry labels must not imply article-level coverage. | | ERR-074 | Absent local-only quarantined drafts were counted as missing runtime references, causing clean strict workflows to degrade despite all production sources being present. | resolved 2026-07-16 | Keep quarantined paths as declared audit inventory, exclude non-runtime absence from readiness, and never promote them into runtime source refs. | | ERR-075 | `real_case_calibration_catalog()` unconditionally opened an untracked holdout manifest, so clean installs could silently lose the MCP runtime evidence log. | resolved 2026-07-16 | Missing optional holdout assets return structured `blocked` metadata instead of raising. | | ERR-076 | Fragment/inventory tests required machine-local drafts, workspace residue, or a fixed minimum file count. | resolved 2026-07-16 | Assert count invariants and stable tracked classifications; validate optional local categories only when present. | | ERR-077 | VedAstro request previews serialized the live `x-api-key` header, allowing logs and failed test output to expose credentials. | resolved; credential rotation required 2026-07-16 | Preview/metadata profiles never contain authentication headers. Inject `VEDASTRO_API_KEY` only immediately before network execution; rotate any key exposed before this fix. | | ERR-078 | On this macOS host, bare `python3` resolves to Python 3.9 without pytest, while the project requires Python >=3.11 and uses PEP 604 annotations. The pre-work launcher previously reused that incompatible interpreter for every child check. | resolved 2026-08-07 | `pre_work_check.py` must probe and prefer the repository `.venv` (Python >=3.11 with pytest), expose the selected runtime in its JSON report, and fail closed with setup guidance if no compatible runtime exists. Keep regression coverage for system-Python launch and strict `JYOTISH_PRE_WORK_PYTHON` override behavior. | | ERR-079 | VedAstro hosted replay and fixed-commit self-host validation cannot run on this host when `VEDASTRO_API_ENDPOINT` / `VEDASTRO_API_KEY` are absent and neither a .NET runtime nor a reachable Docker daemon is available. | observed 2026-07-17 | Keep hosted closure `blocked`; run `vedastro_contract_probe.py --repeats 3` only after injecting credentials through the environment, and build the pinned source in a provisioned Windows/.NET or reachable container environment. Never persist credentials in artifacts or shell history. | ## ERR-080 | Issue link was mistaken for benchmark provenance | mitigated 2026-07-18 PyJHora issue #17 is a UI/encoding issue with a general mismatch report, not VP Jain calibration. The benchmark now pins `V4.8.7` / `ca22995709bd60e371e7820a1a5efc80ce4cf821` and the exact test function URL. Treat its AGPL numeric expectations as a candidate replay, never independent formula arbitration. ## ERR-081 | Fixture attribution was overstated as publication | mitigated 2026-07-18 `shadbala_VPJainBook_tests` supplies no independently citable book edition, page, or numerical table. The product therefore calls it a VP Jain-attributed fixture, not a published worked example; it remains candidate replay data and cannot close a formula branch. ## ERR-082 | Public similar-case catalog coverage was mistaken for global coverage | active 2026-07-18 The replayable public-case manifest currently contains 10 events: 5 career and 5 marriage. A separate health `public_context_only` case may be shown for comparison, but it is not replayed calibration evidence. Wealth still has no case with the required birth source, event source, and replay contract. The product returns available domains and requested uncovered domains rather than treating an empty result as evidence of no comparable case. Prevention: add a new domain only after its public cases satisfy the same source/replay contract; never substitute loosely sourced celebrity notes or absence of a match for a negative conclusion. ## ERR-083 | Duplicate Supabase migration versions skipped required schema | resolved 2026-07-19 Four migration pairs reused the same timestamp prefix, while Supabase records that prefix as the migration identity. The remote ledger therefore recorded only one file from each pair: `chart_profiles`, `synastry_reports`, and part of the profile recovery contract were absent even though their SQL files existed locally. Dynamic birth-time migrations were also still pending after the application branch was merged. Prevention: `tests/test_supabase_migration_versions.py` requires every migration prefix to be unique. Preserve already-recorded versions, move skipped SQL into later uniquely numbered repair migrations, run `supabase db push --linked --dry-run`, and verify the remote migration ledger plus live schema before deploying dependent application code. ## ERR-092 | Staging SSH host key changed before release inspection | mitigated 2026-08-06 A direct strict SSH inspection of `118.26.111.127` stopped with `REMOTE HOST IDENTIFICATION HAS CHANGED`: the local file still contained an older ED25519/RSA/ECDSA set, while the server presented a new ED25519 fingerprint. The release was paused; strict host checking was never disabled. The current ED25519 key was accepted only after its complete key material and fingerprint matched the repository Actions variable `STAGING_KNOWN_HOSTS` exactly. The local `known_hosts` file was backed up, records for only this IP were removed, and only the trusted ED25519 record was installed. The staging deployment tree is root-owned and the SSH user cannot `cd` into it directly; inspections must use the existing constrained `sudo -n` workflow boundary rather than changing directory ownership or permissions. Prevention: on any staging host-key warning, stop before SSH/deploy; compare the observed key against an independently administered trusted source such as `STAGING_KNOWN_HOSTS`, and require exact key-material equality. Never trust `ssh-keyscan` alone, never use `StrictHostKeyChecking=no`, and never overwrite unrelated known-host entries. Preserve a local backup and record the trusted fingerprint. Do not `chmod` or `chown` `/opt/jyotisha-staging` to make ad-hoc inspection easier. ## ERR-093 | Staging env ownership drift blocked the reviewed backup helper | mitigated 2026-08-06 Before the personal-report staging migration, the encrypted backup helper correctly refused to write into the private `deploy`-owned backup tree when invoked as root. Read-only inspection then showed both `.env.staging` and `.env.staging.database` had drifted to `root:root 0600`, although the deployment tree, backup directory, state directory, and Docker-capable deployment account are owned by `deploy`; the operations runbooks explicitly require the env files to be owned by the deployment user. This made the correct `deploy` execution unable to read its database env while root could not pass the helper's private-directory ownership boundary. Prevention: before staging backup/migration, verify both env files are regular, non-symlink files owned by `deploy:deploy` with mode `0600`; restore only that documented owner/mode under the shared mutation lock, without printing or copying file contents. Run `backup-staging-postgres.sh` as `deploy`, never weaken its ancestor checks, never create a parallel root backup tree, and never broaden env permissions. ## ERR-094 | Gitea expanded a multiline staging SSH secret in failed workflow logs | mitigated 2026-08-06 A failed exact-SHA staging deploy displayed the multiline staging SSH private key in the job environment block instead of masking each line. Release mutations were stopped immediately. The staging-only key was rotated, the new key was verified before the exposed key was removed from `authorized_keys`, the old key was proven unable to authenticate and deleted locally, Gitea and GitHub staging secrets were replaced, and 28 potentially affected Gitea deploy/migration runs were deleted. The successful quality-gate run and immutable image manifest were retained because they never received the SSH secret. Prevention: store `STAGING_SSH_PRIVATE_KEY` only as one unwrapped base64 line; workflows decode it into a mode-`0600` temporary key, validate it with `ssh-keygen`, and delete the temporary directory on every exit. Contract tests must reject direct multiline `SSH_PRIVATE_KEY` injection or `printf` of a decoded secret variable. A leaked staging key must be rotated and revoked before any rerun; production keys remain a separate boundary and were not involved in this incident. ## ERR-095 | Gitea trusted-main full-history fetch stalls or exhausts every bounded attempt | mitigated 2026-08-06 After exact-SHA staging gate `1473` succeeded, automatic deploy `1474` stopped making log progress for an extended period in the empty-repository `git fetch --no-tags origin main "$DEPLOY_SHA"` step before any SSH or staging mutation. The fetch later recovered and the 18-minute run successfully deployed the exact SHA. The first mitigation added three 120-second attempts, but run `1480` proved every attempt still asked Gitea to enumerate/compress 16,093 full-history objects and then timed out. It failed closed before SSH; public and state SHAs remained on the prior healthy release. The first fix bounded queue occupation but did not reduce the transfer, and its regression test did not reject the full-history dual-ref form. Prevention: Gitea mutation workflows must perform no Git object operations. A successful staging gate packages its already-verified exact-SHA `deploy/` controller plus manifest validator into `controller.tar`, binds its SHA-256 into the strict image manifest, and uploads both as one immutable artifact. Deploy/migration must verify artifact run/SHA, controller digest, archive paths/types/duplicates/size, current `main == staging` refs, and a complete Gitea compare commit-DAG path before mutation; any missing or inconsistent evidence fails closed. Manual rollback still uses the current reviewed controller, never the old target's controller. Preserve exact-SHA images, forward-only defaults, shared mutation lock, and bounded API/artifact requests. Verified by PR gate `1481`, staging gate `1483`, and one-minute exact-SHA deploy `1484`; mutation-time `git fetch` was zero and all post-deploy health/schema/permission checks passed. ## ERR-096 | Quality-gate exact-SHA checkout failed on a transient low-speed window | resolved 2026-08-06 Staging gate `1485` failed before validation when its single exact-SHA shallow fetch hit the configured 30-second/1024-B/s low-speed abort, producing `curl 28`, `early EOF`, and no publish artifact. No deployment was triggered and the previous exact-SHA staging application remained healthy. This is separate from mutation-time Git removal: quality validation still must acquire the source under test. Prevention: both validate and publish exact-SHA checkouts use three bounded 300-second attempts, a 15-second connect timeout, and a 60-second/1-B/s stalled-transfer threshold. Preserve `--depth=1 --no-tags origin "$GITEA_SHA"`, exact HEAD equality, clean-tree checks, artifact non-reuse, and fail-closed exhaustion. Never report a skipped publish job as successful artifact publication. Closure evidence: exact-SHA PR gate `1523`, staging push gate `1525`, immutable artifact ID `12`, and deploy `1526` all succeeded for the reviewed release chain. ## ERR-097 | Staging host env missed the reviewed admin-origin selector | resolved 2026-08-06 Staging gate `1500` successfully validated and published the exact SHA, but automatic deploy `1502` stopped before app mutation with `invalid staging selector: ADMIN_USER_ORIGIN`. A redacted read-only check confirmed `.env.staging` remained `deploy:deploy 0600`, had one exact user origin, and had zero admin-origin definitions. Public staging therefore remained on the prior healthy SHA; this was not a migration failure and production was not involved. Prevention: when a reviewed identity rollout adds a host-managed non-secret selector, update the staging env under the shared mutation lock before deploying the dependent controller. Modify only the named public selector through a mode-`0600` atomic replacement that preserves deployment-tree UID/GID; never print or copy the raw env. Re-run the exact validator and require the same gate-attested SHA in `main`, `staging`, host state, and public health before closure. Closure evidence: both env files remained `deploy:deploy 0600`, deploy `1526` passed both validators, and dual-host anonymous boundaries matched the reviewed contract. ## ERR-098 | Non-empty staging volume missed service runtime bootstrap and retained an obsolete privileged membership | resolved 2026-08-06 After the admin-origin selector was repaired, the full staging validators exposed that both service runtime env entries were absent. Redacted role inspection then showed `service_role` existed but `service_runtime` did not, while `admin_runtime` retained membership in the BYPASSRLS role contrary to the reviewed bootstrap/RBAC contract. The running old web image had no recoverable service URL, so no password was guessed or copied. Under the shared mutation lock, a new staging-only credential was generated, the dedicated login role and CONNECT/membership were established through PostgreSQL stdin, the two host env files were atomically updated with their separate raw/URL representations, and the obsolete admin membership was revoked. Both validators and a real service login passed; production was not involved. Prevention: `/docker-entrypoint-initdb.d` is not a compatibility mechanism for an existing PostgreSQL volume. Every newly required runtime role must have a reviewed non-destructive repair path plus pre-deploy role/presence probes. Keep `admin_runtime` outside `service_role`; only `service_runtime` may assume the BYPASSRLS role through the dedicated service URL. Never display role passwords, pass them in argv, or edit an already-ledgered migration checksum to retrofit host bootstrap behavior. Closure evidence: final metadata audit reported service membership/login/CONNECT true, admin service membership and BYPASSRLS false, with migration `1516` and deploy `1526` successful. ## ERR-099 | Gitea frontend production build hung after successful compilation until job timeout | resolved 2026-08-06 Staging push gate `1507` completed all frontend tests (`1472/1472`), lint with zero errors, and Turbopack compilation in 38.2 seconds, then emitted no further build output for roughly 44 minutes. The 45-minute validate job expired, publish was skipped, no artifact or deployment was produced, and public staging remained on the previous healthy SHA. The same code had completed production builds in PR gates `1503` and `1505`, so the observed failure is a runner/build-finalization hang rather than a reported compile error. A manually dispatched diagnostic run does not satisfy the push-only publication contract and must not be treated as an immutable release artifact. Prevention: wrap the Gitea frontend production build in a command-level 600-second timeout with an explicit nonzero failure; retain the 45-minute job timeout as a second boundary. Never skip the build, reuse an old artifact, or treat a manual validation-only run as a successful staging push gate. Only a successful exact-SHA push gate may publish images and trigger deployment. Closure evidence: PR gates `1511`/`1519`/`1523` and push gates `1514`/`1521`/`1525` completed production builds within the command deadline; final publish/deploy succeeded. ## ERR-100 | Staging public verification checked exact SHA only once before proxy convergence | resolved 2026-08-06 Exact-SHA gate `1514` and migration `1516` succeeded, but deploy runs `1517` and `1518` each reached healthy target web/API containers and then failed public verification roughly three seconds later. Both runs restored the prior application image and retained the old deployed-revision state. The verifier retried only `/login`; once that endpoint returned 200 through the existing Caddy route, it performed exactly one check of public health SHA and the remaining authorization/private-health predicates. This permits an old upstream response to trigger immediate rollback during container/proxy convergence even though the new container itself carries the expected SHA. No application release completed and production was not involved. Prevention: within the existing bounded 60-second budget, retry the complete predicate set together: login, admin redirect, logged-out admin/account responses, public exact SHA, private API status, and Swiss Ephemeris availability. Success requires every predicate in the same attempt. On exhaustion, fail closed and emit only redacted status codes, observed SHA, and health booleans; never log response bodies, env, credentials, or error stacks. Closure evidence: deploy `1522` produced the intended redacted convergence evidence, and deploy `1526` passed the complete same-attempt predicate set. ## ERR-101 | Atomic Caddyfile replacement left the running Caddy bind-mounted to the old inode | resolved 2026-08-06 The bounded verifier in deploy `1522` proved that public health had converged to the target exact SHA and private API/Swiss checks passed, but admin checks on the user host returned the expected application fail-closed statuses rather than admin-host statuses. Read-only host inspection then found the reviewed host `deploy/Caddyfile.staging` contained the admin virtual host while `/etc/caddy/Caddyfile` inside the long-running Caddy container did not; their inode, size, and mtime differed even though Docker reported the expected bind source. The tree sync atomically replaced the source file, leaving the existing bind mount attached to the old inode. Both authoritative Spaceship nameservers returned the staging VPS address for the admin host when queried from the VPS, so this was not an absent DNS record. The failed deploy restored the prior application and did not advance deployed-revision. Prevention: after syncing a gate-attested single-file bind mount, force-recreate Caddy under the shared host lock before public verification. Verify user and admin origins separately: user-host admin paths must be 404; admin-host anonymous page/API must be 307-to-login and 401. Preserve bounded convergence, exact public SHA, private health, automatic rollback, and redacted diagnostics. Do not weaken identity host routing or modify DNS based on intercepted local resolver results. Closure evidence: deploy `1526` force-recreated Caddy, the container mounted the reviewed dual-host file, public TLS/routes passed, and all container restart counts remained zero. ## Fragment Sweep Command Set ## ERR-086 | Steve Jobs jyotishganit artifacts used non-San-Francisco coordinates | mitigated 2026-07-21 The jyotishganit Shadbala and field-comparison artifacts labelled the public case as San Francisco while using `37.3382, -122.0383`, unlike the canonical parity runner input `37.7749, -122.4194`. The affected artifacts are invalidated and production tuning remains blocked. Probe defaults now use the canonical coordinates; regeneration is still blocked in the active project virtualenv because `skyfield` is unavailable. Prevention: hash only normalized calculation-bearing input, require the location label and canonical coordinates to share one input contract, and reject an oracle artifact when its canonical input hash differs from the comparison packet. ## ERR-084 | Pre-work fragment test assumes zero candidates despite current audited candidates | active 2026-07-19 `scripts/pre_work_check.py` reported `fragment_audit.candidate_count=2` on 2026-07-19 and reports `3` in the 2026-07-20 run, while `tests/test_preflight_fragment_scan.py` requires exactly zero. The pre-work command therefore cannot be reported green until the candidates are classified or the test is updated to validate the reviewed state rather than a hard-coded count. Prevention: retain candidate identity and classification in the sweep artifact; do not mask candidates or weaken the pre-work result. Use split scans, not one unbounded full-home command: ```bash for d in /Documents /WorkBuddy /.workbuddy /Downloads /Desktop /.codex/attachments; do [ -d "$d" ] && find "$d" -maxdepth 6 -type d -name .git 2>/dev/null | sed 's#/.git$##' done | rg -i '印度|jyotish|vedic|astro|yinduzhanxing|workbuddy|星轨|codex|talk' | sort ``` ```bash for d in /Documents /WorkBuddy /.workbuddy /Downloads /Desktop /.codex/attachments; do [ -d "$d" ] && find "$d" -maxdepth 7 -type f \( -iname '*jyotish*' -o -iname '*vedic*' -o -iname '*jhora*' -o -iname '*shadbala*' -o -iname '*ashtakoot*' -o -iname '*印度占星*' -o -iname '*yinduzhanxing*' \) 2>/dev/null done ``` ## ERR-083 | Commercial Next production build terminates before artifact generation | active 2026-07-19 `frontend` local `npm run build` ends during Next.js 16.2.10 compile/static generation, both without configuration and with the CI Supabase placeholders. It leaves no `.next/BUILD_ID` or `.next/prerender-manifest.json`, and no application stack trace. Frontend contracts (`270 passed`), lint, and the selected Python commercial workflow regressions (`128 passed`) remain green. Prevention: do not equate this local host failure with an astrology capability regression. Treat GitHub Actions Node 22 build evidence as the deployment gate before merge. Keep VedAstro `premium_key_missing` and official raw snapshot status explicitly degraded. ## ERR-085 | Public production health cannot prove release identity, database migration, or authenticated workflow | active 2026-07-19 `https://jyotisha.chat` homepage and `/api/health` are reachable and healthy, but those responses do not expose a deployed Git SHA, Supabase migration ledger, evidence-packet TTL policy, or an authorized test-account session. Do not treat HTTP `200` as full release acceptance. Close this only through a deployment-attested SHA plus read-only migration/TTL evidence and an authorized browser acceptance account. ## ERR-087 | Production rectification stayed dependency-unavailable behind incomplete rollout identity | mitigated 2026-07-21 The production web service had no explicit V3 creation/migration/smoke rollout values, while the truth-source fallback pointed at one developer's macOS directory. Health therefore stayed `503` and a homepage rectification start failed as a dependency error even though the Python service and Supabase were reachable. Prevention: resolve the packaged repository root by default, deploy only an attested commit, and move creation from `smoke_only` to `public` only after the exact deployed SHA completes the authenticated synthetic smoke contract. ## ERR-088 | Candidate birth time polluted the reported declaration and blocked profile edits | mitigated 2026-07-21 The journey trigger copied `birth_time` into `reported_birth_time` and then raised `reported_birth_time_is_immutable` on a later account edit. This both changed the meaning of the user's original declaration and surfaced as a generic `PATCH /api/account` 500. Prevention: keep reported declarations editable, never derive them from active/candidate time, repair impossible `period_only`/`unknown` rows, and enforce the source/time consistency constraint in the database. ## ERR-089 | Technical readiness bypassed the three-event business gate on a first turn | mitigated 2026-07-21 A real production scan could return `ready_for_confirmation` before any historical evidence existed. The application then built a `confirming` first turn, while the database correctly accepts only an `active` first turn, producing a delayed `action_conflict` after the fee reservation and calculation. Prevention: gate every technical packet by `MINIMUM_SCOREABLE_EVENTS`; until three effective, historical, scoreable events exist, persist no result ID and expose only an active `pending_validation` turn. Keep the production smoke in `smoke_only` until this path completes against the deployed SHA. ## ERR-090 | Finance evidence passed the application contract but failed durable SQL validation | mitigated 2026-07-21 A real production first-turn scan completed, billing was released, and case creation returned the generic `action_conflict` response. The application contract included `finance`, and D2/D11 technical differences could select it, while the initial SQL validators and event table constraint still used an older evidence-domain list without `finance`. The SQL recap validator also omitted the optional `domain` field already emitted by the application. Prevention: keep evidence-request, life-event, private-candidate, public-recap, and event-row domain validation aligned in a forward migration, with migration regression coverage whenever the application evidence-domain enum evolves. ## ERR-091 | A technically empty narrowed segment terminated evidence collection | mitigated 2026-07-21 After accumulated historical evidence produced a very narrow winning segment, that segment could contain fewer than two linked samples or discriminating divisional themes. Packet construction treated this valid “not enough distinction yet” state as a dependency failure, so a later answer returned 503 even though scoring and the astrology service were healthy. Prevention: classify insufficient candidate-range discrimination explicitly; when a newly narrowed segment cannot support the technical evidence contract, retain the prior candidate range, preserve scored evidence, clear the unconfirmed result, and continue conversational collection. ## ERR-102 | Gitea returned HTTP 502 during final remote synchronization check | active 2026-08-09 Two final `git fetch origin --prune` attempts against the configured primary Gitea remote failed before ref exchange with HTTP `502`. The last locally verified refs remain available, but this run cannot prove that they are still current and must not claim a completed remote synchronization or push. Prevention: retry fetch and `git ls-remote` before any push or release action, compare the full `main`, `staging`, and migration-branch SHAs, and stop if Gitea remains unavailable. Do not substitute cached refs, the GitHub mirror, or a successful local commit for current Gitea synchronization evidence. ### Recurrence 2026-08-11 (rectification v9 follow-up, no push) The first final CAS `git ls-remote` against the primary Gitea remote returned HTTP `502` before any ref exchange; no push was attempted. A bounded retry ~15s later succeeded and confirmed the staging ref is still `5dd0ab66a9f715e04e2b8b4f4968df05caa80833`. Because the run ended without pushing, `git fetch origin --prune` plus a second CAS comparison of `main`/`staging`/migration-branch SHAs remain required before any push or release action. ## ERR-103 | Release Gate runner 缺少 Docker Compose v2 导致 17 个集成测试级联失败 | mitigated 2026-08-09 手工 Release Gate Run `1638` 在 `xiaoxin` 上通过 Docker Engine 检查后进入完整测试,但该 runner 不支持 `docker compose`,`--project-name` 与 `--env-file` 被 Docker 顶层 CLI 判为 unknown flag,导致 17 个 PostgreSQL、备份、身份和权限集成测试级联失败。候选 staging SHA、旧生产、Supabase 与 DNS 未被改变。 Prevention: 将该门禁运行在已验证 Docker Compose v2 的 `manman-linux`,并在安装依赖前以 `docker compose version --short` 强制 v2;不得把 `docker version` 当作 Compose 能力证明。新 SHA 必须重新完成 staging gate、公网 staging 身份和手工 Release Gate,失败 run 不得授权生产 migration、deploy 或维护停写。 ## ERR-104 | Consultation evidence packet can freeze before gateway evidence and omit existing local modules | mitigated 2026-08-10 The gateway did not request an official full snapshot by default, and the consultation workflow built its machine evidence packet before invoking that gateway, so configured credentials and readiness still produced no current raw response for the report. The same workflow also failed to attach the repository's existing Ashtakavarga and KP calculators to `chart.modules`, leaving both Technique Audit rows blocked despite valid local chart inputs. Prevention: make the gateway request official raw evidence without relying on an optional environment switch; invoke it before freezing the evidence packet; require `official_verified` plus a non-empty raw response before promoting official evidence; attach existing local calculator outputs through the shared consultation layer and keep KP values `observation_only` until an external worked-example parity gate closes. Regression tests must lock both raw-response propagation and module presence.