{"id":50938694,"url":"https://github.com/dzylab/kronos-ci","last_synced_at":"2026-06-17T12:00:17.101Z","repository":{"id":363818989,"uuid":"1265065079","full_name":"dzylab/kronos-ci","owner":"dzylab","description":"Pull-request discipline gate for AI-assisted coding — runs your tests, scans for secrets, guards your main. Any editor, any CI.","archived":false,"fork":false,"pushed_at":"2026-06-10T12:48:51.000Z","size":1790,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-10T14:21:46.662Z","etag":null,"topics":["ai-agents","automation","ci-cd","claude-code","code-quality","continuous-integration","copilot","cursor","developer-tools","git-hooks","github-actions","pre-commit","pull-requests","secrets-detection","testing","vibe-coding","vscode","windsurf","workflow"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dzylab.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":"THREAT_MODEL.md","audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-10T12:37:20.000Z","updated_at":"2026-06-10T13:19:34.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dzylab/kronos-ci","commit_stats":null,"previous_names":["dzylab/kronos-ci"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/dzylab/kronos-ci","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dzylab%2Fkronos-ci","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dzylab%2Fkronos-ci/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dzylab%2Fkronos-ci/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dzylab%2Fkronos-ci/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dzylab","download_url":"https://codeload.github.com/dzylab/kronos-ci/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dzylab%2Fkronos-ci/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34447266,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-17T02:00:05.408Z","response_time":127,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","automation","ci-cd","claude-code","code-quality","continuous-integration","copilot","cursor","developer-tools","git-hooks","github-actions","pre-commit","pull-requests","secrets-detection","testing","vibe-coding","vscode","windsurf","workflow"],"created_at":"2026-06-17T12:00:15.367Z","updated_at":"2026-06-17T12:00:16.861Z","avatar_url":"https://github.com/dzylab.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg width=\"1774\" height=\"887\" alt=\"KRONOS CI\" src=\"KRONOS-CI-banner.png\" /\u003e\r\n\r\n# KRONOS CI\r\n\r\n\u003e A pull-request discipline gate for AI-assisted (and human) development.\r\n\u003e It **verifies artifacts, not declarations** — instead of trusting that \"the tests passed\",\r\n\u003e it runs your tests itself and fails the check if they don't.\r\n\r\n**Version 0.6.0** · GPL-3.0 · sibling of **[KRONOS](https://github.com/dzylab/kronos)** (the\r\nClaude Code commit-time engine). KRONOS guards an AI coding session locally; **KRONOS CI guards the\r\nshared branch in CI** — for *any* contributor and *any* tool (Cursor, Copilot, a local LLM, or a\r\nhuman), because it lives below the AI layer, at the pull request.\r\n\r\n\u003e 🌊 **New to all this, or a vibe coder?** Start with **[VIBE-CODING.md](VIBE-CODING.md)** — a\r\n\u003e plain-words guide that gets you running in ~3 minutes.\r\n\r\n---\r\n\r\n## What it checks\r\n\r\nOn each pull request (or push), KRONOS CI runs up to ten independent checks. Each is off by\r\ndefault (except the merge-conflict and secrets scans) and turned on via the Action inputs:\r\n\r\n| Check | What it does | Fails the gate when… |\r\n|---|---|---|\r\n| **TEST** | Runs your `test-command` itself (optionally scans its output) | it exits non-zero — or, with `scan-test-output`, prints a failure marker on exit 0 |\r\n| **COVERAGE** | Runs `coverage-command` and parses the percentage | coverage is below `coverage-min`, or no percentage found |\r\n| **LINT** | Runs your `lint-command` | it fails **and** `lint-required: true` (else advisory) |\r\n| **PLAN** | Looks for a plan file (`plan-glob`) | no file ≥ `plan-min-lines` lines exists |\r\n| **DOCS** | Compares the diff: code-vs-docs | code changed but no docs changed |\r\n| **DIFFSCAN** | Scans added diff lines | a merge-conflict marker (always) or a `forbidden-patterns` match is present |\r\n| **SECRETS** | Scans added diff lines for credential shapes (AWS keys, GitHub tokens, private keys, hardcoded passwords). **ON by default**; never prints the secret itself | a credential shape is added |\r\n| **SIZE** | Counts the added lines | more than `size-max-lines` (advisory unless `size-required`) |\r\n| **COMMIT-MSG** | Checks commit subjects | a subject doesn't match `commit-pattern` |\r\n| **WORKFLOW** | Verifies a committed `WORKFLOW.md` (the full 5-stage process) | a stage is `[x]` without its artifact, or left open |\r\n\r\nThe gate exits non-zero if any **required** check fails, so branch protection can require it and\r\nblock the merge. A genuine hotfix can [bypass it](#bypass-for-genuine-hotfixes) — loudly and on the record.\r\n\r\n---\r\n\r\n## 60-second setup\r\n\r\nThe fastest way — let it bootstrap itself (detects pytest / npm / go / cargo):\r\n\r\n```bash\r\npython /path/to/kronos-ci/kronos_ci.py init\r\n```\r\n\r\nOr by hand:\r\n\r\n1. Copy [`examples/kronos.yml`](examples/kronos.yml) into your repo at `.github/workflows/kronos.yml`.\r\n2. Set your `test-command` (e.g. `pytest -q`, `npm test`, `go test ./...`).\r\n3. Commit. Open a PR — KRONOS CI runs and reports.\r\n\r\n```yaml\r\n- uses: actions/checkout@v4\r\n  with:\r\n    fetch-depth: 0          # needed only for the diff-based checks\r\n- uses: dzylab/kronos-ci@v0.6.0\r\n  with:\r\n    test-command: \"pytest -q\"\r\n```\r\n\r\nTo make it a merge blocker: repo **Settings → Branches → Branch protection → Require status checks**,\r\nand select **KRONOS CI**.\r\n\r\n---\r\n\r\n## Configuration (Action inputs)\r\n\r\n| Input | Default | Meaning |\r\n|---|---|---|\r\n| `test-command` | `\"\"` | Shell command to run the tests. Empty = TEST skipped. |\r\n| `lint-command` | `\"\"` | Shell command to lint. Empty = LINT skipped. |\r\n| `lint-required` | `\"false\"` | `true` makes lint failures fail the gate. |\r\n| `require-plan` | `\"false\"` | `true` requires a plan file. |\r\n| `plan-glob` | `\"plans/*.md\"` | Where plans live. |\r\n| `plan-min-lines` | `\"20\"` | Minimum plan length. |\r\n| `require-docs` | `\"false\"` | `true` requires docs changes when code changes. |\r\n| `code-paths` | `src/**,lib/**,app/**,*.py,*.js,*.ts,*.go,*.rs,*.java,*.rb` | Globs counted as code. |\r\n| `docs-paths` | `docs/**,*.md,README*` | Globs counted as docs. |\r\n| `base-ref` | `\"\"` | Diff base. Default: the PR base, else `HEAD~1`. |\r\n| `scan-test-output` | `\"false\"` | Also fail TEST on failure markers even when it exits 0. |\r\n| `test-fail-markers` | `Traceback…,FAILED,=== FAILURES ===` | Substrings that mean \"tests failed\". |\r\n| `forbidden-patterns` | `\"\"` | Comma-separated regexes forbidden in added diff lines (DIFFSCAN). |\r\n| `commit-pattern` | `\"\"` | Regex every commit subject must match (e.g. conventional commits). |\r\n| `allow-bypass` | `\"true\"` | Honor a bypass token in the latest commit message. |\r\n| `bypass-token` | `[kronos skip]` | The token that bypasses the gate (recorded loudly). |\r\n| `workflow-file` | `\"\"` | Path to a committed `WORKFLOW.md` to verify the full process. Empty = off. |\r\n| `profile` | `\"\"` | Rigor preset: `minimal` / `standard` / `strict`. |\r\n| `type` | `\"\"` | Task type: `trivial`…`ops` — relaxes or tightens the required checks. |\r\n| `coverage-command` | `\"\"` | Command that prints a coverage percentage. Empty = off. |\r\n| `coverage-min` | `\"0\"` | Minimum coverage percent — fail below it. |\r\n| `secrets-scan` | `\"true\"` | Scan added diff lines for credential shapes (set `false` to disable). |\r\n| `size-max-lines` | `\"\"` | Warn/fail when the PR adds more lines than this. Empty = off. |\r\n| `size-required` | `\"false\"` | `true` makes SIZE a hard gate (else advisory). |\r\n| `comment-pr` | `\"false\"` | Post the report as a PR comment (needs `github-token`). |\r\n| `github-token` | `\"\"` | Token for the PR comment — pass `${{ secrets.GITHUB_TOKEN }}`. |\r\n| `command-timeout` | `\"1800\"` | Seconds before a test/lint/coverage command is killed. |\r\n\r\n**Outputs:** `result` (`pass` / `fail` / `bypassed`) and `failed-checks` (comma-separated).\r\n\r\nBooleans accept `true/1/yes/on`. Globs: `**` means \"anything under here\" (e.g. `src/**`); a\r\nslash-free pattern like `*.py` also matches the file name anywhere. The toggles `require-plan`,\r\n`require-docs`, `lint-required`, `scan-test-output` **inherit** from `type` then `profile` when left\r\nempty; an explicit value always wins.\r\n\r\n---\r\n\r\n## Bypass (for genuine hotfixes)\r\n\r\nSometimes you must merge *now*. Put the bypass token in your latest commit message and the gate\r\npasses — but **loudly**: a warning annotation, a line in the step summary, and `result=bypassed`\r\non the output. Nothing is hidden.\r\n\r\n```\r\n[kronos skip] emergency: revert bad deploy\r\n```\r\n\r\nThe token is `[kronos skip]` by default (`bypass-token`); the whole mechanism can be turned off with\r\n`allow-bypass: \"false\"`.\r\n\r\n---\r\n\r\n## Full-discipline mode (profiles, types, WORKFLOW)\r\n\r\nKRONOS CI can enforce the **whole development process**, not just tests — making it a superset of the\r\n[KRONOS](https://github.com/dzylab/kronos) gates, re-checked on the pull request.\r\n\r\n- **Profiles** — one knob for rigor: `profile: minimal | standard | strict`. `strict` turns on\r\n  `scan-test-output`, `lint-required`, `require-plan`, and `require-docs` at once.\r\n- **Task types** — `type: trivial | micro | medium | large | ops` (or read from your `WORKFLOW.md`)\r\n  scales the bar: `trivial`/`micro` relax PLAN/DOCS; `large`/`ops` require them.\r\n- **WORKFLOW verification** — point `workflow-file: WORKFLOW.md` at a committed process record and\r\n  KRONOS CI checks that every stage marked `[x]` is backed by its real artifact (a plan exists, the\r\n  Test log is filled, docs were updated). A stage ticked without its artifact — or left open — fails\r\n  the gate. This is the KRONOS guarantee, enforced in CI.\r\n\r\n```yaml\r\n- uses: dzylab/kronos-ci@v0.6.0\r\n  with:\r\n    test-command: \"pytest -q\"\r\n    profile: \"strict\"\r\n    workflow-file: \"WORKFLOW.md\"\r\n```\r\n\r\n---\r\n\r\n## The DOCS check \u0026 shallow clones\r\n\r\nThe DOCS check needs the git history to compute the diff. `actions/checkout` defaults to a shallow\r\nclone, so set `fetch-depth: 0` (as the example does). If KRONOS CI still can't determine the changed\r\nfiles, the DOCS check **SKIPS** with a hint — it never produces a false failure.\r\n\r\n---\r\n\r\n## Use it anywhere — any editor, any CI\r\n\r\nKRONOS CI is **not tied to Claude Code** (that's [KRONOS](https://github.com/dzylab/kronos)). It lives\r\nat the **git layer**, below the AI layer, so it works no matter who or what wrote the code — Cursor,\r\nWindsurf, VS Code + Copilot, Aider, a local LLM, or a human by hand.\r\n\r\n**1. One-off, from any shell or AI tool:**\r\n```bash\r\nINPUT_TEST_COMMAND=\"pytest -q\" python kronos_ci.py verify\r\npython kronos_ci.py --self-test    # internal tests\r\npython kronos_ci.py --version\r\n```\r\n\r\n**2. As a local git hook (Cursor / Windsurf / VS Code / terminal).** Install once and it runs on every\r\npush — in *any* editor, because it fires on `git`, not on the IDE:\r\n```bash\r\ngit clone https://github.com/dzylab/kronos-ci\r\ncd your-project\r\n/path/to/kronos-ci/install.sh                                  # pre-push hook (or: install.sh pre-commit)\r\ncp /path/to/kronos-ci/.kronos-ci.env.example .kronos-ci.env    # then set your test-command\r\n```\r\n\r\n**3. On GitHub** — use the Action (the [60-second setup](#60-second-setup) above).\r\n\r\n**4. On any other CI** (GitLab, Bitbucket, Jenkins, …) — just call the CLI with `INPUT_*` env vars; a\r\nnon-zero exit fails the job. **Zero dependencies** (Python 3.8+ stdlib and git only).\r\n\r\n\u003e It is a git-level gate, **not an in-editor real-time plugin** — it checks at commit / push / PR time,\r\n\u003e not as you type.\r\n\r\n---\r\n\r\n## Integrations: PR comment \u0026 machine-readable JSON\r\n\r\n**PR comment (opt-in).** Post the report right onto the pull request:\r\n\r\n```yaml\r\n- uses: dzylab/kronos-ci@v0.6.0\r\n  with:\r\n    test-command: \"pytest -q\"\r\n    comment-pr: \"true\"\r\n    github-token: ${{ secrets.GITHUB_TOKEN }}\r\n```\r\n\r\nIt is strictly **fail-safe** — if the comment cannot be posted (no token, network), you get a warning,\r\nnever a failed gate.\r\n\r\n**JSON contract.** `kronos_ci.py verify --json` makes the **last stdout line** a single JSON object —\r\n`{version, result, failed, checks:[{name,status,note}]}` — so any tool, script, or AI agent can consume\r\nthe verdict programmatically. This is the stable machine interface for building on top of KRONOS CI.\r\n\r\n---\r\n\r\n## Philosophy\r\n\r\nLLM agents — and people — are optimistic. They write \"tests pass\" and move on. KRONOS CI removes\r\nthe trust: it runs the tests in CI and reports the truth. It is the CI-native expression of one\r\nidea: **completion is evidence, not a declaration.**\r\n\r\nIt is deliberately small and config-driven — turn on only the checks you want, with graceful\r\ndegradation. See **[THREAT_MODEL.md](THREAT_MODEL.md)** for exactly what it does and does not protect\r\nagainst, and **[PRINCIPLES.md](PRINCIPLES.md)** for the design principles a clean change should follow —\r\nguidance for the author, with the mechanical slice (complexity, length, nesting) enforced via your linter.\r\n\r\n## KRONOS vs KRONOS CI — which one?\r\n\r\nBoth share one idea — *verify artifacts, not declarations* — at two different layers. They are\r\n**complementary, not competitors.**\r\n\r\n| | **KRONOS** | **KRONOS CI** |\r\n|---|---|---|\r\n| Form | a local `git commit` hook + slash-commands | a GitHub Action + CLI + a local git hook |\r\n| When | in-flow, as the AI codes — blocks the **commit** | post-hoc — blocks the **merge** (or the push, via the local hook) |\r\n| Where | your machine (Claude Code only) | GitHub runners, any CI, or any editor via the local hook |\r\n| Who | you, coding with Claude Code | any contributor, any tool, or a human |\r\n| Tests | trusts a green test log | **runs the tests itself** (plus coverage) |\r\n| Scope | rich process discipline: 5 stages, task types, doc routing, watchdog, standards | ten focused checks + full-discipline mode (profiles, types, WORKFLOW verification) + design-principles guidance |\r\n| Source of truth | a local `WORKFLOW.md` | the pull request diff (and a committed `WORKFLOW.md`, if enabled) |\r\n\r\n- **Use KRONOS** to keep an AI coding session disciplined on your machine, while you code.\r\n- **Use KRONOS CI** to guard the shared branch for *everyone* — even contributors who never open\r\n  Claude Code.\r\n- **Best together:** KRONOS locally + KRONOS CI on the repo. One philosophy, two layers.\r\n\r\nKRONOS (the Claude Code engine): [github.com/dzylab/kronos](https://github.com/dzylab/kronos).\r\n\r\n---\r\n\r\n## What it is NOT\r\n\r\n- **Not a security boundary.** It is a *discipline gate* against honest-but-optimistic mistakes,\r\n  not a defense against a hostile actor (who controls the workflow file).\r\n- **Not a test framework, linter, or quality scorer.** It orchestrates the tools you already use.\r\n- **Not a replacement for code review.**\r\n\r\n## License\r\n\r\nGPL-3.0 — see [LICENSE](LICENSE). Author: **dzylab** ·\r\nsibling project: [github.com/dzylab/kronos](https://github.com/dzylab/kronos).\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdzylab%2Fkronos-ci","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdzylab%2Fkronos-ci","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdzylab%2Fkronos-ci/lists"}