{"id":51339603,"url":"https://github.com/async/claims","last_synced_at":"2026-07-02T06:04:29.080Z","repository":{"id":364831787,"uuid":"1268899470","full_name":"async/claims","owner":"async","description":"Deterministic documentation-claim coverage checks for tests and AI-assisted release loops.","archived":false,"fork":false,"pushed_at":"2026-06-14T16:43:01.000Z","size":46,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-14T18:21:38.334Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://async.github.io/claims/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/async.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"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-14T04:15:25.000Z","updated_at":"2026-06-14T16:43:05.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/async/claims","commit_stats":null,"previous_names":["async/claims"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/async/claims","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/async%2Fclaims","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/async%2Fclaims/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/async%2Fclaims/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/async%2Fclaims/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/async","download_url":"https://codeload.github.com/async/claims/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/async%2Fclaims/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35034995,"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-07-02T02:00:06.368Z","response_time":173,"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":[],"created_at":"2026-07-02T06:04:28.340Z","updated_at":"2026-07-02T06:04:29.067Z","avatar_url":"https://github.com/async.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @async/claims\n\n`@async/claims` is a deterministic claims engine for documentation promises. It checks that documented promises stay anchored to source text and mapped to real tests. It does not call models or edit files during `check`.\n\nA clean registry passes only when every registered anchor exists in its source file, every claim id is mapped in `claims.coverage.json`, every referenced test title exists in the configured test files, and every `PROMISE: ` test title is mapped.\n\n`async-claims check` reports stale anchors, missing claim coverage, unknown coverage claim ids, missing referenced tests, duplicate claim ids, and unmapped promise tests with stable failure codes.\n\nThe checker can read custom test files with a configurable regular expression whose first capture group is the test title.\n\n`async-claims check --format json --output claims-report.json --no-fail` writes a machine-readable report and exits zero for claim failures.\n\nInvalid configuration is a usage error and exits with code 2.\n\n`async-claims init` creates starter config, claims, and coverage files, and refuses to overwrite them unless `--force` is passed.\n\nThe package has no runtime dependency on `@async/pipeline`; pipeline examples use it only to orchestrate commands and propose reviewable patches.\n\nThe pipeline helper `claims()` builds the standard flat task map without importing `@async/pipeline` from `@async/claims`.\n\nThe primary task-group helper `claimsTasks()` returns a nested task group for pipeline task-groups syntax: `tasks: { claims: claimsTasks() }`.\n\nThe helpers attach non-enumerable async-pipeline declaration metadata with `Symbol.for(\"@async/pipeline.declaration\")`, so a host pipeline can recognize the task section without `@async/claims` importing `@async/pipeline`.\n\n## Install\n\n```sh\npnpm add -D @async/claims\n```\n\nThe package is ESM TypeScript, requires Node `\u003e=24`, and ships the `async-claims` binary.\n\n## Quickstart\n\nCreate a claims registry:\n\n```json\n{\n  \"$schema\": \"https://async.dev/schemas/claims.schema.json\",\n  \"claims\": [\n    {\n      \"id\": \"readme.cache-inputs\",\n      \"source\": \"README.md\",\n      \"anchor\": \"Cache behavior is explicit through declared inputs.\"\n    }\n  ]\n}\n```\n\nMap claim ids to tests in the coverage registry:\n\n```json\n{\n  \"$schema\": \"https://async.dev/schemas/claims.coverage.schema.json\",\n  \"coverage\": [\n    {\n      \"claimId\": \"readme.cache-inputs\",\n      \"tests\": [\n        \"PROMISE: cache inputs isolate invalidation\"\n      ]\n    }\n  ]\n}\n```\n\nWrite a Node test with a mapped promise title:\n\n```js\nimport assert from \"node:assert/strict\";\nimport test from \"node:test\";\n\ntest(\"PROMISE: cache inputs isolate invalidation\", () =\u003e {\n  assert.equal(true, true);\n});\n```\n\nRun the check:\n\n```sh\nasync-claims check\n```\n\nBy default the checker detects `tests/` or `test/`, reads `claims.json` and `claims.coverage.json` from that folder, scans `**/*.test.js` under the same folder, extracts Node test titles from `test(\"title\", ...)`, and treats titles beginning with `PROMISE: ` as promises that must be registered.\n\nIn this repository, use the generated pipeline-backed package script:\n\n```sh\npnpm run pipeline:task:claims\n```\n\n## Codex Getting-Started Prompts\n\nUse these prompts from the target repository root. Start with the deterministic setup prompt, then add the repair loop only after the claims check passes.\n\nInitial setup prompt:\n\n```text\nSet up @async/claims in this repository as a deterministic release gate.\n\nRequirements:\n- Inspect README.md, docs/**/*.md, AGENTS.md, CHANGELOG.md, package.json, and the existing test folder before editing.\n- Install @async/claims as a dev dependency if it is missing.\n- Run async-claims init or create the equivalent files.\n- Use the detected test folder. If both tests/ and test/ exist and neither already contains claims files, ask before choosing.\n- Put doc anchors only in \u003ctest-folder\u003e/claims.json.\n- Put claim-to-test mappings only in \u003ctest-folder\u003e/claims.coverage.json.\n- Keep each claim anchor exact, stable, and testable.\n- Every mapped test title must exist in the configured test files.\n- Add or rename tests with the PROMISE: prefix only when the repository already has a real test for that behavior, or create the missing test.\n- Do not add agent repair tasks yet.\n- Verify with async-claims check or the repository's pipeline claims task.\n```\n\nPipeline repair-loop prompt:\n\n```text\nAdd the optional @async/claims repair loop using @async/pipeline.\n\nRequirements:\n- Keep async-claims check as the release authority.\n- Import claimsTasks and claimsSuggestTask from @async/claims/pipeline.\n- Mount the helper as tasks: { claims: claimsTasks(...) }.\n- Do not pass task or sh into claimsTasks.\n- Add a repair.suggest subtask with claimsSuggestTask.\n- Make repair.suggest depend on the explicit task id claims.repair.context.\n- Let the root pipeline own the agents block and default ASYNC_AGENT to codex.\n- Do not expose tests, test titles, claims.coverage.json, or coverage mappings to the repair agent.\n- Keep the visible repair stages as claims.repair.context, claims.repair.suggest, and claims.repair.patch.\n- Use the default repair filenames unless the repo has a reason to override namedFiles in one place.\n- Run the pipeline sync check, the claims task, and the repair-context task before calling the setup complete.\n```\n\n## Full Loop With Pipeline\n\nFor projects using `@async/pipeline`, import the claims workflow as a task group:\n\n```ts\nimport { claimsTasks } from \"@async/claims/pipeline\";\nimport { definePipeline, job } from \"@async/pipeline\";\n\nexport default definePipeline({\n  name: \"release\",\n  tasks: {\n    claims: claimsTasks()\n  },\n  jobs: {\n    verify: job({ target: [\"claims\"] }),\n    repairClaims: job({ target: [\"claims.repair.context\"] })\n  }\n});\n```\n\nUse the direct value rather than `{ ...claimsTasks() }`; the helper already returns the subgroup and keeps pipeline declaration metadata attached. Pipeline expands that group to these local task ids:\n\n```text\nclaims\nclaims.report\nclaims.repair.context\nclaims.repair.patch\n```\n\nInternally, the group root is the reserved `default` child from `claimsTasks()`. Pipeline publishes that child as `claims`, not `claims.default`.\n\nThe intended loop is:\n\n1. A human or planning agent updates docs, `tests/claims.json`, and `tests/claims.coverage.json` in the same plan. The claims registry names exact source anchors; the coverage registry maps claim ids to `PROMISE: ` tests.\n2. `claims` runs `async-claims check` and blocks release on mechanical drift.\n3. `claims.report` writes `claims-report.json` with `--no-fail` for release diagnostics.\n4. `claims.repair.context` writes a test-blind `claims-repair-context.json` for stale-anchor repair agents.\n5. An optional `claims.repair.suggest` agent writes `claims-anchor-updates.json`; it must not read tests or coverage mappings.\n6. `claims.repair.patch` turns accepted suggestions into `claims.patch`; review applies it or rejects it.\n7. If tests are missing, add a separate project task that proposes test patches only. Do not let an agent silently edit docs or claims just to make the checker pass.\n\nPut `tests/claims.json`, `tests/claims.coverage.json`, docs, and test globs in task inputs so pipeline reruns the claims workflow whenever the contract changes. `async-claims check` remains the release authority; human review owns whether a mapped test is sufficient.\n\nTo add an agent suggestion step while keeping filenames hidden behind claims-local defaults:\n\n```ts\nimport { claimsSuggestTask, claimsTasks } from \"@async/claims/pipeline\";\nimport { definePipeline, env } from \"@async/pipeline\";\n\nexport default definePipeline({\n  name: \"release\",\n  tasks: {\n    claims: claimsTasks({\n      tasks: {\n        \"repair.suggest\": claimsSuggestTask({\n          dependsOn: [\"claims.repair.context\"],\n          use: env.var(\"ASYNC_AGENT\", { default: \"codex\" })\n        })\n      }\n    })\n  }\n});\n```\n\nIf a repo wants different repair file paths, set them once:\n\n```ts\nclaimsTasks({\n  namedFiles: {\n    \"repair.context\": \".claims/repair-context.json\",\n    \"repair.suggestions\": \".claims/anchor-updates.json\",\n    \"repair.patch\": \".claims/repair.patch\"\n  }\n})\n```\n\nFor this repository, run the generated pipeline scripts:\n\n```sh\npnpm run pipeline:verify\npnpm run pipeline:task:claims.report\npnpm run pipeline:task:claims.repair.context\npnpm run pipeline:task:claims.repair.suggest\npnpm run pipeline:task:claims.repair.patch\npnpm run pipeline:sync:check\npnpm run pipeline:github:check\npnpm run release:check\n```\n\n## CLI\n\n```sh\nasync-claims check\nasync-claims check --format json --output claims-report.json --no-fail\nasync-claims repair-context --output claims-repair-context.json\nasync-claims patch-anchors --suggestions claims-anchor-updates.json --output claims.patch\nasync-claims init\n```\n\nExtra check options:\n\n```sh\nasync-claims check --registry tests/claims.json\nasync-claims check --coverage tests/claims.coverage.json\nasync-claims check --test-files \"tests/**/*.test.js,checks/**/*.js\"\nasync-claims check --test-title-regex \"^case: (.+)$\"\nasync-claims check --promise-prefix \"PROMISE: \"\n```\n\nExit codes:\n\n- `0`: all checks passed, or claim failures were reported with `--no-fail`.\n- `1`: claim failures were found.\n- `2`: configuration or registry shape was invalid.\n\n## Config\n\n`claims.config.json` is optional:\n\n```json\n{\n  \"$schema\": \"./schema/claims.config.schema.json\",\n  \"registry\": \"tests/claims.json\",\n  \"coverage\": \"tests/claims.coverage.json\",\n  \"testFiles\": [\"tests/**/*.test.js\"],\n  \"testTitlePattern\": \"^\\\\s*test\\\\(\\\\s*\\\"((?:[^\\\"\\\\\\\\]|\\\\\\\\.)*)\\\"\",\n  \"promisePrefix\": \"PROMISE: \"\n}\n```\n\n## Library\n\n```ts\nimport { checkClaims, loadConfig } from \"@async/claims\";\n\nconst config = await loadConfig();\nconst report = await checkClaims({\n  registry: config.registry,\n  coverage: config.coverage\n});\n\nif (!report.ok) {\n  for (const failure of report.failures) {\n    console.error(failure.code, failure.message);\n  }\n}\n```\n\nThe package exports `checkClaims(options): Promise\u003cClaimsReport\u003e`, `loadConfig(options): Promise\u003cClaimsConfig\u003e`, `Claim`, `ClaimCoverage`, `ClaimsConfig`, `ClaimsFailure`, and `ClaimsReport`.\n\n## Failure Codes\n\n- `invalid_config`: config or registry JSON is missing required shape.\n- `empty_registry`: the registry contains no valid claims.\n- `duplicate_id`: two claims share an id.\n- `missing_claim_coverage`: a claim has no entry in `claims.coverage.json`.\n- `unknown_coverage_claim`: a coverage entry references an unknown claim id.\n- `missing_source`: a claim source file does not exist.\n- `stale_anchor`: a claim anchor no longer appears verbatim in its source.\n- `missing_referenced_test`: a claim references a test title that was not discovered.\n- `unmapped_promise_test`: a discovered `PROMISE: ` test title is not registered by any claim.\n\n## Agent Boundary\n\nAgents only propose. The authoritative step is always:\n\n```sh\nasync-claims check\n```\n\nUse `repair-context` to give an agent test-blind stale-anchor context, then require a human to review any suggestions before running `patch-anchors`. The checker proves that the claim-to-test mapping exists; review still owns whether the test sufficiently exercises the promise.\n\nSee [docs/agent-contract.md](docs/agent-contract.md) and [docs/async-pipeline.md](docs/async-pipeline.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasync%2Fclaims","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fasync%2Fclaims","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasync%2Fclaims/lists"}