Skip to content

Anki Factory: add GitHub ops gates - #10

Open
dldydghk03 wants to merge 2 commits into
mainfrom
codex/anki-factory-github-ops-clean
Open

Anki Factory: add GitHub ops gates#10
dldydghk03 wants to merge 2 commits into
mainfrom
codex/anki-factory-github-ops-clean

Conversation

@dldydghk03

Copy link
Copy Markdown
Owner

Summary

  • Add public-safe Anki Factory schemas, eval fixtures, quality gates, and APKG profiling utilities.
  • Add Copilot/agent instructions, issue templates, PR checklist, labels, CI smoke artifact upload, and Pages dashboard generation.
  • Add a Codespaces devcontainer so the public smoke gate is reproducible in a clean environment.

Validation

  • .github/skills/anki-factory-quality/scripts/run-smoke.sh
  • python3 tools/anki-factory/scripts/validate_copilot_integration.py --repo .
  • YAML parse for .github/workflows/anki-factory-ci.yml and .github/workflows/anki-factory-pages.yml

Privacy Boundary

  • No private lecture notes, Drive exports, generated APKGs, recovered exam text, local run outputs, or Vault/output data are included.
  • Real private deck findings should be converted into synthetic fixtures before entering this repo.

Gate Checklist

  • Preview/read-back/approval requirements are documented for APKG-affecting workflows.
  • CI uploads the public anki-factory-smoke-report artifact.
  • fixture_gate, copilot_integration_gate, and agent_eval_gate are validated by smoke.
  • Public fixture and instruction boundaries are checked by validate_copilot_integration.py.

@dldydghk03

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 10c1d5f0f5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +469 to +472
rejected_config_hashes: dict[str, str] = {}
for key, spec in specs.items():
for rejected_id in spec.get("rejected_duplicate_source_notetype_ids", []):
rejected_config_hashes[str(rejected_id)] = key

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Enforce rejected note-type IDs during APKG validation

The contract-driven rejected_duplicate_source_notetype_ids map is constructed but never enforced, and the gate instead relies on a single hard-coded config_sha256 check. That means decks lacking config_sha256 metadata (for example legacy collection.anki2 profiles) can still match standard_cloze by name+fields and bypass the intended rejection of known bad duplicate note types, so the APKG gate may accept a format that the contract explicitly bans.

Useful? React with 👍 / 👎.

Comment on lines +148 to +149
if "collection.anki21b" in names and shutil.which("zstd"):
archive.extract("collection.anki21b", workdir)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle anki21b decks when zstd is unavailable

collection.anki21b is only processed when an external zstd binary is present; otherwise the function falls through and reports the APKG as unsupported. In a clean environment without zstd, APKGs that contain only collection.anki21b (a format this tool is meant to support) cannot be profiled, which breaks downstream apkg_profiler/quality_gate usage unless users discover and install an undeclared system dependency.

Useful? React with 👍 / 👎.

parser.add_argument("--contract", required=True, help="standardized-anki-contract.json")
parser.add_argument("--cards", help="Candidate card JSON to validate")
parser.add_argument("--apkg", help="APKG to validate")
parser.add_argument("--strict-template-hash", action="store_true", help="Require canonical anki21b template/config hashes when available")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Require template fingerprint checks for APKG gate by default

The APKG validator only enforces note-type config fingerprint equality when --strict-template-hash is explicitly passed, but the default path accepts name+field matches even if template/config hashes drift. As a result, a deck with modified templates/CSS can pass quality_gate.py --apkg under default invocation, despite the contract’s non-negotiable rule that templates must not be altered.

Useful? React with 👍 / 👎.

<article class="panel">
<h2>Fixture Gate</h2>
<div class="metric">{status_label(bool(fixture_gate.get('ok')))}</div>
<p>Good fixture warnings: {html.escape(str(len(as_list(good_fixture.get('warnings')))))}</p>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 Badge Render good fixture warning counts correctly in dashboard

The dashboard treats fixture_gate.good.warnings as a list, but validate_public_fixtures.py emits it as a numeric count. Because as_list() converts non-lists to [], the UI will always display Good fixture warnings: 0 even when the smoke report records warnings, which makes the published quality summary inaccurate.

Useful? React with 👍 / 👎.

@dldydghk03

Copy link
Copy Markdown
Owner Author

@codex review

Runtime wrapper update pushed in 2867ff6. Please review the public-safe Anki Factory one-command pipeline, runtime_smoke wiring, and eval coverage for the new runtime-wrapper regression case.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2867ff6d39

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +130 to +131
if not isinstance(cards, list):
raise SystemExit("--cards must be a JSON array")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Accept non-array card payloads in human review pack

run_anki_factory.py runs quality_gate.py and then human_review_pack.py on the same --cards file, but quality_gate.load_cards() accepts wrapped payloads like { "cards": [...] } while human_review_pack.py hard-fails unless the root JSON is a list. This creates a real pipeline break where a card file can pass the quality gate and then immediately fail the review-pack step (--cards must be a JSON array), so the one-command runtime flow rejects an input format it already claims to support.

Useful? React with 👍 / 👎.

require("$GITHUB_STEP_SUMMARY" in workflow, "CI workflow must publish the smoke report summary")
require("anki-factory-ci-artifacts/smoke-report.json" in workflow, "CI workflow must persist the smoke report JSON")
for glob in EXPECTED_PATH_GLOBS:
require(workflow.count(glob) >= 2, f"CI path filter must include {glob} for pull_request and push")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Parse CI path filters by trigger section, not raw string count

validate_hook_and_ci() enforces CI path coverage with workflow.count(glob) >= 2, which only counts raw occurrences in the YAML text. Because it does not verify one occurrence under pull_request.paths and one under push.paths, a path can be removed from push and duplicated under pull_request while this check still passes, allowing main-branch pushes for that path to skip the smoke workflow without the integration gate detecting the regression.

Useful? React with 👍 / 👎.

Comment on lines +79 to +80
"available": bool(paths),
"files": [source_file(path, note) for path in paths],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Mark missing source files as unavailable in source bundles

source_group() sets available from bool(paths) instead of checking that listed files exist, so a typoed or deleted input path is still reported as available in source-bundle.json. This causes downstream planning to treat required lecture/jokbo inputs as present even when the files are missing on disk, which can let runs proceed with invalid source coverage and misleading intake reports.

Useful? React with 👍 / 👎.

if quality_report and (quality_report.get("errors") or quality_report.get("warnings")):
status = "needs_rewrite"
manifest = {
"ok": status in {"preview_ready", "needs_card_candidates"},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fail run manifest when required intake inputs are missing

run_anki_factory.py marks a run as successful whenever status is needs_card_candidates, but that status is also used when source intake is incomplete (for example, lecture_only_preview without any --lecture). In that case the manifest still returns ok: true and suggests drafting cards next, which masks a blocked prerequisite and can allow automation to treat an invalid run as healthy.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant