feat(skill): add gap truth audit

This commit is contained in:
732642856
2026-06-27 00:08:10 +08:00
parent 223a465781
commit a16a157f0a
4 changed files with 518 additions and 0 deletions
+20
View File
@@ -277,6 +277,26 @@ python3 scripts/validate_interpretation_templates.py --format markdown
完整排序见 `/Users/wuyongnaren/Documents/印度占星/docs/research/current_skill_core_gap_rerank_2026_06_26.md`
### Skill Gap Truth Audit(严禁过度声明)
当用户问“是否已经全球第一”“是否包含所有印度占星技法”“过去案例哪里错了”“还差什么硬任务”时,必须先运行:
```bash
python3 scripts/skill_gap_truth_audit.py --format markdown
```
真源文件:
`references/skill_gap_truth_registry.json`
此审计的结论优先级高于口头记忆:
-`can_claim_global_first: false`,不得宣称全球无争议第一。
-`can_claim_all_skills_complete: false`,不得宣称所有技法已完全封顶。
-`can_claim_perfect_accuracy: false`,不得宣称排盘、Dasha、Shadbala、年运等已达到完美精度。
- 若某技法为 `covered`,只能说“有稳定入口或可用层”,不能自动说成 `complete`
- 过去案例分析若触及 `past_case_analysis_corrections` 中的误判类型,必须主动修正并降低置信度。
## 全球开源定位
**当前还不能诚实地说这是全球开源印度占星 / 吠陀占星项目里的无争议第一。**
+164
View File
@@ -0,0 +1,164 @@
{
"schema_version": 1,
"scope": "jyotish_skill_gap_truth_registry",
"purpose": "Machine-readable truth boundary for the Jyotish skill: what remains unfinished, what must not be overclaimed, and which past analysis claims have been corrected.",
"public_claim_rules": {
"can_claim_global_first": false,
"can_claim_all_skills_complete": false,
"can_claim_perfect_accuracy": false,
"reason": "The skill has strong breadth, but external oracle closure, long-term benchmark history and several traditional judgment layers remain unfinished."
},
"hard_fronts": {
"dasha_external_oracle": {
"title": "Dasha external oracle",
"priority": "P0",
"status": "blocked_external_evidence",
"current_truth": "Dasha engines are usable, but exact start dates, balance periods and sub-period boundaries cannot be called externally closed until real JHora/PyJHora/book-example packets pass validation.",
"completion_standard": [
"At least one real external_verified packet is accepted for the first Dasha target.",
"Multiple Dasha families have versioned boundary comparisons.",
"Differences between local output and external oracle output are documented without production tuning from local data."
],
"forbidden_claims": [
"Dasha external oracle alone is complete",
"Exact Dasha dates are perfectly calibrated",
"One local chart output proves software-grade timing accuracy"
],
"next_actions": [
"Use scripts/dasha_oracle_closure_status.py to fill the first external packet.",
"Collect redacted JHora/PyJHora/book evidence under references/oracle/artifacts.",
"Re-run scripts/oracle_evidence_validator.py after packet application."
]
},
"shadbala_external_absolute_values": {
"title": "Shadbala external absolute values",
"priority": "P0",
"status": "blocked_external_evidence",
"current_truth": "Internal six-component Rupa/Virupa aggregation is usable, but external absolute-value closure is not complete.",
"completion_standard": [
"All seven visible planets have external Sthana, Dig, Kala, Chesta, Naisargika, Drik and total Rupa evidence.",
"Component sums match validated packet structure.",
"Any differences are explained component-by-component rather than hidden with a global multiplier."
],
"forbidden_claims": [
"Shadbala absolute values alone are fully JHora-calibrated",
"Relative planetary ranking proves absolute Rupa correctness",
"Global scaling alone fixes Shadbala"
],
"next_actions": [
"Use scripts/shadbala_oracle_closure_status.py for the first absolute-value packet.",
"Fill the REDACTED_PLACE/Raman or equivalent component table from an external oracle.",
"Reject production constant changes until component-level evidence is accepted."
]
},
"tajika_sahams_annual_closure": {
"title": "Tajika / Sahams annual closure",
"priority": "P0",
"status": "active_gap",
"current_truth": "Varshaphala, Muntha, Year Lord, Mudda Dasha and Sahams have local structure, but annual judgment depth and external sample closure remain incomplete.",
"completion_standard": [
"External annual packets include solar return time, Varsha Lagna, Muntha, Year Lord, Mudda Dasha, key Sahams and Tajika Yogas.",
"Annual interpretation templates distinguish calculation evidence from judgment confidence.",
"At least several public cases are benchmarked over multiple years."
],
"forbidden_claims": [
"Tajika or Sahams alone are fully closed",
"A calculated Saham alone predicts an annual event",
"Local Varshaphala output alone is external oracle evidence"
],
"next_actions": [
"Use scripts/tajika_annual_closure_status.py to fill the first annual packet.",
"Freeze the annual judgment template around Muntha, Year Lord, Mudda Dasha and Sahams.",
"Add public benchmark rows only after external annual evidence exists."
]
},
"article_template_industrialization": {
"title": "Article-level interpretation template industrialization",
"priority": "P1",
"status": "active_gap",
"current_truth": "Several high-granularity templates are frozen, but article-derived rules must keep being distilled into guarded templates with sources, cross-checks and forbidden claims.",
"completion_standard": [
"High-value topics have reusable templates in references/interpretation_template_registry.json.",
"Each template states required cross-checks, confidence ceiling and forbidden single-factor claims.",
"User-supplied article claims are treated as B/C-level clues unless supported by stronger sources."
],
"forbidden_claims": [
"Article claims alone are authoritative",
"A screenshot or online article alone proves a Jyotish rule",
"A high-granularity template replaces D1, Varga, Dasha or Transit"
],
"next_actions": [
"Keep extending references/interpretation_template_registry.json instead of scattering rules.",
"Run scripts/validate_interpretation_templates.py after each template addition.",
"Promote only source-graded, cross-checked templates into SKILL.md."
]
},
"long_term_public_benchmark": {
"title": "Long-term public benchmark",
"priority": "P0",
"status": "active_gap",
"current_truth": "Benchmark scripts exist, but the skill still lacks a long-running public history comparable to the strongest global projects.",
"completion_standard": [
"Capability, oracle readiness and public benchmark reports are versioned after every sample batch.",
"Benchmark rows separate internal consistency, external oracle evidence and interpretation maturity.",
"Global-first claims remain false until public evidence supports them."
],
"forbidden_claims": [
"Long-term benchmark alone is complete",
"A green local test suite alone proves global first status",
"Many covered techniques equal public benchmark leadership"
],
"next_actions": [
"Run scripts/public_benchmark_dashboard.py and scripts/oracle_closure_master_dashboard.py after evidence changes.",
"Publish markdown reports only after validation commands pass.",
"Track global-first gap as a durable public claim boundary."
]
}
},
"past_case_analysis_corrections": [
{
"id": "ashtakoot_not_all_zero",
"wrong_pattern": "Treating Ashtakoot as if it returned all zero scores.",
"corrected_truth": "Ashtakoot matrices and non-zero scoring exist; the remaining issue is external validation and finer-grained comparison, not total absence.",
"source_ref": "docs/research/antigravity_round25_ashtakoot_round24_claim_correction_2026_06_25.md"
},
{
"id": "panchanga_not_empty",
"wrong_pattern": "Treating Panchanga/Muhurta as completely blank.",
"corrected_truth": "Panchanga and Muhurta engines are deep; remaining work is UI, external oracle comparison and festival/v vrata breadth.",
"source_ref": "docs/research/antigravity_round26_panchang_round25_claim_correction_2026_06_25.md"
},
{
"id": "covered_is_not_complete",
"wrong_pattern": "Using covered and complete as if they meant the same thing.",
"corrected_truth": "Covered means there is a stable entry or usable layer; complete requires mature workflow, tests, boundary text and, where needed, external oracle closure.",
"source_ref": "docs/research/current_skill_core_gap_rerank_2026_06_26.md"
},
{
"id": "single_factor_reading_risk",
"wrong_pattern": "Drawing case conclusions from one planet, one yoga, one transit, one Dasha or one article rule.",
"corrected_truth": "Use D1, relevant Varga, Dasha, Transit, strength and historical verification where applicable. Single-factor readings should be capped at low confidence.",
"source_ref": "references/practitioner-wisdom-anti-dogma.md"
},
{
"id": "enemy_sign_not_debilitation",
"wrong_pattern": "Confusing enemy sign with debilitation.",
"corrected_truth": "Enemy sign and debilitation are separate dignity states. Do not label a planet as debilitated unless it is in the classical debilitation sign/degree zone.",
"source_ref": "references/common-misconceptions.md"
},
{
"id": "jaimini_kp_tajika_not_absent",
"wrong_pattern": "Describing Chara Dasha, KP/Prashna or Tajika/Sahams as absent.",
"corrected_truth": "These fronts have usable structures; the hard work is tail-difference closure, traditional workflow deepening and external sample validation.",
"source_ref": "docs/research/three_fronts_skill_depth_audit_2026_06_26.md"
}
],
"must_not_overclaim": [
"Dasha exact-date boundaries are externally closed.",
"Shadbala absolute Rupa values are fully calibrated against JHora or book examples.",
"Tajika/Sahams annual prediction is traditional-software-grade closed.",
"All Indian astrology techniques are complete.",
"The skill is already the undisputed global open-source number one.",
"A single chart factor, article rule, screenshot or template can override D1/Varga/Dasha/Transit convergence."
]
}
+245
View File
@@ -0,0 +1,245 @@
#!/usr/bin/env python3
"""Audit the current Jyotish skill truth boundary."""
from __future__ import annotations
import argparse
import json
import subprocess
import sys
from datetime import datetime, timezone
from pathlib import Path
from typing import Any
ROOT = Path(__file__).resolve().parents[1]
PYTHON = sys.executable
DEFAULT_REGISTRY = ROOT / "references" / "skill_gap_truth_registry.json"
def _resolve(path: str | None) -> Path:
if not path:
return DEFAULT_REGISTRY
candidate = Path(path)
return candidate if candidate.is_absolute() else ROOT / candidate
def _load_json(path: Path) -> dict[str, Any]:
with path.open("r", encoding="utf-8") as fh:
return json.load(fh)
def _run_json(command: list[str]) -> dict[str, Any]:
completed = subprocess.run(
command,
cwd=ROOT,
text=True,
capture_output=True,
timeout=120,
check=False,
)
if completed.returncode != 0:
raise RuntimeError(completed.stderr.strip() or completed.stdout.strip())
return json.loads(completed.stdout)
def _validate_registry(registry: dict[str, Any]) -> list[str]:
problems: list[str] = []
if registry.get("scope") != "jyotish_skill_gap_truth_registry":
problems.append("invalid_scope")
hard_fronts = registry.get("hard_fronts")
if not isinstance(hard_fronts, dict) or not hard_fronts:
problems.append("missing_hard_fronts")
hard_fronts = {}
for front_id, front in hard_fronts.items():
for field in [
"title",
"priority",
"status",
"current_truth",
"completion_standard",
"forbidden_claims",
"next_actions",
]:
if front.get(field) in (None, "", [], {}):
problems.append(f"{front_id}:missing_{field}")
if "alone" not in " ".join(front.get("forbidden_claims", [])).lower():
problems.append(f"{front_id}:forbidden_claims_should_block_single_factor_or_overclaim")
corrections = registry.get("past_case_analysis_corrections")
if not isinstance(corrections, list) or not corrections:
problems.append("missing_past_case_analysis_corrections")
corrections = []
for correction in corrections:
for field in ["id", "wrong_pattern", "corrected_truth", "source_ref"]:
if correction.get(field) in (None, "", [], {}):
problems.append(f"correction:missing_{field}")
source_ref = correction.get("source_ref")
if source_ref and not (ROOT / source_ref).exists():
problems.append(f"correction:missing_source_ref:{source_ref}")
return problems
def build_report(registry_path: Path) -> dict[str, Any]:
registry = _load_json(registry_path)
problems = _validate_registry(registry)
capability = _run_json([PYTHON, "scripts/audit_capabilities.py", "--mode", "validate"])
oracle = _run_json([
PYTHON,
"scripts/oracle_closure_master_dashboard.py",
"--format",
"json",
])
hard_fronts = registry.get("hard_fronts", {})
remaining = [
{
"id": front_id,
"title": front["title"],
"priority": front["priority"],
"status": front["status"],
"current_truth": front["current_truth"],
"completion_standard": front["completion_standard"],
"next_actions": front["next_actions"],
}
for front_id, front in hard_fronts.items()
]
priority_rank = {"P0": 0, "P1": 1, "P2": 2}
remaining.sort(key=lambda item: (priority_rank.get(item["priority"], 99), item["id"]))
claim_rules = registry.get("public_claim_rules", {})
can_claim_global_oracle = oracle["summary"]["can_claim_global_oracle_closure"]
can_claim_global_first = bool(
claim_rules.get("can_claim_global_first")
and can_claim_global_oracle
and capability.get("valid")
)
can_claim_all_skills_complete = bool(
claim_rules.get("can_claim_all_skills_complete")
and can_claim_global_oracle
and capability.get("status_counts", {}).get("covered", 0) == 0
)
can_claim_perfect_accuracy = bool(
claim_rules.get("can_claim_perfect_accuracy")
and can_claim_global_oracle
and oracle["summary"].get("production_tuning_allowed")
)
corrections = registry.get("past_case_analysis_corrections", [])
return {
"scope": "jyotish_skill_gap_truth_audit",
"schema_version": 1,
"generated_at": datetime.now(timezone.utc).isoformat(),
"registry": str(registry_path.relative_to(ROOT) if registry_path.is_relative_to(ROOT) else registry_path),
"valid": not problems,
"summary": {
"technique_count": capability["technique_count"],
"capability_valid": capability["valid"],
"capability_problem_count": capability["problem_count"],
"status_counts": capability["status_counts"],
"hard_front_count": len(hard_fronts),
"past_correction_count": len(corrections),
"registry_problem_count": len(problems),
},
"public_claim": {
"can_claim_global_first": can_claim_global_first,
"can_claim_all_skills_complete": can_claim_all_skills_complete,
"can_claim_perfect_accuracy": can_claim_perfect_accuracy,
"reason": claim_rules.get("reason", ""),
},
"oracle_closure": {
"summary": oracle["summary"],
"next_action_order": oracle.get("next_action_order", []),
},
"remaining_hard_fronts": remaining,
"past_correction_ids": [item["id"] for item in corrections],
"past_case_analysis_corrections": corrections,
"must_not_overclaim": registry.get("must_not_overclaim", []),
"problems": problems,
"boundary": (
"This audit answers the skill-level truth question. A covered technique is not the same as a "
"complete externally closed technique; single-factor case readings must remain confidence-capped."
),
}
def render_markdown(report: dict[str, Any]) -> str:
claim = report["public_claim"]
summary = report["summary"]
oracle = report["oracle_closure"]["summary"]
lines = [
"# Jyotish Skill Gap Truth Audit",
"",
f"Generated: `{report['generated_at']}`",
"",
"## Public Claim Boundary",
"",
f"- can_claim_global_first: `{str(claim['can_claim_global_first']).lower()}`",
f"- can_claim_all_skills_complete: `{str(claim['can_claim_all_skills_complete']).lower()}`",
f"- can_claim_perfect_accuracy: `{str(claim['can_claim_perfect_accuracy']).lower()}`",
f"- reason: {claim['reason']}",
"",
"## Capability Snapshot",
"",
f"- technique_count: `{summary['technique_count']}`",
f"- capability_valid: `{str(summary['capability_valid']).lower()}`",
f"- hard_front_count: `{summary['hard_front_count']}`",
f"- past_correction_count: `{summary['past_correction_count']}`",
"",
"## External Oracle Closure",
"",
f"- total_tasks: `{oracle['total_tasks']}`",
f"- external_verified_tasks: `{oracle['external_verified_tasks']}`",
f"- open_tasks: `{oracle['open_tasks']}`",
f"- can_claim_global_oracle_closure: `{str(oracle['can_claim_global_oracle_closure']).lower()}`",
"",
"## Remaining Hard Fronts",
"",
]
for front in report["remaining_hard_fronts"]:
lines.extend(
[
f"### {front['title']}",
"",
f"- id: `{front['id']}`",
f"- priority: `{front['priority']}`",
f"- status: `{front['status']}`",
f"- current_truth: {front['current_truth']}",
"",
]
)
lines.extend(["## Past Corrections", ""])
for correction in report["past_case_analysis_corrections"]:
lines.extend(
[
f"- `{correction['id']}`: {correction['corrected_truth']}",
]
)
lines.extend(["", "## Must Not Overclaim", ""])
lines.extend(f"- {item}" for item in report["must_not_overclaim"])
lines.extend(["", "## Boundary", "", report["boundary"], ""])
if report["problems"]:
lines.extend(["## Problems", ""])
lines.extend(f"- {problem}" for problem in report["problems"])
lines.append("")
return "\n".join(lines)
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Audit Jyotish skill gap truth boundary")
parser.add_argument("--registry", help="Path to skill_gap_truth_registry.json")
parser.add_argument("--format", choices=["json", "markdown"], default="json")
parser.add_argument("--output", help="Optional output path")
return parser.parse_args(argv)
def main(argv: list[str] | None = None) -> int:
args = parse_args(argv)
report = build_report(_resolve(args.registry))
text = json.dumps(report, ensure_ascii=False, indent=2) if args.format == "json" else render_markdown(report)
if args.output:
output = Path(args.output)
output.parent.mkdir(parents=True, exist_ok=True)
output.write_text(text, encoding="utf-8")
print(text)
return 0 if report["valid"] else 1
if __name__ == "__main__":
raise SystemExit(main())
+89
View File
@@ -0,0 +1,89 @@
#!/usr/bin/env python3
"""Tests for the skill-level gap truth audit."""
from __future__ import annotations
import json
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
REGISTRY = ROOT / "references" / "skill_gap_truth_registry.json"
def test_skill_gap_truth_registry_lists_hard_fronts_and_past_corrections() -> None:
data = json.loads(REGISTRY.read_text(encoding="utf-8"))
assert data["scope"] == "jyotish_skill_gap_truth_registry"
assert data["public_claim_rules"]["can_claim_global_first"] is False
assert data["public_claim_rules"]["can_claim_all_skills_complete"] is False
hard_fronts = data["hard_fronts"]
required_fronts = {
"dasha_external_oracle",
"shadbala_external_absolute_values",
"tajika_sahams_annual_closure",
"article_template_industrialization",
"long_term_public_benchmark",
}
assert required_fronts <= set(hard_fronts)
for front_id in required_fronts:
front = hard_fronts[front_id]
assert front["status"] in {"blocked_external_evidence", "active_gap"}
assert front["priority"] in {"P0", "P1", "P2"}
assert front["completion_standard"]
assert front["forbidden_claims"]
assert front["next_actions"]
corrections = data["past_case_analysis_corrections"]
correction_ids = {item["id"] for item in corrections}
assert "ashtakoot_not_all_zero" in correction_ids
assert "panchanga_not_empty" in correction_ids
assert "covered_is_not_complete" in correction_ids
assert "single_factor_reading_risk" in correction_ids
def test_skill_gap_truth_audit_outputs_current_truth_boundary() -> None:
completed = subprocess.run(
[sys.executable, "scripts/skill_gap_truth_audit.py", "--format", "json"],
cwd=ROOT,
text=True,
capture_output=True,
timeout=120,
check=False,
)
assert completed.returncode == 0, completed.stderr or completed.stdout
report = json.loads(completed.stdout)
assert report["scope"] == "jyotish_skill_gap_truth_audit"
assert report["valid"] is True
assert report["summary"]["technique_count"] >= 79
assert report["summary"]["capability_valid"] is True
assert report["summary"]["hard_front_count"] >= 5
assert report["public_claim"]["can_claim_global_first"] is False
assert report["public_claim"]["can_claim_all_skills_complete"] is False
assert report["public_claim"]["can_claim_perfect_accuracy"] is False
assert "Dasha" in report["must_not_overclaim"][0]
assert report["oracle_closure"]["summary"]["can_claim_global_oracle_closure"] is False
assert report["remaining_hard_fronts"][0]["id"] == "dasha_external_oracle"
assert "covered_is_not_complete" in report["past_correction_ids"]
def test_skill_gap_truth_audit_markdown_is_human_readable() -> None:
completed = subprocess.run(
[sys.executable, "scripts/skill_gap_truth_audit.py", "--format", "markdown"],
cwd=ROOT,
text=True,
capture_output=True,
timeout=120,
check=False,
)
assert completed.returncode == 0, completed.stderr or completed.stdout
markdown = completed.stdout
assert "# Jyotish Skill Gap Truth Audit" in markdown
assert "can_claim_global_first: `false`" in markdown
assert "Dasha external oracle" in markdown
assert "Past Corrections" in markdown