diff --git a/.docket/ledger.jsonl b/.docket/ledger.jsonl index af44bcc..709d9d6 100644 --- a/.docket/ledger.jsonl +++ b/.docket/ledger.jsonl @@ -216,3 +216,35 @@ {"schema":2,"kind":"claim","id":"c184","text":"Network-topology names have no precedent for arranging a decision record store, and most decision-record tools present records as a list.","state":"accepted","ts":"2026-10-06T09:15:19+00:00","author":"claude-code","session":"","branch":"main","scope":["docs/superpowers/specs/2026-09-13-ledger-topologies-design.md"],"rationale":"An October 2026 recheck found bus, star, ring and mesh used for no decision log, ADR collection or knowledge base; the closest writing calls an ADR graph a web of typed edges. MADR, adr-tools and Log4brains present by number or date. adr-explorer is the exception: it offers a force-directed supersedes/amends graph next to a timeline, and adr-tools can export Graphviz. The earlier rationale was wrong about the Obsidian zettelkasten-navigation plugin, which adds ID-hierarchy Mermaid graphs because link graphs make long chains hard to trace; it did not drop a graph view. A web search cannot prove the negative.","supports":[],"depends_on":[],"answers":[],"supersedes":["c101"],"evidence":[{"ref":"https://github.com/janmohammadi/adr-explorer/blob/main/README.md"},{"ref":"https://www.nilus.be/blog/architecture_decision_records_as_knowledge_graph_in_distributed_systems/"},{"ref":"https://community.obsidian.md/plugins/zettelkasten-navigation"},{"ref":"https://adr.github.io/adr-tooling/"}],"revisit":"","cost_if_wrong":"Docket ships an arrangement roster that no other tool found worth building, and users carry the setting.","pinned":false,"supersede_reason":"revise"} {"schema":2,"kind":"correction","id":"d106.1","corrects":"d106","fields":{"rationale":"d69 reached this answer from the ledger data and d102 reached it again from a literature survey, leaving two adopted records on one question. A survey of MADR, adr-tools, Log4brains and adr-explorer found most tools presenting records as a list, adr-explorer adding a supersession graph view, and the network names only on Ethernet pages."},"reason":"rationale repeated the Obsidian and every-tool-is-a-list findings that the October recheck overturned","ts":"2026-10-06T09:15:28+00:00","author":"claude-code","session":"","branch":"main"} {"schema":2,"kind":"review","id":"d106.r2","reviews":"d106","grounds":{"c101":"c184"},"note":"","ts":"2026-10-06T09:15:28+00:00","author":"claude-code","session":"","branch":"main"} +{"schema":2,"kind":"decision","id":"d185","text":"Schema 3 renumbers every ledger record per kind, retired records included, and each record keeps its schema-2 id in a field.","state":"adopted","ts":"2026-10-06T22:36:00+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/ledger.py","docket/migrate.py"],"rationale":"Only a full renumber removes the gaps already in the chains, and keeping the old id on each record lets the ledger itself trace old ids with no side file to lose.","supports":[],"depends_on":[],"answers":[],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"Every id cited outside the ledger changes, and every revision token agents hold goes stale.","pinned":false,"choice":"A schema 2 to 3 migration renumbers claims, decisions and questions each in file order: c1-c46, d1-d126 and q1-q12 on this ledger at 184 records. Every migrated record carries its schema-2 id in a field, which replaces the separate old-to-new map file the September design wrote to .docket/.","alternatives":["Forward only: keep existing ids and count new records per kind from each kind's current maximum.","Write the old-to-new map to a separate file under .docket/."],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d186","text":"The schema-3 migration rewrites the ledger ids that features cite, in features.jsonl and its archive, in the same pass.","state":"adopted","ts":"2026-10-06T22:36:00+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/features.py","docket/migrate.py"],"rationale":"Old ids still exist after the renumber, so an include left unrewritten silently points at a different record.","supports":[],"depends_on":[],"answers":[],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"","pinned":false,"choice":"Rewrite include and exclude ids in .docket/features.jsonl and the feature archive through the old-to-new mapping during the migration, and check each rewrite against the feature's stored record key, which does not contain the id.","alternatives":["Move features into the ledger as a fourth kind with its own f chain."],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d187","text":"Schema-2 ids stay history only after the renumber, and no command resolves them.","state":"adopted","ts":"2026-10-06T22:36:00+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/cli/**","docs/**"],"rationale":"Old and new ids share one format, so a bare string like c3 names different records before and after the renumber. A resolver can be added later if old citations turn out to matter; one that scripts already use is hard to remove.","supports":[],"depends_on":[],"answers":[],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"","pinned":false,"choice":"The old id lives in its record field and stays searchable, but show and every other id-taking command accept only schema-3 ids. The migration rewrites id citations in tracked docs through the field; commit messages and git history keep the old ids.","alternatives":["Resolve old ids through an explicit marker such as c3@v2 wherever an id is accepted."],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d188","text":"The schema-3 migration stays cheap in agent tokens and manual work on ledgers of hundreds of records.","state":"adopted","ts":"2026-10-06T22:36:00+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/migrate.py","docket/context.py","docket/cli/query.py"],"rationale":"A migration's lasting cost on a large ledger is what every later agent session reads, not the CPU time of the pass.","supports":[],"depends_on":[],"answers":[],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"","pinned":false,"choice":"The renumber is a deterministic pass with no model involved. The old-id field stays out of briefings and default list and show output, as the legacy audit block does, so it costs agents nothing per session.","alternatives":[],"decided_by":""} +{"schema":2,"kind":"question","id":"q189","text":"How does a schema-3 docket treat a schema-2 ledger in a project that has not migrated?","state":"open","ts":"2026-10-06T22:36:00+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/ledger.py","docket/cli/context_cmd.py","hooks/**"],"rationale":"Today a schema mismatch makes the session-start briefing print to stderr and exit 1, so an unmigrated project silently loses its briefing once the plugin updates. Options: refuse until migrated and have the hook show the agent the migrate instruction; read schema 2 transparently and migrate on the first write; support both schemas indefinitely.","supports":[],"depends_on":[],"answers":[],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"","pinned":false} +{"schema":2,"kind":"decision","id":"d190","text":"A schema-3 docket refuses a schema-2 ledger until it is migrated, and the session hook shows the agent how to migrate.","state":"adopted","ts":"2026-10-07T06:22:15+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/ledger.py","docket/cli/context_cmd.py","hooks/**"],"rationale":"One allocation rule and one validation rule stay in the code, and each project pays the rewrite once in a commit of its own. Today the hook prints a schema error to stderr and exits 1, which the agent never sees.","supports":[],"depends_on":[],"answers":["q189"],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"Every unmigrated project gets a migrate instruction instead of a briefing until someone runs it, and a collaborator on 0.25.x cannot read a migrated ledger.","pinned":false,"choice":"Reading a schema-2 ledger raises an error naming docket migrate, as schema 1 does today. From the session-start hook, docket context prints that instruction as its briefing and exits 0, so the agent working in that project sees it and can run the migration.","alternatives":["Read schema 2 transparently and migrate on the first write.","Support both schemas indefinitely."],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d191","text":"The schema-3 migration reaches the merge driver, rebase, and named doc files, not only the ledger and features.","state":"adopted","ts":"2026-10-07T06:25:50+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/migrate.py","docket/merge_driver.py","docket/rebase.py"],"rationale":"Per-kind renumbering in file order is prefix-stable, so records two branches share get the same new id on both sides. Without the in-memory step a forgotten branch migration leaves conflict markers on every ledger line.","supports":[],"depends_on":[],"answers":[],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"","pinned":false,"choice":"docket migrate chains schema steps so a schema-1 ledger reaches 3 in one run. The merge driver and docket rebase migrate a schema-2 side in memory with the same per-kind renumber before matching, so a branch open across the migration merges with no manual step. docket migrate --rewrite FILE... rewrites id citations in the named files, matching only ids recorded as old ids.","alternatives":["Migrate only the ledger and features; each open branch runs docket migrate before it merges, and docs are fixed by hand.","Scan every tracked file for id citations automatically."],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d192","text":"Each migrated record keeps its schema-2 id in a migrated_from audit field, and the renumber rewrites id mentions in record prose as well as in relations.","state":"adopted","ts":"2026-10-07T06:28:26+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/ledger.py","docket/migrate.py","docket/cli/query.py"],"rationale":"39 of 184 records mention ids in prose, 104 mentions in all, and 8 of those strings already name no record because the pre-0.8 renumber left prose alone.","supports":[],"depends_on":[],"answers":[],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"","pinned":false,"choice":"migrated_from joins AUDIT_FIELDS beside legacy, so briefings never render it and list and show JSON hide it without --legacy; corrections and reviews omit it. The renumber rewrites relations, correction and review ids with their corrects, reviews and grounds fields, and legacy.relation_map mapped_* fields; legacy.source_id and legacy.raw stay. Prose mentions in text, choice, alternatives, rationale, cost_if_wrong, revisit and correction fields are rewritten at word boundaries when they match a current id, and feature keys are recomputed in the same pass.","alternatives":["Leave id mentions in record prose untouched."],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d193","text":"docket migrate chains schema steps, renumbers in one file-order pass, and moves features with the ledger under a features schema bump.","state":"adopted","ts":"2026-10-07T06:56:56+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/migrate.py","docket/features.py","docket/feature_archive.py","docket/cli/admin.py"],"rationale":"Renaming the ledger last and skipping features already at schema 2 makes a rerun after a crash map nothing twice; a per-record report on a large ledger would cost an agent hundreds of lines.","supports":[],"depends_on":[],"answers":[],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"","pinned":false,"choice":"STEPS runs from the detected schema to 3; the classification map and --map/--emit-map apply only to the 1-to-2 step; one backup named after the starting schema. The renumber builds the map and rewrites ids and prose in one pass, each mention replaced in a single lookup. features.jsonl and every archive file get cited ids and keys rewritten and move from features schema 1 to 2. All temp files are written first, features renamed next, the ledger last. --rewrite FILE... works only with the migration. Output is a summary unless --dry-run.","alternatives":[],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d194","text":"record_key ignores id-shaped tokens in a record's headline, so feature keys survive a renumber.","state":"adopted","ts":"2026-10-07T06:56:56+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/ledger.py"],"rationale":"Only c4, d17 and q146 mention an id in their headline, so masking changes no other key, and the features' existing key-based rebinding then covers the migration.","supports":[],"depends_on":[],"answers":[],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"Feature events written before the migration that cite one of those three records no longer rebind by key, and docket check reports them.","pinned":false,"choice":"record_key masks [cdq]N tokens in the as-written text before hashing; kind, ts, author and session stay in the key.","alternatives":[],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d195","text":"The merge driver and docket rebase upgrade a schema-2 side in memory, and merges rewrite prose mentions through the same translation as the migration.","state":"adopted","ts":"2026-10-07T06:58:00+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/merge_driver.py","docket/rebase.py"],"rationale":"File-order renumbering gives shared records identical ids and migrated_from on both sides, so the existing record matching works unchanged; dropping migrated_from on merged-in records would make a second merge of one branch append duplicates.","supports":[],"depends_on":[],"answers":[],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"One old id can name two records, one per branch, and a machine whose PATH docket is 0.25.x leaves conflict markers instead of merging.","pinned":false,"choice":"Any schema-2 side is renumbered in memory before matching; when ours was schema 2 the driver writes the whole upgraded file plus the tail. Merged-in records keep migrated_from with their branch-local id. The prose rewrite lives in rebase._translated, and matching falls back to untranslated prose so records merged before this change still match. A schema-1 features side has its events bumped to features schema 2 with ids unchanged and rebinds through keys.","alternatives":["Leave merges translating relations only, with prose mentions stale as today."],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d196","text":"Schema 3 validates and allocates ids per kind, docket check compares per kind, and the session hook turns a schema-2 refusal into a migrate instruction.","state":"adopted","ts":"2026-10-07T07:02:42+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/ledger.py","docket/cli/admin.py","docket/cli/context_cmd.py","tests/golden/regenerate.py","scripts/rescope_ledger.py"],"rationale":"Merges now go through the merge driver, and validate_record still catches dangling and wrong-kind references, so losing cross-kind ordering in check costs little.","supports":[],"depends_on":[],"answers":[],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"docket check no longer detects ids out of order across kinds after a hand-resolved merge.","pinned":false,"choice":"_Prefix tracks a highest number per prefix letter and allocate_id counts within the kind; SCHEMA is 3 on record, correction and review lines, and schema 2 is refused with a migrate instruction. docket check's own ordering copy compares per kind. docket context in the session hook prints the migrate instruction on stdout and exits 0. tests/golden/regenerate.py moves to per-kind counters with fixtures regenerated in their own commit. scripts/rescope_ledger.py is deleted. Release 0.26.0.","alternatives":[],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d197","text":"Schema-2 ids stay history only after the renumber, and no command resolves them.","state":"adopted","ts":"2026-10-07T07:09:00+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/cli/**","docs/**"],"rationale":"Nearly every id in this repository's docs is an example such as docket show d2 or (c1 AND c2) OR c3, and rewriting through the map would scramble them.","supports":[],"depends_on":[],"answers":[],"supersedes":["d187"],"evidence":[],"revisit":"","cost_if_wrong":"","pinned":false,"supersede_reason":"revise","choice":"The old id lives in its record's migrated_from field and stays searchable, but show and every other id-taking command accept only schema-3 ids. Citations outside the ledger change only in files passed to docket migrate --rewrite; commit messages, git history and the changelog keep the old ids. This repository's docs use illustrative ids, so its migration runs without --rewrite and the docs change by hand only where they describe the numbering.","alternatives":["Resolve old ids through an explicit marker such as c3@v2 wherever an id is accepted."],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d198","text":"Each migrated record keeps its schema-2 id in a migrated_from audit field, and the renumber rewrites id mentions in record prose as well as in relations.","state":"adopted","ts":"2026-10-07T07:09:00+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/ledger.py","docket/migrate.py","docket/cli/query.py"],"rationale":"The validator no longer checks legacy against relations, and its mapped_* lists record the ids the schema-1 migration assigned, which migrated_from now bridges to schema 3.","supports":[],"depends_on":[],"answers":[],"supersedes":["d192"],"evidence":[],"revisit":"","cost_if_wrong":"","pinned":false,"supersede_reason":"revise","choice":"migrated_from joins AUDIT_FIELDS beside legacy, so briefings never render it and list and show JSON hide it without --legacy; corrections and reviews omit it. The renumber rewrites relations and correction and review ids with their corrects, reviews and grounds fields. legacy stays untouched, mapped_* lists included. Prose mentions in text, choice, alternatives, rationale, cost_if_wrong, revisit and correction fields are rewritten at word boundaries when they match a current id, and feature keys are recomputed in the same pass.","alternatives":["Leave id mentions in record prose untouched."],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d199","text":"docket migrate chains schema steps and rewrites named files, and each branch migrates itself before it merges.","state":"adopted","ts":"2026-10-07T08:14:42+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/migrate.py","docket/merge_driver.py","docket/rebase.py"],"rationale":"Review traced the in-memory upgrade through merges: records a pre-migration merge renumbered get appended twice, the features store has no path across schemas, and a merge of two unmigrated branches silently writes schema 3 without the features migration or backup. File-order renumbering is deterministic, so two branches that migrate separately agree on every shared record.","supports":[],"depends_on":[],"answers":[],"supersedes":["d191"],"evidence":[],"revisit":"","cost_if_wrong":"A branch nobody has opened since the migration needs a manual docket migrate before it merges.","pinned":false,"supersede_reason":"revise","choice":"docket migrate chains schema steps so a schema-1 ledger reaches 3 in one run, and --rewrite FILE... rewrites id citations in the named files, matching only ids in the mapping. Nothing upgrades another branch's ledger: a branch open across the migration runs docket migrate itself, which the session hook prompts any agent that opens it to do.","alternatives":["The merge driver and docket rebase upgrade a schema-2 side in memory so an open branch merges with no manual step."],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d200","text":"The merge driver and docket rebase merge only ledgers and feature stores at the same schema.","state":"adopted","ts":"2026-10-07T08:14:42+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/merge_driver.py","docket/rebase.py","docket/cli/admin.py"],"rationale":"Only BASE needs reading across schemas once each branch migrates itself, and BASE is never written, so no merged output depends on an in-memory upgrade.","supports":[],"depends_on":[],"answers":[],"supersedes":["d195"],"evidence":[],"revisit":"","cost_if_wrong":"A forced hand merge across schemas gets no help from the driver.","pinned":false,"supersede_reason":"reverse","choice":"OURS and THEIRS must both be at the current schema; otherwise the driver leaves OURS untouched, exits 1 and names docket migrate, and rebase refuses the same way. A BASE one schema behind is upgraded in memory for matching only, because two branches that migrated separately share a pre-migration merge base; it is never written.","alternatives":["Upgrade any schema-2 side in memory and write the merged result at schema 3."],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d201","text":"Merge matching ignores migrated_from and id tokens in prose.","state":"adopted","ts":"2026-10-07T08:14:42+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/rebase.py","docket/merge_driver.py"],"rationale":"A record a pre-migration merge renumbered carries a different migrated_from and differently rewritten prose on each branch after they migrate separately, so the old key appends it twice.","supports":[],"depends_on":[],"answers":[],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"","pinned":false,"choice":"rebase._key drops id and migrated_from and masks [cdq]N tokens in every prose field before comparing; the feature merge key likewise ignores schema, the ledger-id fields and keys. Merges still rewrite prose in the records they append.","alternatives":["Match on every field but id, and fall back to untranslated prose for records merged before prose was translated."],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d202","text":"docket migrate renumbers in one file-order pass, moves features with the ledger, and survives a crash at any point.","state":"adopted","ts":"2026-10-07T08:14:42+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/migrate.py","docket/features.py","docket/feature_archive.py","docket/cli/admin.py"],"rationale":"Review found the two-rename ledger step can leave no ledger at all, reruns refused on leftover temps and backups, feature writes lost to the rename, and --rewrite files mapped twice on a rerun.","supports":[],"depends_on":[],"answers":[],"supersedes":["d193"],"evidence":[],"revisit":"","cost_if_wrong":"A crash mid-migration leaves a state the next run cannot finish without hand repair.","pinned":false,"supersede_reason":"revise","choice":"One renumber pass builds the map and rewrites ids and prose. features.jsonl and archive files move from features schema 1 to 2 with ids and keys remapped. The ledger lock is taken, then the features lock. Temps for features, --rewrite files and the ledger are written and fsynced first; features and --rewrite files are replaced next; the original ledger is hard-linked to ledger.jsonl.schemaN and the temp replaces the ledger in one os.replace. A rerun overwrites stale temps, accepts a backup identical to the current ledger, skips features already at schema 2, and refuses --rewrite files that are untracked or have uncommitted changes. On a schema-3 ledger, migrate remaps any features file still at schema 1 through migrated_from. Output is a summary unless --dry-run.","alternatives":[],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d203","text":"Each migrated record keeps its schema-2 id in a migrated_from audit field, and the renumber rewrites id mentions in record prose as well as in relations.","state":"adopted","ts":"2026-10-07T08:14:42+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/rebase.py","docket/migrate.py","docket/where.py","docket/cli/query.py"],"rationale":"Ten of the sixteen tokens that name no record today sit in schema-1 lines and are schema-1 ids that legacy.source_id resolves; after the renumber every unresolved token names a live, unrelated record, so the dry-run listing is how illustrative and foreign ids get caught before the real run.","supports":[],"depends_on":[],"answers":[],"supersedes":["d198"],"evidence":[],"revisit":"","cost_if_wrong":"","pinned":false,"supersede_reason":"revise","choice":"migrated_from joins AUDIT_FIELDS beside legacy and stays out of briefings and default JSON; corrections and reviews omit it, and was:ID matches it or legacy.source_id. The renumber refuses a duplicate old id or a citation of an id not yet mapped, rewrites relations, correction and review ids with corrects, reviews and grounds, and leaves legacy untouched. Prose in text, choice, alternatives, rationale, cost_if_wrong, revisit, a correction's fields and reason, and a review's note is rewritten at word boundaries; on a line carrying legacy, a token resolves through legacy.source_id first. --dry-run lists every prose rewrite and every unmapped token.","alternatives":["Leave id mentions in record prose untouched."],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d204","text":"Schema 3 validates and allocates ids per kind, docket check compares per kind, and the session hook turns a schema-2 refusal into a migrate instruction.","state":"adopted","ts":"2026-10-07T08:14:42+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/ledger.py","docket/cli/admin.py","docket/cli/context_cmd.py","tests/golden/regenerate.py"],"rationale":"Merges go through the merge driver, and validate_record still catches dangling and wrong-kind references, so losing cross-kind ordering in check costs little.","supports":[],"depends_on":[],"answers":[],"supersedes":["d196"],"evidence":[],"revisit":"","cost_if_wrong":"docket check no longer detects ids out of order across kinds after a hand-resolved merge.","pinned":false,"supersede_reason":"restate","choice":"_Prefix tracks a highest number per prefix letter and allocate_id takes that kind's maximum plus one; SCHEMA is 3 on record, correction and review lines, and older lines raise SchemaTooOld naming docket migrate. docket check compares per kind and prints the migrate instruction once on an old ledger. docket context catches SchemaTooOld at both ledger reads and prints the instruction through its normal output path, exit 0. tests/golden/regenerate.py moves to per-kind counters with fixtures regenerated in their own commit. Release 0.26.0.","alternatives":[],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d205","text":"The merge driver and docket rebase merge only ledgers and feature stores at the same schema, and a refused merge leaves conflict markers.","state":"adopted","ts":"2026-10-07T08:31:27+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/merge_driver.py","docket/rebase.py","docket/cli/admin.py"],"rationale":"An untouched OURS that someone runs git add on would drop THEIRS's records without a word; the markers keep the driver's existing failure rule.","supports":[],"depends_on":[],"answers":[],"supersedes":["d200"],"evidence":[],"revisit":"","cost_if_wrong":"A refused merge shows conflict markers on every line until it is aborted.","pinned":false,"supersede_reason":"revise","choice":"OURS and THEIRS must both be at the current schema; otherwise the driver names the side that is behind and says to run docket migrate, commit and merge again, writes the usual conflict markers, and exits 1, and rebase refuses with SchemaTooOld. A BASE one schema behind is upgraded in memory for matching only and never written.","alternatives":["Leave OURS byte-identical with no markers on a schema refusal."],"decided_by":"user"} +{"schema":2,"kind":"decision","id":"d206","text":"This repository's ledger migrates immediately before the 0.26.0 release, after its example-quoting records are reworded.","state":"adopted","ts":"2026-10-07T08:31:27+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":[".docket/ledger.jsonl","justfile"],"rationale":"just release runs the dev ./bin/docket check, which reads only schema 3, while the installed 0.25.1 hook reads only schema 2, so one short window where the installed hook fails is unavoidable.","supports":[],"depends_on":[],"answers":[],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"Sessions between the migrate commit and the install get an error instead of a briefing.","pinned":false,"choice":"Run ./bin/docket migrate --dry-run, reword records whose prose quotes example ids or other projects' ids with the installed docket, migrate and commit, run just release, then install 0.26.0 on PATH and in the plugin and restart. Nothing is recorded between the migrate commit and the install.","alternatives":["Edit the justfile so the release check tolerates a schema-2 ledger, and migrate after installing 0.26.0."],"decided_by":""} +{"schema":2,"kind":"decision","id":"d207","text":"A was: query includes retired records in docket list and docket export.","state":"adopted","ts":"2026-10-07T11:38:55+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/where.py","docket/cli/query.py","docket/cli/export.py"],"rationale":"Old ids in commits and notes often name decisions that were later superseded, and was: is the only way back to them after the renumber.","supports":[],"depends_on":[],"answers":[],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"A was: search shows retired rows a user did not expect.","pinned":false,"choice":"When a --where query has a non-negated was: term, list and export keep retired records as --superseded does; a query without was: still hides them.","alternatives":["Keep retired records hidden and put --superseded in the show hint and docs."],"decided_by":""} +{"schema":2,"kind":"decision","id":"d208","text":"The ledger.jsonl.schemaN backup is not committed, and a backup left by another branch's migration is removed by hand.","state":"adopted","ts":"2026-10-07T11:38:55+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/migrate.py","docket/cli/context_cmd.py","docs/ledger.md","docs/schemas.md"],"rationale":"A committed backup differs per branch and conflicts when two migrated branches merge; an uncommitted one survives a branch switch and must not be overwritten silently, because it is the only copy of that branch's original.","supports":[],"depends_on":[],"answers":[],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"Migrating a second branch in one worktree needs a manual delete.","pinned":false,"choice":"The migrate instruction and docs say to commit ledger.jsonl and the features files only. A differing backup stops docket migrate with a message to delete or move it and run again. init's gitignore is unchanged.","alternatives":["Commit the backup with the migration.","Add .docket/*.schema* to the gitignore init writes."],"decided_by":""} +{"schema":2,"kind":"decision","id":"d209","text":"docket migrate refuses to commit when the ledger changed after it was read.","state":"adopted","ts":"2026-10-07T11:38:55+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/migrate.py"],"rationale":"Reading happens before the lock, so a line an older docket appended in between would otherwise be dropped by the replace.","supports":[],"depends_on":[],"answers":[],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"A migration interrupted by a concurrent append has to be run again.","pinned":false,"choice":"migrate_in_place snapshots the ledger bytes before reading, and _commit compares them under the ledger and features locks before replacing anything, raising a rerun instruction if they differ.","alternatives":[],"decided_by":""} +{"schema":2,"kind":"decision","id":"d210","text":"On a ledger that starts at schema 1, docket migrate --rewrite maps files through schema-1 ids.","state":"adopted","ts":"2026-10-07T11:38:55+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/migrate.py"],"rationale":"A schema-1 project's files cite schema-1 ids, and the intermediate schema-2 ids never existed on disk.","supports":[],"depends_on":[],"answers":[],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"A file citing schema-2 ids in a schema-1 project is rewritten wrongly.","pinned":false,"choice":"The rewrite map for a schema-1 ledger is legacy.source_id to new id, built from the final records; result.mapping keeps the schema 2 to 3 mapping.","alternatives":["Refuse --rewrite on a schema-1 ledger."],"decided_by":""} +{"schema":2,"kind":"decision","id":"d211","text":"Projects fix prose false positives after migrating, not before.","state":"adopted","ts":"2026-10-07T11:38:55+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docs/schemas.md"],"rationale":"Once 0.26.0 is installed it refuses to write to a schema-2 ledger, so corrections cannot precede the migration except where an older docket is still installed, as in this repository.","supports":[],"depends_on":[],"answers":[],"supersedes":[],"evidence":[],"revisit":"","cost_if_wrong":"","pinned":false,"choice":"docs/schemas.md tells a project to note the dry run's wrong rewrites, run docket migrate, then fix each with docket correct (found by docket list --where was:OLD), restating a decision by supersession when the false positive is in its choice.","alternatives":[],"decided_by":""} +{"schema":2,"kind":"correction","id":"c138.1","corrects":"c138","fields":{"rationale":"About 22 of the 27 rest on a ground superseded by a restatement or refinement: docket d38 by d88, stoat's decision 25 by its decision 38, nimblefox's decision 10 by its decision 89. Three rest on c62, which was disputed and corrected by c105, the defeat the rule exists for. Two rest on unassessed claims. nimblefox's claim 90 explicitly records that its dependents survived the replacement of nimblefox's decision 69. Across 600 claims and decisions no record is rejected or revoked; grounds leave only by supersession or dispute."},"reason":"spell out ids from the stoat and nimblefox ledgers so the per-kind renumber does not rewrite them as this ledger's","ts":"2026-10-07T11:50:52+00:00","author":"claude-code","session":"","branch":"per-kind-ids"} +{"schema":2,"kind":"correction","id":"q139.1","corrects":"q139","fields":{"rationale":"Supersession records replacement, and the formal model only has withdrawal. Passing support to the replacement silently keeps dependents of a changed ground, as with nimblefox's decision 69 and its replacement, decision 97, where the substance changed. Withdrawing it retracts dependents of a mere restatement. Dispute is the one observed withdrawal."},"reason":"spell out nimblefox ids so the per-kind renumber does not rewrite them as this ledger's","ts":"2026-10-07T11:50:52+00:00","author":"claude-code","session":"","branch":"per-kind-ids"} +{"schema":2,"kind":"correction","id":"d197.1","corrects":"d197","fields":{"rationale":"Nearly every id in this repository's docs is an illustrative example inside a command or a supports expression, and rewriting through the map would scramble them.","alternatives":["Resolve old ids through an explicit marker, an old id followed by @v2, wherever an id is accepted."]},"reason":"drop example ids that the per-kind renumber would rewrite as real citations","ts":"2026-10-07T11:50:53+00:00","author":"claude-code","session":"","branch":"per-kind-ids"} +{"schema":2,"kind":"correction","id":"d187.1","corrects":"d187","fields":{"rationale":"Old and new ids share one format, so the same bare id names different records before and after the renumber. A resolver can be added later if old citations turn out to matter; one that scripts already use is hard to remove.","alternatives":["Resolve old ids through an explicit marker, an old id followed by @v2, wherever an id is accepted."]},"reason":"drop example ids that the per-kind renumber would rewrite as real citations","ts":"2026-10-07T11:50:53+00:00","author":"claude-code","session":"","branch":"per-kind-ids"} +{"schema":2,"kind":"decision","id":"d212","text":"Schema 3 renumbers every ledger record per kind, retired records included, and each record keeps its schema-2 id in a field.","state":"adopted","ts":"2026-10-07T11:51:30+00:00","author":"claude-code","session":"","branch":"per-kind-ids","scope":["docket/ledger.py","docket/migrate.py"],"rationale":"Only a full renumber removes the gaps already in the chains, and keeping the old id on each record lets the ledger itself trace old ids with no side file to lose.","supports":[],"depends_on":[],"answers":[],"supersedes":["d185"],"evidence":[],"revisit":"","cost_if_wrong":"Every id cited outside the ledger changes, and every revision token agents hold goes stale.","pinned":false,"supersede_reason":"restate","choice":"A schema 2 to 3 migration renumbers claims, decisions and questions each in file order, so each kind counts from 1: 46 claims, 126 decisions and 12 questions on this ledger at 184 records. Every migrated record carries its schema-2 id in a field, which replaces the separate old-to-new map file the September design wrote to .docket/.","alternatives":["Forward only: keep existing ids and count new records per kind from each kind's current maximum.","Write the old-to-new map to a separate file under .docket/."],"decided_by":"user"} diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f91005..648ed95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- **Breaking:** schema 3 numbers each kind on its own, so claims are `c1…`, decisions `d1…` and questions `q1…`. Every record in an existing ledger is renumbered once, retired records included, and keeps its schema 2 ID in `migrated_from`. Old IDs stay searchable and no command resolves them. Every collaborator must upgrade docket and the plugin before merging a migrated ledger, because 0.25.x cannot read schema 3 and its session hook reports an error. Each project runs `docket migrate` once and commits the result. +- Each branch migrates itself before it merges. The merge driver refuses a ledger or features side that is still at an older schema, names the branch to migrate, and leaves conflict markers; abort the merge, migrate that branch, commit, and merge again. +- A merge or `docket rebase` now rewrites `c`, `d` and `q` IDs mentioned in a record's prose along with its relations, and matching ignores those IDs so a record merged under a new number is not appended twice. +- `docket migrate` runs every step from the ledger's schema to the current one, so a schema 1 ledger reaches schema 3 in one run. It prints a summary by default and, with `--dry-run`, the per-record report, every prose field it would rewrite and every ID it would leave as written. It keeps the original at `ledger.jsonl.schemaN`, where N is the starting schema. `--map` and `--emit-map` apply to schema 1 only. +- The migration rewrites `.docket/features.jsonl` and `.docket/archive/features-*.jsonl` to the new IDs and moves their schema to 2. +- `docket check` compares ID order per kind, and on a ledger older than the running docket prints the migrate instruction once. +- The pre-edit hook asks before an edit to any `ledger.jsonl.schemaN` backup, not only `.schema1`. + +### Added + +- `docket migrate --rewrite FILE...` rewrites ID citations in the named files in the same run. Each file must be tracked by git and have no uncommitted changes. With `--dry-run` it lists the files and counts and writes nothing. It is refused on a ledger already at schema 3. +- `docket list --where was:ID` finds a record by the ID it had before a migration, and `docket show ID` names that command for an ID that no longer exists. +- `list --json` and `show --json` drop `migrated_from` along with `legacy` unless `--legacy` is passed. +- The session hook prints the migrate instruction on stdout, with exit 0, when the ledger is older than the running docket, so the agent sees it. Any other ledger error still prints on stderr with exit 1. + ## [0.25.1] - 2026-10-05 ### Fixed diff --git a/README.md b/README.md index f4841aa..fbffab8 100644 --- a/README.md +++ b/README.md @@ -176,3 +176,4 @@ records, reports what was omitted, and includes a command to retrieve more. **Upgrading from before 0.8?** The ledger format and commands changed. Follow the [migration guide](docs/ledger.md#migrating-a-schema-1-ledger) before using an existing ledger. +Moving from 0.25 or earlier to per-kind ids? See [Schema versions](docs/schemas.md). diff --git a/docket/cli/__init__.py b/docket/cli/__init__.py index ffb4c07..fd0ffd9 100644 --- a/docket/cli/__init__.py +++ b/docket/cli/__init__.py @@ -197,7 +197,7 @@ def main(argv: list[str] | None = None) -> int: help="with --json, keep only these fields, e.g. id,kind,state,text", ) ls.add_argument( - "--legacy", action="store_true", help="with --json, keep the schema 1 migration audit field" + "--legacy", action="store_true", help="with --json, keep the migration audit fields" ) ls.add_argument("--plain", action="store_true", help="force colour off") ls.add_argument("--pretty", action="store_true", help="force colour on, e.g. piping to less -R") @@ -225,7 +225,7 @@ def main(argv: list[str] | None = None) -> int: sh.add_argument("id") sh.add_argument("--json", action="store_true", help="print the entry as JSON") sh.add_argument( - "--legacy", action="store_true", help="with --json, keep the schema 1 migration audit field" + "--legacy", action="store_true", help="with --json, keep the migration audit fields" ) sh.add_argument("--at", default="", help="print the record as history stood at this record ID") sh.set_defaults(func=cmd_show) @@ -286,11 +286,22 @@ def main(argv: list[str] | None = None) -> int: md.add_argument("theirs") md.set_defaults(func=cmd_merge_driver) - mg = sub.add_parser("migrate", help="convert a legacy ledger to the current schema") + mg = sub.add_parser("migrate", help="convert a ledger to the current schema") source = mg.add_mutually_exclusive_group() source.add_argument("--map", help="classification map to apply instead of the derived one") source.add_argument("--emit-map", help="write the derived map to this path and stop") - mg.add_argument("--dry-run", action="store_true", help="report the conversion and stop") + mg.add_argument( + "--dry-run", + action="store_true", + help="print the per-record report, every prose change and unmapped id, and write nothing", + ) + mg.add_argument( + "--rewrite", + nargs="+", + default=[], + metavar="FILE", + help="also rewrite id citations in these tracked, clean files; only alongside a migration", + ) mg.set_defaults(func=cmd_migrate) it = sub.add_parser("init", help="move this project's ledger into the repository") diff --git a/docket/cli/admin.py b/docket/cli/admin.py index 50f66c5..a2c7fba 100644 --- a/docket/cli/admin.py +++ b/docket/cli/admin.py @@ -13,13 +13,16 @@ from pathlib import Path from docket import env, feature_archive, feature_project, features, merge_setup +from docket.cli.context_cmd import migrate_instruction from docket.ledger import ( ID_RE, LedgerError, + SchemaTooOld, _ledger_lock, _Prefix, append, rebind, + stale_keys, validate_record, ) @@ -38,7 +41,8 @@ def cmd_rebase(args: argparse.Namespace) -> int: theirs = env.read(other, strict=True) tail, mapping = renumber(mine, theirs) except (LedgerError, RebaseError, OSError) as exc: - print(f"docket: {exc}", file=sys.stderr) + # Ledger errors, SchemaTooOld among them, already carry the prefix. + print(f"docket: {str(exc).removeprefix('docket: ')}", file=sys.stderr) return 1 if not tail: print("docket: nothing to rebase; the histories already agree") @@ -68,9 +72,14 @@ def cmd_rebase(args: argparse.Namespace) -> int: return 0 +def _count(number: int, noun: str) -> str: + return f"{number} {noun}{'' if number == 1 else 's'}" + + def cmd_migrate(args: argparse.Namespace) -> int: """Convert this project's ledger to the current schema.""" from docket.migrate import ( + SCHEMA_LATEST, MigrationError, derive_mapping, detect_version, @@ -82,13 +91,19 @@ def cmd_migrate(args: argparse.Namespace) -> int: if not path.exists(): print(f"docket: no ledger at {path}") return 0 + version = None try: + version = detect_version(read_source(path)) if args.emit_map: - source = read_source(path) - if detect_version(source) == 2: - print("docket: already schema 2") + if version == SCHEMA_LATEST: + print(f"docket: already schema {SCHEMA_LATEST}") return 0 - mapping = derive_mapping(source) + if version != 1: + raise MigrationError( + f"--emit-map applies to a schema 1 ledger; this one is at schema {version}, " + "whose records are already typed" + ) + mapping = derive_mapping(read_source(path)) Path(args.emit_map).write_text( json.dumps(mapping, indent=2, sort_keys=True) + "\n", encoding="utf-8" ) @@ -97,32 +112,70 @@ def cmd_migrate(args: argparse.Namespace) -> int: f"{'y' if len(mapping) == 1 else 'ies'} to {args.emit_map}" ) return 0 - count, report, notes = migrate_in_place(path, mapping_path=args.map, dry_run=args.dry_run) + result = migrate_in_place( + path, mapping_path=args.map, dry_run=args.dry_run, rewrite=args.rewrite + ) except MigrationError as exc: print(f"docket: {exc}", file=sys.stderr) - print( - "docket: to classify records by hand, run 'docket migrate --emit-map FILE', " - "edit FILE, then 'docket migrate --map FILE'", - file=sys.stderr, - ) + if version == 1: + print( + "docket: to classify records by hand, run 'docket migrate --emit-map FILE', " + "edit FILE, then 'docket migrate --map FILE'", + file=sys.stderr, + ) return 2 except OSError as exc: print(f"docket: {exc}", file=sys.stderr) return 1 - if not count: - print("docket: already schema 2") + if not result.count: + # A current ledger whose features files were not. + extra = ( + f"; remapped {_count(result.features_events, 'features event')}" + if result.features_events + else "" + ) + print(f"docket: already schema {SCHEMA_LATEST}{extra}") return 0 - for note in notes: + for note in result.notes: print(f"docket: warning: {note}", file=sys.stderr) - for line in report: - print(line) - if args.dry_run: - print(f"docket: would convert {count} record{'' if count == 1 else 's'}") - return 0 + dry = args.dry_run + if dry: + for line in result.report: + print(line) + for change in result.prose_changes: + if change.after is None: + print(f" {change.line_id} {change.field}: unmapped {change.before}") + else: + print(f" {change.line_id} {change.field}: {change.before} -> {change.after}") + kinds = ", ".join( + _count(result.per_kind.get(kind, 0), kind) for kind in ("claim", "decision", "question") + ) print( - f"docket: converted {count} record{'' if count == 1 else 's'}; " - f"original kept at {path}.schema1" + f"docket: {'would migrate' if dry else 'migrated'} {_count(result.count, 'record')} " + f"from schema {version} to schema {SCHEMA_LATEST} ({kinds})" ) + rewritten = sum(1 for change in result.prose_changes if change.after is not None) + unmapped = len(result.prose_changes) - rewritten + done = "would rewrite" if dry else "rewrote" + parts = [_count(rewritten, "prose field")] + if result.features_events: + parts.append(_count(result.features_events, "features event")) + print(f"docket: {done} {' and '.join(parts)}") + if unmapped: + print(f"docket: left {_count(unmapped, 'unmapped id')} as written") + if result.rewritten: + total = sum(result.rewrite_counts.values()) + print( + f"docket: {done} {_count(total, 'id mention')} in " + f"{_count(len(result.rewritten), 'file')}" + ) + for name in result.rewritten: + if dry: + print(f" {name}: {_count(result.rewrite_counts[name], 'id')}") + else: + print(f" {name}") + if not dry: + print(f"docket: original kept at {path}.schema{version}") return 0 @@ -149,7 +202,7 @@ def cmd_check(args: argparse.Namespace) -> int: # already shed. prefix = _Prefix([]) seen: dict[str, int] = {} - highest = 0 + highest: dict[str, int] = {} records = 0 correction_lines = 0 review_lines = 0 @@ -170,6 +223,9 @@ def cmd_check(args: argparse.Namespace) -> int: # nothing a brief can attach, and the feature check reports it. try: checked = validate_record(record, prefix=prefix) + except SchemaTooOld as exc: + print(migrate_instruction(exc), end="") + return 1 except LedgerError as exc: faults.append(f"line {number}: {str(exc).removeprefix('docket: ')}") else: @@ -185,17 +241,22 @@ def cmd_check(args: argparse.Namespace) -> int: faults.append(f"line {number}: duplicate id {ident}, first seen on line {seen[ident]}") continue seen[ident] = number + letter = match.group(1) + past = highest.get(letter, 0) sequence = int(match.group(2)) - if sequence <= highest: - faults.append(f"line {number}: id {ident} does not increase past {highest}") + if sequence <= past: + faults.append(f"line {number}: id {ident} does not increase past {letter}{past}") continue - highest = sequence + highest[letter] = sequence # The ID checks alone let a hand-resolved merge pass: a record pointing # at a same-numbered record from the other branch has a target that # exists and has the right kind. validate_record is what catches a # dangling or wrong-kind reference. try: checked = validate_record(record, prefix=prefix) + except SchemaTooOld as exc: + print(migrate_instruction(exc), end="") + return 1 except LedgerError as exc: faults.append(f"line {number}: {str(exc).removeprefix('docket: ')}") else: @@ -249,6 +310,18 @@ def cmd_check(args: argparse.Namespace) -> int: f"renumbered ({', '.join(moved)}); run docket feature remap" ) failed = True + stale = ( + [] + if feature["state"] in features.TERMINAL_STATES + else stale_keys(feature[field], feature["keys"], good) + ) + if stale: + print( + f"{store}: {feature['id']} {field} names {', '.join(stale)}, " + "whose stored key matches no record; check which record was " + "meant and re-cite it with docket feature amend" + ) + failed = True for fault in feature_archive.faults(store): print(fault) diff --git a/docket/cli/context_cmd.py b/docket/cli/context_cmd.py index b3a8e4c..4f0571e 100644 --- a/docket/cli/context_cmd.py +++ b/docket/cli/context_cmd.py @@ -17,7 +17,7 @@ from docket.cli.autoscope import auto_scope_files from docket.context_model import positions from docket.env import read -from docket.ledger import LedgerError, project +from docket.ledger import SCHEMA, LedgerError, SchemaTooOld, project # Harnesses that want context as their own hook envelope instead of plain # text, keyed by the --for value. docs/installation.md is the source for @@ -123,6 +123,17 @@ def _feature_block(root, entries=None) -> str: return "" +def migrate_instruction(exc: SchemaTooOld) -> str: + command = ROOT / "bin" / "docket" + return ( + f"docket: this project's ledger is schema {exc.version} and this docket reads " + f"schema {SCHEMA}. Run `{command} migrate` to convert it. If any files cite " + "ledger ids, add `--rewrite FILE...` to rewrite them in the same run. " + "Then commit ledger.jsonl and the features files, but not the ledger.jsonl.schema* " + "backup.\n" + ) + + def cmd_context(args: argparse.Namespace) -> int: from docket.config import ConfigError from docket.config import load as load_settings @@ -146,6 +157,8 @@ def cmd_context(args: argparse.Namespace) -> int: try: raw = read(env.ledger_path()) + except SchemaTooOld as exc: + return _print_context(migrate_instruction(exc), args, line) except (LedgerError, OSError) as exc: print(str(exc), file=sys.stderr) return 1 @@ -198,10 +211,12 @@ def cmd_context(args: argparse.Namespace) -> int: command=str(ROOT / "bin" / "docket"), explain=args.explain, ) + except SchemaTooOld as exc: + return _print_context(migrate_instruction(exc), args, line) except (LedgerError, OSError) as exc: print(str(exc), file=sys.stderr) return 1 return _print_context(text, args, line) -__all__ = ["CONTEXT_ENVELOPES", "cmd_context", "update_line"] +__all__ = ["CONTEXT_ENVELOPES", "cmd_context", "migrate_instruction", "update_line"] diff --git a/docket/cli/graph.py b/docket/cli/graph.py index 6fa4494..c241879 100644 --- a/docket/cli/graph.py +++ b/docket/cli/graph.py @@ -332,10 +332,11 @@ def walk(eid: str, ancestor_last: list[bool]) -> None: def _find_or_alloc(columns: list[str | None], label: str) -> int: """A column labelled `label`, reusing the leftmost freed one if none - exists. The ledger's ids are monotonic and append-only, so processing - newest-first means every column we need has either already been opened by - a dependent, or never existed; there is no need for git's full graph - algorithm to find it.""" + exists. The ledger is append-only and a record only cites earlier lines, so + processing newest-first in file order means every column we need has either + already been opened by a dependent, or never existed; there is no need for + git's full graph algorithm to find it. File position carries this, not the + id: ids count per kind and say nothing about order across kinds.""" if label in columns: return columns.index(label) for i, c in enumerate(columns): diff --git a/docket/cli/query.py b/docket/cli/query.py index 0a4a884..bbe51d5 100644 --- a/docket/cli/query.py +++ b/docket/cli/query.py @@ -53,11 +53,11 @@ def _list_dim_tail(line: str, marker: str, use_color: bool) -> str: JSON_FIELDS = tuple(sorted(ledger.ALLOWED_FIELDS - ledger.AUDIT_FIELDS | _DERIVED_FIELDS)) -def _without_legacy(entry: dict, keep: bool) -> dict: - """Schema 1 migration audit blobs are about a tenth of a ledger's JSON and nothing reads them.""" - if keep or "legacy" not in entry: +def _without_audit(entry: dict, keep: bool) -> dict: + """Migration audit fields (legacy alone is about a tenth of a ledger's JSON) are read by nothing but --legacy.""" + if keep or ledger.AUDIT_FIELDS.isdisjoint(entry): return entry - return {k: v for k, v in entry.items() if k != "legacy"} + return {k: v for k, v in entry.items() if k not in ledger.AUDIT_FIELDS} def fields_arg(value: str) -> list[str]: @@ -93,7 +93,7 @@ def cmd_list(args: argparse.Namespace) -> int: print("docket: nothing recorded") return 0 if getattr(args, "json", False): - rows = [_without_legacy(e, args.legacy) for e in entries] + rows = [_without_audit(e, args.legacy) for e in entries] if args.fields: rows = [{k: e[k] for k in args.fields if k in e} for e in rows] print(json.dumps(rows, ensure_ascii=False, indent=2)) @@ -160,10 +160,18 @@ def cmd_show(args: argparse.Namespace) -> int: e = by_id.get(args.id) if not e: print(f"docket: no entry {args.id}", file=sys.stderr) + # A current id never reaches this branch, so an old id that is also a + # new id resolves above and stays silent. + if any(args.id in where.old_ids(item) for item in entries): + print( + f"docket: {args.id} was renumbered by a migration; " + f"find it with: docket list --where was:{args.id}", + file=sys.stderr, + ) return 1 if args.json: - print(json.dumps(_without_legacy(e, getattr(args, "legacy", False)), indent=2)) + print(json.dumps(_without_audit(e, getattr(args, "legacy", False)), indent=2)) return 0 def cite(i: str) -> str: diff --git a/docket/construct/accept.py b/docket/construct/accept.py index 6868a2c..ff662dd 100644 --- a/docket/construct/accept.py +++ b/docket/construct/accept.py @@ -30,8 +30,8 @@ def _question_shaped(proposals: list[dict]) -> list[str]: def _chronological(proposals: list[dict]) -> list[dict]: """Oldest document first. - The briefing scores recency from the numeric record id, never from `ts`, so - the order records enter the ledger is the only thing that makes a newer + The briefing scores recency from file position, never from `ts`, so the + order records enter the ledger is the only thing that makes a newer decision outrank an older one. A run that accepts in staging order leaves 887 records the walker cannot tell apart by age. diff --git a/docket/context.py b/docket/context.py index 90135b6..c7bc283 100644 --- a/docket/context.py +++ b/docket/context.py @@ -1,7 +1,7 @@ """Deterministic, character-bounded context for projected Docket history. The context renderer deliberately knows nothing about storage or CLI path -discovery. Its input is the projected schema 2 history produced by the ledger +discovery. Its input is the projected history produced by the ledger module, which keeps selection and rendering easy to exercise independently. The work splits by responsibility, each part in its own module: context_model diff --git a/docket/corrections.py b/docket/corrections.py index e087da8..ae2f079 100644 --- a/docket/corrections.py +++ b/docket/corrections.py @@ -55,7 +55,7 @@ def validate(record: dict[str, Any], prefix: Any) -> dict[str, Any]: Without a prefix only the line's own shape is checked, as validate_record does for a record. """ - from docket.ledger import SCHEMA, _error, validate_record + from docket.ledger import _error, _require_current, validate_record ident = record.get("id") if not isinstance(ident, str) or (parts := split_id(ident)) is None: @@ -63,8 +63,7 @@ def validate(record: dict[str, Any], prefix: Any) -> dict[str, Any]: unknown = sorted(set(record) - LINE_FIELDS) if unknown: raise _error(ident, f"unknown field(s): {', '.join(unknown)}") - if type(record.get("schema")) is not int or record["schema"] != SCHEMA: - raise _error("schema", f"expected schema {SCHEMA}, got {record.get('schema')!r}") + _require_current(record) for field in ("ts", "author", "session", "branch", "reason"): if not isinstance(record.get(field), str): raise _error(ident, f"{field} must be a string") diff --git a/docket/feature_archive.py b/docket/feature_archive.py index 7c787a4..a7486e8 100644 --- a/docket/feature_archive.py +++ b/docket/feature_archive.py @@ -41,10 +41,26 @@ def highest_archived_id(store: Path) -> int: """ highest = 0 - for event in archived_events(store): - match = ID_RE.fullmatch(str(event.get("id", ""))) - if match: - highest = max(highest, int(match.group(1))) + directory = archive_dir_for(store) + if not directory.is_dir(): + return 0 + # Raw, not through read(): an id is the same at every schema, and this runs + # before any migrate, from append and from the merge driver. A strict read + # would refuse every new feature until the archive was migrated. A line that + # is not valid is skipped here and reported by `docket check`. + for name in sorted(directory.glob("features-*.jsonl")): + try: + lines = name.read_text(encoding="utf-8").splitlines() + except (OSError, UnicodeError): + continue + for line in lines: + try: + value = json.loads(line) + except json.JSONDecodeError: + continue + match = ID_RE.fullmatch(str(value.get("id", ""))) if isinstance(value, dict) else None + if match: + highest = max(highest, int(match.group(1))) return highest diff --git a/docket/features.py b/docket/features.py index 725d86a..079a44d 100644 --- a/docket/features.py +++ b/docket/features.py @@ -13,12 +13,13 @@ import json import os import re +from collections.abc import Mapping from pathlib import Path from typing import Any -from docket.ledger import ledger_lock +from docket.ledger import ledger_lock, record_key -SCHEMA = 1 +SCHEMA = 2 EVENTS = ("start", "amend", "note", "done", "abandon") STATUSES = ("active", "paused", "review") TERMINAL_STATES = ("done", "abandoned") @@ -90,6 +91,10 @@ class FeatureError(ValueError): """A feature event that cannot be used as written.""" +class FeatureSchemaTooOld(FeatureError): + """A features event written before the per-kind id migration.""" + + def _error(where: str, message: str) -> FeatureError: return FeatureError(f"docket: {where}: {message}") @@ -131,6 +136,12 @@ def validate_event(record: Any) -> dict[str, Any]: **{key: copy.deepcopy(value) for key, value in DEFAULTS.items() if key != "schema"}, **record, } + if type(record.get("schema")) is int and record["schema"] == 1: + name = record.get("slug") if isinstance(record.get("slug"), str) else "event" + raise FeatureSchemaTooOld( + f"docket: {name}: feature events are schema 1; run `docket migrate` " + "to move them to schema 2" + ) if type(record.get("schema")) is not int or record["schema"] != SCHEMA: raise _error("schema", f"expected schema {SCHEMA}, got {record.get('schema')!r}") @@ -194,6 +205,33 @@ def validate_event(record: Any) -> dict[str, Any]: return record +def remap_events( + events: list[dict[str, Any]], mapping: Mapping[str, str], by_id: Mapping[str, dict[str, Any]] +) -> list[dict[str, Any]]: + """Schema-1 events with every cited ledger id passed through ``mapping``. + + ``by_id`` holds the projected records under their new ids; each stored key + is recomputed from the record its id now names, or kept when that record + is missing. An event already at schema 2 passes through untouched, which + is what stops a rerun after a crash from mapping an id twice. + """ + out = [] + for event in events: + if type(event.get("schema")) is not int or event["schema"] != 1: + out.append(event) + continue + moved = copy.deepcopy(event) + for field in LEDGER_REFS: + moved[field] = [mapping.get(ident, ident) for ident in moved.get(field, [])] + moved["keys"] = {} + for old, key in event.get("keys", {}).items(): + new = mapping.get(old, old) + moved["keys"][new] = record_key(by_id[new]) if new in by_id else key + moved["schema"] = SCHEMA + out.append(validate_event(moved)) + return out + + def next_id(events: list[dict[str, Any]], floor: int = 0) -> str: """Allocate the next sequence number, local to this file. @@ -242,7 +280,10 @@ def read(path: Path | str, lock: bool = True) -> list[dict[str, Any]]: try: events.append(validate_event(value)) except FeatureError as exc: - raise _error(f"line {line_number}", str(exc).removeprefix("docket: ")) from exc + # type(exc): a schema-1 line stays FeatureSchemaTooOld for callers. + raise type(exc)( + _error(f"line {line_number}", str(exc).removeprefix("docket: ")).args[0] + ) from exc return events @@ -293,10 +334,12 @@ def append(path: Path | str, record: dict[str, Any]) -> dict[str, Any]: "STATUSES", "TERMINAL_STATES", "FeatureError", + "FeatureSchemaTooOld", "append", "make_event", "next_id", "qualified", "read", + "remap_events", "validate_event", ] diff --git a/docket/ledger.py b/docket/ledger.py index 6fa4eaf..8fd4cb8 100644 --- a/docket/ledger.py +++ b/docket/ledger.py @@ -21,7 +21,7 @@ from docket import corrections, reviews, support -SCHEMA = 2 +SCHEMA = 3 KINDS = ("claim", "decision", "question") STATES = { "claim": ("unassessed", "accepted", "disputed", "rejected"), @@ -29,6 +29,7 @@ "question": ("open", "resolved"), } ID_RE = re.compile(r"([cdq])(0|[1-9][0-9]*)$") +ID_TOKEN = re.compile(r"\b([cdq])(0|[1-9][0-9]*)\b") COMMON_DEFAULTS: dict[str, Any] = { "scope": [], "rationale": "", @@ -45,7 +46,7 @@ {"schema", "kind", "id", "text", "state", "ts", "author", "session", "branch", *COMMON_DEFAULTS} ) DECISION_FIELDS = frozenset({"choice", "alternatives", "decided_by"}) -AUDIT_FIELDS = frozenset({"legacy"}) +AUDIT_FIELDS = frozenset({"legacy", "migrated_from"}) ALLOWED_FIELDS = COMMON_FIELDS | DECISION_FIELDS | AUDIT_FIELDS | {"supersede_reason"} _LINE_FIELDS = { **dict.fromkeys(KINDS, ALLOWED_FIELDS), @@ -58,10 +59,36 @@ class LedgerError(ValueError): """A human-actionable schema, reference, or storage error.""" +class SchemaTooOld(LedgerError): + """A line written under an older schema. ``docket migrate`` converts the file. + + ``version`` is the schema the line carries, 1 when it carries none. read() + and validate_entries() let it through unwrapped so a caller can tell it from + corruption and offer the migration. + """ + + def __init__(self, version: int) -> None: + self.version = version + super().__init__( + f"docket: schema: this ledger is schema {version}; run 'docket migrate' " + f"to convert it to schema {SCHEMA}" + ) + + def _error(where: str, message: str) -> LedgerError: return LedgerError(f"docket: {where}: {message}") +def _require_current(record: dict[str, Any]) -> None: + schema = record.get("schema") + if schema is None: + raise SchemaTooOld(1) + if type(schema) is not int or schema > SCHEMA: + raise _error("schema", f"expected schema {SCHEMA}, got {schema!r}") + if schema < SCHEMA: + raise SchemaTooOld(max(schema, 1)) + + def _is_string_list(value: Any) -> bool: return isinstance(value, list) and all(isinstance(item, str) and item for item in value) @@ -190,7 +217,7 @@ def make_record( ts: str | None = None, record_id: str | None = None, ) -> dict[str, Any]: - """Build an unnumbered or explicitly numbered schema 2 record.""" + """Build an unnumbered or explicitly numbered record at the current schema.""" if kind not in KINDS: raise _error("record", f"unknown kind {kind!r}; expected claim, decision, or question") if not isinstance(text, str) or not text.strip(): @@ -260,7 +287,7 @@ class _Prefix: def __init__(self, entries: list[dict[str, Any]]) -> None: self.by_id: dict[str, dict[str, Any]] = {} - self.max_number = 0 + self.max_number: dict[str, int] = {} self.retired: dict[str, str] = {} self.corrections: dict[str, int] = {} self.reviews: dict[str, int] = {} @@ -279,7 +306,7 @@ def add(self, entry: dict[str, Any]) -> None: return ident = entry["id"] self.by_id[ident] = entry - self.max_number = max(self.max_number, int(ident[1:])) + self.max_number[ident[0]] = max(self.max_number.get(ident[0], 0), int(ident[1:])) for target in entry["supersedes"]: self.retired[target] = ident @@ -303,6 +330,7 @@ def validate_record( raise _error("record", "each JSONL line must be an object") if any(not isinstance(key, str) for key in record): raise _error("record", "field names must be strings") + _require_current(record) if record.get("kind") == corrections.KIND: if prefix is not None and previous is not None: raise _error("record", "pass previous or prefix, not both") @@ -315,15 +343,9 @@ def validate_record( if prefix is None and previous is not None: prefix = _Prefix(previous) return reviews.validate(record, prefix) - if record.get("schema") in (None, 1): - raise _error( - "schema", "legacy format is unsupported; run 'docket migrate' to convert it to schema 2" - ) unknown_fields = sorted(set(record) - ALLOWED_FIELDS) if unknown_fields: raise _error("record", f"unknown field(s): {', '.join(unknown_fields)}") - if type(record.get("schema")) is not int or record.get("schema") != SCHEMA: - raise _error("schema", f"expected schema 2, got {record.get('schema')!r}") kind = record.get("kind") if kind not in KINDS: raise _error("record", f"kind must be one of {', '.join(KINDS)}") @@ -386,6 +408,10 @@ def validate_record( # migration assigned. if "legacy" in record and not isinstance(record["legacy"], dict): raise _error(record_id, "legacy must be an object") + if "migrated_from" in record: + origin = record["migrated_from"] + if not isinstance(origin, str) or not ID_RE.fullmatch(origin): + raise _error(record_id, "migrated_from must be a record id such as 'd12'") if kind == "question" and state != "open": raise _error( record_id, "questions have recorded state open; resolution is derived from answers" @@ -408,8 +434,8 @@ def validate_record( known = prefix.by_id if record_id in known: raise _error(record_id, "duplicate ID") - if number <= prefix.max_number: - raise _error(record_id, "global sequence must increase monotonically; gaps are allowed") + if number <= prefix.max_number.get(id_prefix, 0): + raise _error(record_id, "per-kind sequence must increase; gaps are allowed") for field in ("supports", "depends_on", "answers", "supersedes"): ids = ( [ref for group in supports for ref in group] @@ -443,6 +469,8 @@ def validate_entries(entries: Any) -> list[dict[str, Any]]: for index, entry in enumerate(entries, 1): try: record = validate_record(entry, prefix=prefix) + except SchemaTooOld: + raise except LedgerError as exc: raise _error(f"line {index}", str(exc).removeprefix("docket: ")) from exc validated.append(record) @@ -473,7 +501,10 @@ def _newer_than_us(value: Any) -> tuple[str, frozenset[str]] | None: Returns None for a line this version fully understands, or one too broken to tell, which validation then reports. """ - if not isinstance(value, dict) or value.get("schema") in (None, 1): + if not isinstance(value, dict): + return None + schema = value.get("schema") + if type(schema) is not int or schema < SCHEMA: return None kind = value.get("kind") if not isinstance(kind, str): @@ -544,6 +575,8 @@ def read(path: Path | str, lock: bool = True, strict: bool = False) -> list[dict value = {k: v for k, v in value.items() if k not in extra} try: record = validate_record(value, prefix=prefix, copy_result=False) + except SchemaTooOld: + raise except LedgerError as exc: raise _error(f"line {line_number}", str(exc).removeprefix("docket: ")) from exc entries.append(record) @@ -557,12 +590,13 @@ def read(path: Path | str, lock: bool = True, strict: bool = False) -> list[dict return entries -def next_id(entries: list[dict[str, Any]]) -> str: - """Allocate the next global sequence number, preserving mixed-kind IDs.""" +def next_id(entries: list[dict[str, Any]], kind: str) -> str: + """The next number for ``kind``; each kind counts on its own from 1.""" + letter = {"claim": "c", "decision": "d", "question": "q"}[kind] numbers = [] for entry in entries: match = ID_RE.fullmatch(str(entry.get("id", ""))) - if match: + if match and match.group(1) == letter: numbers.append(int(match.group(2))) return str(max(numbers, default=0) + 1) @@ -570,7 +604,7 @@ def next_id(entries: list[dict[str, Any]]) -> str: def allocate_id(entries: list[dict[str, Any]], kind: str) -> str: if kind not in KINDS: raise _error("record", f"unknown kind {kind!r}") - return {"claim": "c", "decision": "d", "question": "q"}[kind] + next_id(entries) + return {"claim": "c", "decision": "d", "question": "q"}[kind] + next_id(entries, kind) def retired_by(entries: list[dict[str, Any]]) -> dict[str, str]: @@ -730,9 +764,13 @@ def record_key(entry: dict[str, Any]) -> str: cited outside the ledger can come to name a different record. Text is the as-written text, from ``original`` once a correction has rewritten it in the projection; ts alone collides whenever two branches record within one - second, which every scripted run does. + second, which every scripted run does. An id token in the headline is + masked: the per-kind renumber rewrites it, and a key that followed the + rewrite would orphan every event stored before it. A headline with no + token hashes exactly as it did before. """ text = (entry.get("original") or {}).get("text", entry.get("text", "")) + text = ID_TOKEN.sub("#", str(text or "")) fields = (entry.get("kind"), entry.get("ts"), entry.get("author"), entry.get("session"), text) raw = "\0".join(str(value or "") for value in fields) return hashlib.sha1(raw.encode("utf-8")).hexdigest()[:12] @@ -764,6 +802,25 @@ def rebind(ids: list[str], keys: dict[str, str], entries: list[dict[str, Any]]) return out +def stale_keys(ids: list[str], keys: dict[str, str], entries: list[dict[str, Any]]) -> list[str]: + """Ids whose stored key fits neither their own record nor any other. + + ``rebind`` leaves such an id as written, so a caller that wants to report + it needs this. An id with no record is not listed: that is a dangling + reference, reported separately. + """ + by_id = {str(entry.get("id")): entry for entry in entries} + held = {record_key(entry) for entry in entries} + return [ + ident + for ident in ids + if ident in keys + and ident in by_id + and record_key(by_id[ident]) != keys[ident] + and keys[ident] not in held + ] + + def graph_payload(entries: list[dict[str, Any]]) -> dict[str, Any]: """Return the graph viewer's version 2 wire representation.""" # CLI filters may pass a projected subset whose relation targets are not diff --git a/docket/merge_driver.py b/docket/merge_driver.py index 8615170..5def238 100644 --- a/docket/merge_driver.py +++ b/docket/merge_driver.py @@ -4,7 +4,7 @@ holds. On a non-zero exit it marks the path unmerged but still takes that file as the worktree version, so a failure must leave conflict markers in it: an untouched OURS would look like a clean ledger, and staging it would drop -every incoming record. +every incoming record. A refusal for mixed schemas counts as a failure. """ from __future__ import annotations @@ -15,7 +15,7 @@ from pathlib import Path from typing import Any -from docket import env, feature_project, features, ledger, rebase +from docket import env, feature_project, features, ledger, migrate, rebase from docket.feature_archive import highest_archived_id @@ -96,7 +96,12 @@ def _feature_tail( """ def key(event: dict[str, Any]) -> str: - return json.dumps({k: v for k, v in event.items() if k != "id"}, sort_keys=True) + # Ledger ids, their keys and the schema differ between copies of one + # event that two branches migrated separately, or that BASE still + # holds at features schema 1. ts, author, session and text still tell + # two recordings apart. + skip = {"id", "schema", "keys", *features.LEDGER_REFS} + return json.dumps({k: v for k, v in event.items() if k not in skip}, sort_keys=True) shared = rebase.common_prefix(ours, theirs) waiting: dict[str, int] = {} @@ -122,23 +127,87 @@ def key(event: dict[str, Any]) -> str: return tail +def _first_schema(path: Path) -> Any: + """The schema of the first line, 1 when it declares none, None when unreadable or empty.""" + try: + lines = path.read_text(encoding="utf-8").splitlines() + except (OSError, UnicodeError): + return None + for line in lines: + if line.strip(): + try: + value = json.loads(line) + except json.JSONDecodeError: + return None + return value.get("schema", 1) if isinstance(value, dict) else None + return None + + +def _raw(path: Path) -> list[dict[str, Any]]: + return [ + json.loads(line) for line in path.read_text(encoding="utf-8").splitlines() if line.strip() + ] + + +def _base_ledger(path: Path) -> list[dict[str, Any]]: + """BASE, upgraded in memory when it is one schema behind. + + Only the matching in rebase.merge reads it, and both branches migrated from + this same file, so renumbering it gives the ids they now share. It is never + written back. + """ + if _first_schema(path) == ledger.SCHEMA - 1: + return migrate.renumber_step(_raw(path))[0] + return ledger.read(path, lock=False, strict=True) + + +def _behind(ours: Path, theirs: Path, current: int) -> tuple[str, int] | None: + for label, path in (("this branch's", ours), ("the other branch's", theirs)): + schema = _first_schema(path) + if isinstance(schema, int) and schema < current: + return label, schema + return None + + def run(base: Path, ours: Path, theirs: Path) -> int: - """Merge THEIRS into OURS in place. 0 when merged, 1 when left in conflict.""" + """Merge THEIRS into OURS in place. 0 when merged, 1 when left in conflict or refused.""" moved: dict[str, str] = {} + holds_features = _holds_features(base, ours, theirs) + behind = _behind(ours, theirs, features.SCHEMA if holds_features else ledger.SCHEMA) + if behind: + side, schema = behind + noun = "features file" if holds_features else "ledger" + print( + f"docket: cannot merge {ours.name}: {side} {noun} is schema {schema}; " + "run docket migrate on it, commit, and merge again", + file=sys.stderr, + ) + _conflict(base, ours, theirs) + return 1 try: - if _holds_features(base, ours, theirs): - old, mine, incoming = (features.read(p, lock=False) for p in (base, ours, theirs)) - tail = _feature_tail(old, mine, incoming) + if holds_features: + mine, incoming = (features.read(p, lock=False) for p in (ours, theirs)) + # BASE is read raw: it may still be schema 1, and only matching uses it. + tail = _feature_tail(_raw(base), mine, incoming) else: # lock=False: the default lock creates .lock next to git's # temp files at the repository root, where nothing ignores it. - old, mine, incoming = ( - ledger.read(p, lock=False, strict=True) for p in (base, ours, theirs) - ) + old = _base_ledger(base) + mine, incoming = (ledger.read(p, lock=False, strict=True) for p in (ours, theirs)) tail, moved = rebase.merge(old, mine, incoming) ledger.validate_entries(mine + tail) - except (ledger.LedgerError, rebase.RebaseError, features.FeatureError, OSError) as exc: + except ( + ledger.LedgerError, + rebase.RebaseError, + features.FeatureError, + json.JSONDecodeError, + OSError, + # BASE is read raw: a non-UTF-8 file or a line that is JSON but not an object. + UnicodeError, + AttributeError, + TypeError, + ) as exc: print(f"docket: cannot merge {ours.name}: {exc}", file=sys.stderr) _conflict(base, ours, theirs) return 1 diff --git a/docket/migrate.py b/docket/migrate.py index c229d28..65b44c7 100755 --- a/docket/migrate.py +++ b/docket/migrate.py @@ -1,5 +1,8 @@ #!/usr/bin/env python3 -"""Explicitly migrate a schema-1 Docket JSONL ledger to schema 2. +"""Explicitly migrate a Docket JSONL ledger to the current schema. + +Schema 1 becomes schema 2 through the classification map described below. Schema 2 +becomes schema 3 by renumbering each kind from 1 (docket.rebase.renumber_per_kind). The classification map is a JSON object keyed by every source ID. Each map value must contain ``kind``, ``state``, and ``text`` and may contain any typed @@ -29,11 +32,20 @@ from __future__ import annotations import json +import os import re +import shutil +import subprocess +from collections.abc import Mapping +from contextlib import ExitStack +from dataclasses import dataclass, field from pathlib import Path -from typing import Any, Callable +from typing import Any, Callable, Sequence -from docket.ledger import ledger_lock, validate_entries +from docket import feature_archive, features +from docket.ledger import ID_TOKEN, ledger_lock, project, validate_entries +from docket.ledger import read as read_ledger +from docket.rebase import ProseChange, RebaseError, renumber_per_kind OLD_ID = re.compile(r"^d[1-9][0-9]*$") NEW_ID = re.compile(r"^[cdq][1-9][0-9]*$") @@ -67,7 +79,7 @@ "decided_by", *RELATION_FIELDS, } -SCHEMA_LATEST = 2 +SCHEMA_LATEST = 3 # Schema 1 typed the difference between settling on doing something and # settling on not doing it. Schema 2 does not, and the choice text carries it. @@ -111,7 +123,7 @@ def read_source(path: Path) -> list[dict[str, Any]]: if not isinstance(raw, dict): raise MigrationError(f"malformed input at line {lineno}: record must be an object") old_id = raw.get("id") - if raw.get("schema") == SCHEMA_LATEST: + if isinstance(raw.get("schema"), int) and raw["schema"] >= 2: records.append(raw) continue if not isinstance(old_id, str) or not OLD_ID.fullmatch(old_id): @@ -489,7 +501,15 @@ def build_records( def core_validator() -> Callable[[list[dict[str, Any]]], Any]: - return validate_entries + """Validate schema-2 records as the schema-3 ledger they would become. + + Returns None, so migrate() keeps the schema-2 records it was given. + """ + + def check(records: list[dict[str, Any]]) -> None: + validate_entries(renumber_step(records)[0]) + + return check def migrate( @@ -518,62 +538,394 @@ def migrate( raise MigrationError(f"cannot create output {output_path}: {exc}") from exc -STEPS = {1: build_records} +def renumber_step( + records: list[dict[str, Any]], +) -> tuple[list[dict[str, Any]], dict[str, str], list[ProseChange]]: + """Schema 2 to 3: per-kind ids, with schema 3 stamped on every line.""" + renumbered, mapping, prose_changes = renumber_per_kind(records) + return [{**record, "schema": SCHEMA_LATEST} for record in renumbered], mapping, prose_changes + -BACKUP_SUFFIX = ".schema1" +STEPS = {1: build_records, 2: renumber_step} + +BACKUP_SUFFIX = ".schema" TEMP_SUFFIX = ".migrating" +@dataclass +class MigrationResult: + count: int + report: list[str] + notes: list[str] + mapping: dict[str, str] + per_kind: dict[str, int] + prose_changes: list[ProseChange] + features_events: int = 0 + rewritten: list[str] = field(default_factory=list) + rewrite_counts: dict[str, int] = field(default_factory=dict) + backup: str = "" + + def _report_line(old_id: str, record: dict[str, Any]) -> str: - return f"{old_id} -> {record['id']} {record['kind']}/{record['state']}" + # Correction and review lines carry no state. + state = record.get("state") + return f"{old_id} -> {record['id']} {record['kind']}" + (f"/{state}" if state else "") + + +def _run_step( + version: int, + records: list[dict[str, Any]], + mapping_path: Path | str | None, + notes: list[str], +) -> tuple[list[dict[str, Any]], dict[str, str], list[ProseChange]]: + if version != 1: + try: + return renumber_step(records) + except RebaseError as exc: + raise MigrationError( + f"cannot renumber this ledger: {exc}; run docket check and repair it first" + ) from exc + # The classification map exists only for schema 1: it assigns the kinds that + # schema never recorded. Every later step is mechanical. + if mapping_path is None: + classes = derive_mapping(records, notes=notes) + else: + classes = read_mapping(Path(mapping_path), {raw["id"] for raw in records}) + return build_records(records, classes), {}, [] + + +def _feature_files(ledger_path: Path) -> list[Path]: + store = ledger_path.parent / "features.jsonl" + found = [store] if store.exists() else [] + return found + sorted(feature_archive.archive_dir_for(store).glob("features-*.jsonl")) + + +def _read_events(path: Path) -> list[dict[str, Any]]: + """Raw events, unvalidated: features.read refuses the schema this step upgrades.""" + events: list[dict[str, Any]] = [] + for number, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1): + if not line.strip(): + continue + try: + event = json.loads(line) + except json.JSONDecodeError as exc: + raise MigrationError(f"{path}: line {number}: invalid JSON: {exc.msg}") from exc + if not isinstance(event, dict): + raise MigrationError(f"{path}: line {number}: event must be an object") + events.append(event) + return events + + +def _migrated_map(records: list[dict[str, Any]]) -> dict[str, str]: + """Old id to new id, from the ledger's own ``migrated_from``. + + An old id held by two records is left out: a merge from a schema-2 branch + can give one old id to a record on each side, and guessing would point an + event at the wrong one. ``docket check`` reports the id it leaves behind. + """ + held: dict[str, list[str]] = {} + for record in records: + if record.get("migrated_from"): + held.setdefault(record["migrated_from"], []).append(record["id"]) + return {old: ids[0] for old, ids in held.items() if len(ids) == 1} + + +def _remap_features( + ledger_path: Path, mapping: dict[str, str], records: list[dict[str, Any]] +) -> list[tuple[Path, list[dict[str, Any]]]]: + """Every features file still at schema 1, with its events remapped. + + A file at schema 2 was rewritten by an earlier run that died before the + ledger swap; its ids are already new, and mapping them again would send + each to a different record. + """ + by_id = {entry["id"]: entry for entry in project(records, validated=True)} + pending = [] + for target in _feature_files(ledger_path): + events = _read_events(target) + if any(event.get("schema") == 1 for event in events): + pending.append((target, features.remap_events(events, mapping, by_id))) + return pending + + +def _events_text(events: list[dict[str, Any]]) -> str: + return "".join(json.dumps(e, ensure_ascii=False, separators=(",", ":")) + "\n" for e in events) + + +def _write_synced(temp: Path, text: str) -> None: + with temp.open("w", encoding="utf-8") as handle: + handle.write(text) + handle.flush() + os.fsync(handle.fileno()) + + +def _check_backup(path: Path, backup: Path) -> None: + """Refuse a backup that is not a copy of the ledger being migrated. + + An identical one is what a crashed run leaves behind, and the rerun accepts it. + """ + if backup.exists() and backup.read_bytes() != path.read_bytes(): + raise MigrationError( + f"{backup} already exists and differs from {path}; a second migration " + "would overwrite the original. If another branch's migration left the backup, " + "delete or move it and run docket migrate again" + ) + + +def _link_backup(path: Path, backup: Path) -> None: + try: + os.link(path, backup) + except FileExistsError: + _check_backup(path, backup) + except OSError: + # No hard links on this filesystem. Copy through a temp so a crash + # cannot leave a half-written backup that the next run would refuse. + staging = backup.with_name(backup.name + TEMP_SUFFIX) + shutil.copyfile(path, staging) + os.replace(staging, backup) + + +def _commit( + path: Path, + backup: Path, + records: list[dict[str, Any]] | None, + remap: Callable[[], list[tuple[Path, list[dict[str, Any]]]]], + extra: tuple[tuple[Path, str], ...] = (), + expected: bytes | None = None, +) -> int: + """Write every file the migration touches. Returns the features events rewritten. + + Ledger lock, then the features lock. Every temp is written and fsynced + before the first rename, so a failure while writing leaves nothing moved. + Features and ``extra`` files go first; the ledger goes last, as a + hard-linked backup and then one os.replace, so a crash anywhere leaves the + ledger at its old schema and a rerun repeats the work, skipping the + features files that already moved. ``records`` is None when the ledger is + already current and only features files move. ``expected`` is the ledger's + bytes as the migration read them; the ledger is compared with it under the + lock, because the renumbered file would otherwise erase a line an older + docket appended since. + """ + store = path.parent / "features.jsonl" + temp = Path(str(path) + TEMP_SUFFIX) + with ExitStack() as locks: + locks.enter_context(ledger_lock(path)) + if store.exists(): + locks.enter_context(ledger_lock(store)) + if expected is not None and path.read_bytes() != expected: + raise MigrationError("the ledger changed while migrating; run docket migrate again") + pending = remap() + staged = [ + (target.with_name(target.name + TEMP_SUFFIX), target, _events_text(events)) + for target, events in pending + ] + staged += [(t.with_name(t.name + TEMP_SUFFIX), t, text) for t, text in extra] + temps = [staging for staging, _, _ in staged] + ([temp] if records is not None else []) + try: + for staging, _, text in staged: + _write_synced(staging, text) + if records is not None: + _write_synced( + temp, + "".join( + json.dumps(r, ensure_ascii=False, sort_keys=True) + "\n" for r in records + ), + ) + except BaseException: + for stale in temps: + stale.unlink(missing_ok=True) + raise + for staging, target, _ in staged: + os.replace(staging, target) + if records is not None: + _link_backup(path, backup) + os.replace(temp, path) + return sum(len(events) for _, events in pending) + + +def rewrite_text(text: str, mapping: Mapping[str, str]) -> tuple[str, int]: + """Replace every mapped id token once; return the new text and how many changed. + + One substitution pass with a dict lookup per token, so d4 -> d2 never feeds + d2 -> d1. A token with a suffix (`d2.1`, `d72.r1`) matches on its leading id + and keeps the suffix, which is how corrections and reviews renumber. + """ + changed = 0 + + def swap(match: re.Match[str]) -> str: + nonlocal changed + old = match.group(0) + new = mapping.get(old, old) + if new != old: + changed += 1 + return new + + return ID_TOKEN.sub(swap, text), changed + + +def _is_store_file(file: Path, ledger: Path) -> bool: + """The ledger and features files, which the migration already rewrites itself.""" + directory = ledger.parent.resolve() + return ( + file.parent == directory and file.name.startswith(("ledger.jsonl", "features.jsonl")) + ) or file.parent == directory / "archive" + + +def _tracked_and_clean(file: Path) -> None: + """Refuse a file git cannot restore. + + The rewritten file replaces the original before the ledger changes, so a + crash between the two leaves it at new ids beside a schema 2 ledger. A rerun + would map it again. A clean tracked file makes that visible as a modification + to undo with `git checkout -- FILE`, and holds the old text for review. + """ + + def run(*argv: str) -> subprocess.CompletedProcess[str]: + return subprocess.run( + ["git", "-C", str(file.parent), *argv, "--", file.name], + capture_output=True, + text=True, + ) + + try: + tracked = run("ls-files", "--error-unmatch") + status = run("status", "--porcelain") + except OSError as exc: + raise MigrationError(f"--rewrite needs git to check {file}: {exc}") from exc + if tracked.returncode != 0: + raise MigrationError( + f"--rewrite: {file} is not tracked by git; commit it first so the old text is kept" + ) + if status.stdout.strip(): + raise MigrationError(f"--rewrite: {file} has uncommitted changes; commit or stash them") + + +def _plan_rewrites( + files: Sequence[Path | str], mapping: Mapping[str, str], ledger: Path +) -> list[tuple[Path, str, int]]: + """Read every named file and return (path, new text, ids changed) for those that change. + + Nothing is written here, so a file that cannot be read fails the run before + the write phase starts. + """ + plans: list[tuple[Path, str, int]] = [] + seen: set[Path] = set() + for item in files: + file = Path(item) + resolved = file.resolve() + if resolved in seen: + raise MigrationError(f"--rewrite names {file} twice") + seen.add(resolved) + if _is_store_file(resolved, ledger): + raise MigrationError(f"--rewrite cannot rewrite {file}; migrate rewrites it itself") + if not file.is_file(): + raise MigrationError(f"--rewrite: {file} is not a file") + _tracked_and_clean(file) + try: + # Bytes in and out: read_text would turn CRLF into LF. + text = file.read_bytes().decode("utf-8") + except (OSError, UnicodeError) as exc: + raise MigrationError(f"--rewrite: cannot read {file}: {exc}") from exc + new, count = rewrite_text(text, mapping) + if new != text: + plans.append((file, new, count)) + return plans def migrate_in_place( - path: Path | str, mapping_path: Path | str | None = None, dry_run: bool = False -) -> tuple[int, list[str], list[str]]: + path: Path | str, + mapping_path: Path | str | None = None, + dry_run: bool = False, + rewrite: Sequence[Path | str] = (), +) -> MigrationResult: """Convert a ledger to the current schema, keeping the original beside it. - Both renames happen inside one directory, so each is atomic. A crash - between them leaves the source at BACKUP_SUFFIX and the result at - TEMP_SUFFIX, and neither file is truncated. + Every step runs in memory before anything is written, so a failure at any + version leaves the ledger as it was. The backup is named after the starting + schema. The features store and archives move with the ledger; see ``_commit`` + for the write order and what a crash leaves behind. A ledger already current + still gets its features files remapped when they are at schema 1. """ path = Path(path) - backup = Path(str(path) + BACKUP_SUFFIX) - temp = Path(str(path) + TEMP_SUFFIX) + # Taken before the parse, so a line appended in between shows up as a + # difference at commit time rather than being absorbed into the snapshot. + try: + snapshot = path.read_bytes() + except OSError as exc: + raise MigrationError(f"cannot read source {path}: {exc}") from exc source = read_source(path) version = detect_version(source) + backup = Path(f"{path}{BACKUP_SUFFIX}{version}") + if rewrite and version == SCHEMA_LATEST: + raise MigrationError( + f"--rewrite runs alongside a migration, and this ledger is already at schema " + f"{SCHEMA_LATEST}; its ids in your files are already current" + ) if version == SCHEMA_LATEST: - return 0, [], [] - step = STEPS.get(version) - if step is None: + result = MigrationResult(0, [], [], {}, {}, []) + records = read_ledger(path, lock=False) + mapping = _migrated_map(records) + if dry_run: + pending = _remap_features(path, mapping, records) + result.features_events = sum(len(events) for _, events in pending) + else: + result.features_events = _commit( + path, backup, None, lambda: _remap_features(path, mapping, records) + ) + return result + if version not in STEPS: raise MigrationError(f"no migration from schema {version} to {SCHEMA_LATEST}") - - # Checked only once a conversion is actually needed: a ledger already at - # schema 2 must exit clean even if an earlier migration left a backup. - if not dry_run and backup.exists(): + if mapping_path is not None and version != 1: raise MigrationError( - f"{backup} already exists; a second migration would overwrite the original" + f"a classification map applies only to schema 1; this ledger is schema {version}" ) - old_ids = {raw["id"] for raw in source} + # Checked only once a conversion is actually needed: a ledger already at + # the latest schema must exit clean even if an earlier migration left a backup. + if not dry_run: + _check_backup(path, backup) + notes: list[str] = [] - if mapping_path is None: - mapping = derive_mapping(source, notes=notes) - else: - mapping = read_mapping(Path(mapping_path), old_ids) - records = step(source, mapping) - records = core_validator()(records) or records - report = [_report_line(raw["id"], record) for raw, record in zip(source, records)] + records = source + renumbered: dict[str, str] = {} + prose_changes: list[ProseChange] = [] + for current in range(version, SCHEMA_LATEST): + records, renumbered, prose_changes = _run_step(current, records, mapping_path, notes) + records = validate_entries(records) + result = MigrationResult( + count=len(records), + report=[_report_line(raw["id"], record) for raw, record in zip(source, records)], + notes=notes, + mapping=renumbered, + per_kind={kind: sum(r["kind"] == kind for r in records) for kind in PREFIX}, + prose_changes=prose_changes, + backup=str(backup), + ) + cited = renumbered + if version == 1: + # Files in a schema 1 project cite schema 1 ids, which renumbered + # (the schema 2 to 3 step only) does not know. + cited = { + record["legacy"]["source_id"]: record["id"] + for record in records + if isinstance(record.get("legacy"), dict) + and isinstance(record["legacy"].get("source_id"), str) + } + plans = _plan_rewrites(rewrite, cited, path) if rewrite else [] + result.rewritten = [str(file) for file, _, _ in plans] + result.rewrite_counts = {str(file): count for file, _, count in plans} if dry_run: - return len(records), report, notes - - with ledger_lock(path): - if temp.exists(): - raise MigrationError(f"{temp} already exists; remove it and retry") - with temp.open("x", encoding="utf-8") as handle: - for record in records: - handle.write(json.dumps(record, ensure_ascii=False, sort_keys=True) + "\n") - path.rename(backup) - temp.rename(path) - return len(records), report, notes + pending = _remap_features(path, renumbered, records) + result.features_events = sum(len(events) for _, events in pending) + return result + + result.features_events = _commit( + path, + backup, + records, + lambda: _remap_features(path, renumbered, records), + extra=tuple((file, text) for file, text, _ in plans), + expected=snapshot, + ) + return result diff --git a/docket/rebase.py b/docket/rebase.py index 8ad9305..5fd7b1f 100644 --- a/docket/rebase.py +++ b/docket/rebase.py @@ -18,10 +18,10 @@ import copy import json from collections.abc import Mapping, Sequence -from typing import Any +from typing import Any, NamedTuple from docket import corrections, reviews -from docket.ledger import ID_RE, allocate_id +from docket.ledger import ID_RE, ID_TOKEN, allocate_id class RebaseError(ValueError): @@ -29,6 +29,60 @@ class RebaseError(ValueError): _REFERENCE_FIELDS = ("depends_on", "answers", "supersedes") +PROSE_FIELDS = ("text", "choice", "alternatives", "rationale", "cost_if_wrong", "revisit") +_KIND_LETTER = {"claim": "c", "decision": "d", "question": "q"} + + +class ProseChange(NamedTuple): + """One prose edit of ``renumber_per_kind``, for the ``--dry-run`` report. + + ``line_id`` is the line's id before renumbering. ``before`` and ``after`` + are the whole string, or one element of a list-valued field. An id token + that names no mapped record is reported with ``before`` the token itself + and ``after`` None. + """ + + line_id: str + field: str + before: str + after: str | None + + +def rewrite_prose( + value: Any, mapping: Mapping[str, str], via: Mapping[str, str] | None = None +) -> Any: + """``value`` with every mapped id token replaced. + + One substitution pass with a dict lookup per token. Chaining would turn + c3 into c1 when c3 -> c2 and c2 -> c1 are both in the mapping. ``via`` + renames a token first: a legacy line's prose cites schema-1 ids, which + ``via`` carries to the schema-2 ids that ``mapping`` is keyed by. + """ + + def swap(match: Any) -> str: + token = match.group(0) + return mapping.get(via.get(token, token) if via else token, token) + + if isinstance(value, str): + return ID_TOKEN.sub(swap, value) + if isinstance(value, list): + return [rewrite_prose(v, mapping, via) if isinstance(v, str) else v for v in value] + return value + + +def _prose_slots(row: Mapping[str, Any]) -> list[tuple[Any, str]]: + """The (container, key) pairs of ``row`` that hold wording.""" + + kind = row.get("kind") + if kind == corrections.KIND: + fields = row.get("fields") + slots: list[tuple[Any, str]] = ( + [(fields, f) for f in PROSE_FIELDS if f in fields] if isinstance(fields, dict) else [] + ) + return slots + ([(row, "reason")] if "reason" in row else []) + if kind == reviews.KIND: + return [(row, "note")] if "note" in row else [] + return [(row, f) for f in PROSE_FIELDS if f in row] def common_prefix(mine: Sequence[Mapping[str, Any]], theirs: Sequence[Mapping[str, Any]]) -> int: @@ -50,8 +104,10 @@ def _retired_in(records: Sequence[Mapping[str, Any]]) -> set[str]: return retired -def _translated(record: Mapping[str, Any], mapping: Mapping[str, str]) -> dict[str, Any]: - """A copy of ``record`` with every ID it cites passed through ``mapping``.""" +def _translated( + record: Mapping[str, Any], mapping: Mapping[str, str], via: Mapping[str, str] | None = None +) -> dict[str, Any]: + """A copy of ``record`` with every ID it cites, and every id its prose mentions, mapped.""" def get(value: Any) -> str: return mapping.get(str(value), str(value)) @@ -67,6 +123,8 @@ def get(value: Any) -> str: out[field] = [get(v) for v in out[field]] if out.get("supports"): out["supports"] = [[get(v) for v in group] for group in out["supports"]] + for holder, field in _prose_slots(out): + holder[field] = rewrite_prose(holder[field], mapping, via) return out @@ -82,11 +140,22 @@ def _cited(record: Mapping[str, Any]) -> set[str]: def _key(record: Mapping[str, Any]) -> str: - """The record minus its own id, so a renumbered copy compares equal.""" + """The record minus its own id, ``migrated_from`` and id tokens in its prose. - return json.dumps( - {k: v for k, v in record.items() if k != "id"}, sort_keys=True, ensure_ascii=False - ) + A record migrated on two branches, or merged before one of them migrated, + carries different ids, a different ``migrated_from`` and different numbers + in its wording on each side. Relations stay in the key, so records that + cite different records still differ. + """ + + row = copy.deepcopy({k: v for k, v in record.items() if k not in ("id", "migrated_from")}) + for holder, field in _prose_slots(row): + value = holder[field] + if isinstance(value, str): + holder[field] = ID_TOKEN.sub("#", value) + elif isinstance(value, list): + holder[field] = [ID_TOKEN.sub("#", v) if isinstance(v, str) else v for v in value] + return json.dumps(row, sort_keys=True, ensure_ascii=False) def merge( @@ -97,8 +166,9 @@ def merge( """Return the records of ``theirs`` to append to ``ours``, and their old-to-new IDs. A THEIRS record that equals an OURS record once its citations are - translated is the same recording under another ID, so it maps to that ID - and is not appended: that is what lets a branch merge twice. One that + translated and ids in its wording are ignored is the same recording under + another ID, so it maps to that ID and is not appended: that is what lets a + branch merge twice. One that equals a BASE record but no OURS record was removed or rewritten on our side and stays out, which keeps a cherry-pick from importing the picked commit's whole history. Citations only point backwards, so one pass in @@ -161,3 +231,91 @@ def renumber( """Return their tail with fresh IDs, and the old-to-new ID map.""" return merge([], mine, theirs) + + +def _prose_changes( + line_id: str, + before: Mapping[str, Any], + after: Mapping[str, Any], + mapping: Mapping[str, str], + via: Mapping[str, str] | None, +) -> list[ProseChange]: + changes: list[ProseChange] = [] + for (old_holder, field), (new_holder, _) in zip(_prose_slots(before), _prose_slots(after)): + old, new = old_holder[field], new_holder[field] + pairs = zip(old, new) if isinstance(old, list) else [(old, new)] + for was, now in pairs: + if not isinstance(was, str): + continue + if was != now: + changes.append(ProseChange(line_id, field, was, now)) + for match in ID_TOKEN.finditer(was): + token = match.group(0) + if (via.get(token, token) if via else token) not in mapping: + changes.append(ProseChange(line_id, field, token, None)) + return changes + + +def renumber_per_kind( + records: Sequence[Mapping[str, Any]], +) -> tuple[list[dict[str, Any]], dict[str, str], list[ProseChange]]: + """Give claims, decisions and questions independent counters, in file order. + + Corrections and reviews take their target's new id and keep their suffix. + Citations only point backwards, so the mapping built so far holds every id + a line cites, and renumbering a prefix gives the prefix of renumbering the + whole. A duplicate id, or a citation of an id no earlier line defines, + raises RebaseError, because either would rewrite silently to the wrong + record. + + A line's own id is mapped before its prose is rewritten. On a line that + carries ``legacy.source_id``, prose tokens are schema-1 ids and resolve + through the source ids of the lines so far first. + + Returns the new records, the old-to-new map for claims, decisions and + questions, and every prose rewrite and unmapped token, for ``--dry-run``. + """ + + counters = {"c": 0, "d": 0, "q": 0} + mapping: dict[str, str] = {} + legacy_map: dict[str, str] = {} + seen: set[str] = set() + out: list[dict[str, Any]] = [] + changes: list[ProseChange] = [] + for record in records: + kind = record.get("kind") + old = str(record.get("id", "")) + if old in seen: + raise RebaseError(f"{old} appears twice; the ledger cannot be renumbered") + seen.add(old) + needed = _cited(record) + suffix: tuple[str, str, int] | None = None + if kind in (corrections.KIND, reviews.KIND): + module = corrections if kind == corrections.KIND else reviews + target, number = module.parts_of(old) + suffix = (target, "" if module is corrections else "r", number) + needed.add(target) + elif kind not in _KIND_LETTER: + raise RebaseError(f"{old or 'a line'} has unknown kind {kind!r}") + missing = sorted(n for n in needed if n not in mapping) + if missing: + raise RebaseError(f"{old} cites {', '.join(missing)}, which no earlier line defines") + if kind in _KIND_LETTER: + letter = _KIND_LETTER[kind] + counters[letter] += 1 + mapping[old] = f"{letter}{counters[letter]}" + legacy = record.get("legacy") + source = legacy.get("source_id") if isinstance(legacy, dict) else None + if isinstance(source, str): + legacy_map[source] = old + via = legacy_map if isinstance(source, str) else None + row = _translated(record, mapping, via) + if kind in _KIND_LETTER: + row["id"] = mapping[old] + row["migrated_from"] = old + elif suffix is not None: + target, mark, number = suffix + row["id"] = f"{mapping[target]}.{mark}{number}" + changes.extend(_prose_changes(old, record, row, mapping, via)) + out.append(row) + return out, mapping, changes diff --git a/docket/reviews.py b/docket/reviews.py index c110006..3f69716 100644 --- a/docket/reviews.py +++ b/docket/reviews.py @@ -35,7 +35,7 @@ def parts_of(ident: str) -> tuple[str, int]: def validate(record: dict[str, Any], prefix: Any) -> dict[str, Any]: """Validate a review line; ``prefix`` is a ledger._Prefix or None.""" - from docket.ledger import SCHEMA, _error + from docket.ledger import _error, _require_current ident = record.get("id") if not isinstance(ident, str) or (parts := split_id(ident)) is None: @@ -43,8 +43,7 @@ def validate(record: dict[str, Any], prefix: Any) -> dict[str, Any]: unknown = sorted(set(record) - LINE_FIELDS) if unknown: raise _error(ident, f"unknown field(s): {', '.join(unknown)}") - if type(record.get("schema")) is not int or record["schema"] != SCHEMA: - raise _error("schema", f"expected schema {SCHEMA}, got {record.get('schema')!r}") + _require_current(record) for field in ("ts", "author", "session", "branch", "note"): if not isinstance(record.get(field), str): raise _error(ident, f"{field} must be a string") diff --git a/docket/where.py b/docket/where.py index f2da4f6..ce77c5f 100644 --- a/docket/where.py +++ b/docket/where.py @@ -19,7 +19,7 @@ from docket.context_model import _list, _normalize_path, scope_strength from docket.ledger import KINDS, STATES -FIELDS = ("after", "author", "before", "branch", "is", "kind", "scope", "state") +FIELDS = ("after", "author", "before", "branch", "is", "kind", "scope", "state", "was") IS_VALUES = ("blocked", "corrected", "flagged", "pinned", "retired", "unsupported") STATE_VALUES = tuple(sorted({state for values in STATES.values() for state in values})) _TEXT_KEYS = ("id", "text", "choice", "rationale") @@ -47,7 +47,12 @@ class Query: @property def wants_retired(self) -> bool: - return any(t.field == "is" and t.value == "retired" and not t.negated for t in self.terms) + # was: names a record by an id it no longer carries, and a migration + # often leaves that record retired. + return any( + not t.negated and (t.field == "was" or (t.field == "is" and t.value == "retired")) + for t in self.terms + ) @property def has_fields(self) -> bool: @@ -150,12 +155,27 @@ def _day(term: str, value: str) -> date: raise _fail(term, "dates are YYYY-MM-DD") +def old_ids(entry: Mapping[str, Any]) -> tuple[str, ...]: + """The ids a migrated record carried before: its schema 2 id and its schema 1 id. + + A record migrated from schema 1 holds both, and they can differ in letter + (c4 with legacy.source_id d4). + """ + legacy = entry.get("legacy") + source = legacy.get("source_id") if isinstance(legacy, dict) else None + found = (entry.get("migrated_from"), source) + return tuple(item for item in found if isinstance(item, str) and item) + + def _hit(term: Term, entry: Mapping[str, Any]) -> bool: field, value = term.field, term.value if not field: return any(value in str(entry.get(key) or "").lower() for key in _TEXT_KEYS) if field in ("kind", "state"): return str(entry.get(field) or "").lower() == value + if field == "was": + # Exact, unlike author and branch: was:c3 must not find c30. + return value in (old.lower() for old in old_ids(entry)) if field in ("author", "branch"): return value in str(entry.get(field) or "").lower() if field == "is": @@ -214,4 +234,4 @@ def _ts_day(raw: Any) -> date | None: return stamp.astimezone(timezone.utc).date() -__all__ = ["FIELDS", "IS_VALUES", "Query", "STATE_VALUES", "Term", "WhereError", "parse"] +__all__ = ["FIELDS", "IS_VALUES", "Query", "STATE_VALUES", "Term", "WhereError", "old_ids", "parse"] diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 675be45..e5b635e 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -22,6 +22,7 @@ * [Commands](commands.md) * [Environment variables](environment.md) * [Ledger format and rules](ledger.md) +* [Schema versions](schemas.md) * [Installer options and behavior](installer-reference.md) * [Manual agent setup](integrations.md) * [Setup instructions for agents](agent-setup.md) diff --git a/docs/commands.md b/docs/commands.md index 5ba7352..6a98f13 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -18,7 +18,7 @@ Ledger commands use the file that `docket where` reports. Run | `docket check` | Report what makes the ledger unreadable | | `docket feature ...` | Track a piece of work in flight; see below | | `docket init` | Create a project ledger and copy any existing private records into it. It also adds the ledger merge driver to `.gitattributes` and, when `docket` is on PATH, registers it in the clone's git config; git invokes the driver during merges. Re-running it repairs a fresh clone | -| `docket migrate` | Convert a pre-0.8 ledger to the current schema | +| `docket migrate` | Convert an older ledger to the current schema | | `docket rebase` | Renumber another branch's records onto this ledger | | `docket update` | Update this Docket installation; `--check` reports without changing anything | | `docket completion SHELL` | Print a shell completion script | @@ -194,6 +194,7 @@ The projection adds derived fields. They are never stored in the ledger. | `is:pinned`, `is:corrected`, `is:retired`, `is:blocked` | the record is pinned, corrected, or retired, or is a blocked decision | | `is:flagged`, `is:unsupported` | the record is a current accepted claim or adopted decision whose derived `support` is `flagged` or `unsupported` | | `author:A`, `branch:B` | the author or the branch contains the value | +| `was:ID` | the record carried ID before a migration: its `migrated_from` or its schema 1 `legacy.source_id` is ID. Matches exactly, and a merge across the migration can leave two records with one old ID | | `after:D`, `before:D` | the record's UTC date is on or after D, or before D; D is `YYYY-MM-DD` | - Spaces separate terms. Double quotes hold spaces: `author:"a teammate"`. @@ -265,9 +266,7 @@ the bad line or relation when it does not. `docket rebase OTHER` renumbers the records in `OTHER` onto the end of this ledger. Use `--dry-run` to see the ID map first. -`docket migrate` converts a schema 1 ledger. Use `--dry-run` to review the -conversion, `--emit-map PATH` to write the derived classification map, and -`--map PATH` to apply a map you edited. +`docket migrate` converts an older ledger to the current schema: schema 1 and schema 2 both end at schema 3 in one run. It prints a summary of what it renumbered and keeps the original at `ledger.jsonl.schemaN`. Use `--dry-run` to see the per-record report, every prose rewrite and every unmapped ID, and write nothing. `--rewrite FILE...` rewrites ID citations in the named files in the same run; each file must be tracked and clean, and with `--dry-run` it lists the files and counts instead. `--rewrite` needs a ledger that is about to migrate. `--emit-map PATH` writes the derived classification map and `--map PATH` applies one you edited; both apply to a schema 1 ledger only. See [Maintenance](maintenance.md) for repair and migration procedures. diff --git a/docs/decision-chains.md b/docs/decision-chains.md index ca7761c..cd762ae 100644 --- a/docs/decision-chains.md +++ b/docs/decision-chains.md @@ -14,7 +14,7 @@ which conclusions depend on which claims are the part the summary discards. ## Shipped in Docket 0.8.0 -Docket stores schema 2 records in an append-only JSONL ledger. The three record +Docket stores records in an append-only JSONL ledger. The three record types are: | Type | Recorded state | Meaning | diff --git a/docs/definitions.md b/docs/definitions.md index ac27bb2..ac22741 100644 --- a/docs/definitions.md +++ b/docs/definitions.md @@ -311,7 +311,7 @@ blocker will surface there as well. ### Required fields -Every schema 2 record contains these fields: +Every record contains these fields: - `schema`: schema version. - `kind`: record type. @@ -323,8 +323,7 @@ Every schema 2 record contains these fields: - `session`: session metadata. - `branch`: branch metadata. -IDs use `c`, `d`, or `q` followed by a positive integer. Allocation uses the -next global sequence across all types. +IDs use `c`, `d`, or `q` followed by a positive integer. Allocation uses the next number within the record's own kind, so claims, decisions, and questions each count from 1. ### Fields with defaults diff --git a/docs/ledger.md b/docs/ledger.md index 193b8d9..7f1b5ab 100644 --- a/docs/ledger.md +++ b/docs/ledger.md @@ -1,6 +1,6 @@ # Ledger reference -Docket 0.8.0 writes schema 2 records as append-only JSONL. Each non-empty line +Docket writes schema 3 records as append-only JSONL. Each non-empty line contains one JSON object. Reads validate the complete file, so Docket reports an invalid line or relation instead of silently dropping it. @@ -8,9 +8,9 @@ an invalid line or relation instead of silently dropping it. Every record has these required fields: -- `schema`: the schema number, which is `2` for this format. +- `schema`: the schema number, which is `3` for this format. - `kind`: `claim`, `decision`, or `question`. -- `id`: a type-prefixed record ID with a positive global sequence number. +- `id`: a type-prefixed record ID numbered within its kind. - `text`: the proposition, commitment, or inquiry. - `state`: the record's recorded workflow state. - `ts`: the record timestamp string. @@ -40,8 +40,7 @@ These checks run at write time. Reading a ledger checks structure alone, so older records remain readable. For example, this project's ledger contains 81 decisions phrased as questions that predate the rule. -IDs use the type prefix and a positive global sequence number: `c1`, `d2`, and -`q3`. The sequence is shared across kinds, and gaps are allowed. +IDs use the type prefix and a positive number that counts within the kind: `c1`, `d1`, and `q1` are the first claim, decision, and question. Each kind counts on its own, and gaps are allowed. A question's recorded state remains `open`. A current accepted claim or applicable adopted decision linked to it through `answers` gives it effective @@ -106,6 +105,7 @@ when their CLI options are omitted, and sets `pinned` to `false`: - `cost_if_wrong`: the stated cost if the record is wrong. - `pinned`: whether the record scores a fixed bonus in every briefing; defaults to `false`. A pin no longer outranks a better scope match. +- `migrated_from`: on a record the schema 3 migration renumbered, the ID it had at schema 2. Records created since never carry it. `list --json` and `show --json` omit it unless you pass `--legacy`, and `docket list --where was:ID` finds a record by it, or by the schema 1 ID kept in `legacy.source_id`. Path scopes use normalized repository-relative paths. A scope containing a slash or glob metacharacters uses `fnmatch`; a literal directory scope also @@ -328,7 +328,7 @@ docket show c12 --at d40 `append` allocates the record ID, validates, and writes while holding an exclusive lock on `ledger.jsonl.lock`. This prevents concurrent writers on -one host from allocating the same sequence number. Readers take a shared lock +one host from allocating the same ID twice. Readers take a shared lock on the same file so they do not read a partially written line. Two branches that both record append different lines after the same last line. `docket init` adds `.docket/ledger.jsonl merge=docket` and `.docket/features.jsonl merge=docket` to `.gitattributes` and registers `docket merge-driver` in the clone's git config, after which `git merge`, `git rebase` and `git cherry-pick` merge the ledger themselves: records on both sides are kept, the other side's new records take fresh IDs, and references follow. Git invokes `merge-driver`; it is not a command you run. @@ -356,6 +356,8 @@ targets A's record. Validation passes because the target exists and has the right kind, even though it is not the record B cited. Use `docket rebase` to preserve these references. +Both sides of a merge or `docket rebase` must be at the same schema. A branch still at an older schema runs `docket migrate` and commits first; the merge driver refuses otherwise and names the side that is behind, and `docket rebase` stops at the first file it reads that is behind. + Never use a union merge driver on the ledger. It keeps both branches' tails, which leaves two records holding one ID, and every command then fails, including the session hook. When a ledger stops reading, run `docket check`. It reports every malformed, @@ -388,10 +390,7 @@ The command derives a classification map from the old state field alone: doing something, and that commitment still applies. A revoked decision renders as unavailable support, which would tell an agent to ignore a live constraint. -Migration keeps the original. The converted ledger replaces `ledger.jsonl`, -and the untouched schema-1 file survives at `ledger.jsonl.schema1`. A ledger -already at schema 2 exits clean and changes nothing. `--dry-run` prints the -derived conversion and writes nothing. +Migration keeps the original. The converted ledger replaces `ledger.jsonl`, and the untouched file survives at `ledger.jsonl.schemaN`, where N is the schema the ledger started at. A ledger already at the current schema stays unchanged, and any features file still at schema 1 is remapped. `--dry-run` prints the per-record conversion and writes nothing. A schema-1 ledger goes straight to schema 3 in one run. Migration handles two common legacy relationships automatically: @@ -412,3 +411,20 @@ docket migrate --emit-map map.json # edit map.json by hand docket migrate --map map.json ``` + +## Migrating to schema 3 + +[Schema versions](schemas.md) gives the full upgrade procedure, including branches and interrupted runs. + +Schema 3 numbers each kind on its own: the first claim is `c1`, the first decision `d1`, the first question `q1`. A schema 2 ledger fails to read until you run `docket migrate`, which renumbers every record, retired ones included, in one pass and keeps each record's schema 2 ID in `migrated_from`. + + docket migrate --dry-run + docket migrate + +The first prints the per-record report, then every prose field it would rewrite and every ID token it would leave as written, and writes nothing. The second prints a summary: records renumbered per kind, prose fields rewritten, features events rewritten, and files rewritten. It also renumbers corrections and reviews with their targets, rewrites `.docket/features.jsonl` and `.docket/archive/features-*.jsonl` to the new IDs, and keeps the original at `ledger.jsonl.schema2`. Commit `ledger.jsonl` and the features files, and do not commit the `ledger.jsonl.schemaN` backup: two migrated branches that both commit it conflict on merge, and an uncommitted one left by another branch blocks the next migration until you delete or move it. + +`--rewrite FILE...` rewrites ID citations in the files you name, in the same run and with the same rule: each `c`, `d` or `q` token that names a renumbered record is replaced once, so `d4` becoming `d2` never feeds `d2` becoming `d1`. A file with nothing to rewrite is left alone, and `--dry-run` lists the files and counts without writing. Each file must be tracked and have no uncommitted changes, so git holds the old text and an interrupted run shows up as a modified file to restore with `git checkout -- FILE` before you rerun. Name files that cite real records; documents full of illustrative IDs such as `d2` would be rewritten wrongly. `--rewrite` is refused on a ledger already at schema 3, and `--map` and `--emit-map` are refused on a schema 2 ledger. + +Old IDs stay searchable and stop resolving. `docket list --where was:ID` finds the record that carried an old ID, and `docket show ID` for an ID that no longer exists names that command. If the old ID is also a current ID, `show` resolves to the current record without comment. + +Each branch migrates itself before it merges. The merge driver refuses to merge a ledger or features file whose side is still at an older schema, says which branch to migrate, and leaves the usual conflict markers so the file cannot be committed by accident. Abort the merge, rebase or cherry-pick in progress, migrate the branch that is behind, commit, and merge again. A collaborator on 0.25.x cannot read schema 3, so everyone upgrades docket and the plugin before a migrated ledger is merged. diff --git a/docs/maintenance.md b/docs/maintenance.md index 04ca27b..c2b886c 100644 --- a/docs/maintenance.md +++ b/docs/maintenance.md @@ -88,8 +88,7 @@ docket migrate docket check ``` -Migration saves the original as `ledger.jsonl.schema1`. Running it on a current -ledger leaves the file unchanged. +Migration saves the original beside the ledger as `ledger.jsonl.schemaN`, where N is the schema the ledger started at. Running it on a current ledger leaves the ledger unchanged and remaps any features file still at schema 1. A ledger at schema 2 migrates to schema 3 with the same command; see [Migrating to schema 3](ledger.md#migrating-to-schema-3). ## Adjust the briefing size diff --git a/docs/north-star.md b/docs/north-star.md index acc152b..21e11ae 100644 --- a/docs/north-star.md +++ b/docs/north-star.md @@ -34,7 +34,7 @@ brainstorming ends and the ledger starts. ### 1. Typed ledger The ledger is a persistent record of decisions stored outside any one session. -Each schema 2 record contains: +Each record contains: - `id`: stable identifier. - `kind`: `claim`, `decision`, or `question`. diff --git a/docs/schemas.md b/docs/schemas.md new file mode 100644 index 0000000..6fc2a3a --- /dev/null +++ b/docs/schemas.md @@ -0,0 +1,73 @@ +# Schema versions + +The ledger format carries a schema number on every line. This page lists the versions, what schema 3 changed, and how to upgrade a project and its branches. + +## Versions + +| Schema | Docket release | What it is | +| --- | --- | --- | +| 1 | before 0.8.0 | Untyped `dN` records with a `settled`, `ruled-out` or `open` state | +| 2 | 0.8.0 | Typed claims, decisions and questions with a kind and a state; the relations `supports`, `depends_on`, `answers` and `supersedes`; corrections and reviews; one id counter shared by every kind | +| 3 | 0.26.0 | Each kind numbered on its own | + +Every command refuses a ledger older than the docket reading it, and `docket migrate` brings any older ledger to the current schema in one run. + +## What changed in schema 3 + +| Field or file | Schema 3 | +| --- | --- | +| `schema` | 3 on every line, corrections and reviews included | +| Record ids | Count per kind (`c1`, `d1`, `q1`); a new record gets that kind's highest number plus one | +| `migrated_from` | Holds a migrated record's schema 2 id. Briefings never show it, and `list` and `show` JSON include it only with `--legacy`. Records created later never carry it | +| Correction and review ids | Follow their target: `d12.1` becomes `d5.1` | +| `legacy` | Left as it was | +| `.docket/features.jsonl` and its archive | Move to features schema 2, with the ledger ids they cite remapped | +| Feature keys | Ignore id tokens in a headline, so they survive the renumber | +| Merge and `docket rebase` | Require both sides at the same schema | + +The migration rewrites every place a record names another by id: relations, correction and review targets, and id mentions in record prose. The prose fields are `text`, `choice`, `alternatives`, `rationale`, `cost_if_wrong` and `revisit`, a correction's fields and reason, and a review's note. Each mention is replaced once, so shifted ids never chain: `d4` becoming `d2` does not then become `d1`. A schema 1 record resolves its old ids through `legacy.source_id` first. + +## Upgrading a project + +1. Upgrade docket and the plugin. The session hook then shows the migrate instruction instead of a briefing. +2. Preview the migration. + + ```sh + docket migrate --dry-run + ``` + + Read the prose changes and the unresolved tokens it lists. Note any change that rewrites an example id or an id quoted from another project. +3. Migrate. Add `--rewrite FILE...` for tracked, clean files that cite real ids of this ledger. + + ```sh + docket migrate + docket migrate --rewrite README.md docs/design.md + ``` + +4. Fix the false positives you noted. Find each record with `docket list --where was:OLD` and change it with `docket correct`. When the false positive is in a decision's `choice`, restate the decision by supersession instead: the new docket cannot write to a schema 2 ledger, and `correct` cannot change `choice`. +5. Commit `ledger.jsonl` and the features files. Do not commit the `ledger.jsonl.schema2` backup. +6. Delete the backup once you have checked the result. + +## Branches and collaborators + +Each branch migrates itself before it merges. A merge across schemas leaves conflict markers and names the side that is behind. Abort the merge, rebase or cherry-pick in progress, migrate that branch, commit, and merge again. + +Delete or move a backup left by another branch's migration before you migrate the next branch in the same worktree. Otherwise `docket migrate` refuses, because the backup differs from the ledger. + +A collaborator on 0.25.x cannot read schema 3, so everyone upgrades first. + +## If a migration is interrupted + +Run it again. The migration replaces the features files and any named files before the ledger. It hard-links the original ledger to the backup and then replaces the ledger in one atomic step. A rerun therefore finishes the work, skips files already moved, and never maps an id twice. + +A named file left half-done shows as modified. Restore it with `git checkout -- FILE` before you rerun. + +## Finding an old id + +```sh +docket list --where was:ID +``` + +This finds the record that carried an old id, retired records included. It matches `migrated_from`, or a schema 1 record's `legacy.source_id`. + +`docket show ID` for an id that no longer exists points at that search. An old id that is also a current id resolves to the current record. diff --git a/hooks/guard_ledger.py b/hooks/guard_ledger.py index 6ad410d..d388247 100755 --- a/hooks/guard_ledger.py +++ b/hooks/guard_ledger.py @@ -24,7 +24,9 @@ import time from pathlib import Path -LEDGER_SUFFIXES = (".jsonl", ".jsonl.schema1", ".json") +# migrate keeps the original at ledger.jsonl.schemaN, N the starting version, +# so a fixed suffix list goes stale with every schema bump. +LEDGER_NAME = re.compile(r"\.(?:jsonl(?:\.schema[0-9]+)?|json)$") # Allowlist, because a command string cannot be read for intent. Anything that # names a ledger and is not on this list gets the prompt, including every @@ -158,7 +160,7 @@ def is_ledger(path: str, cwd: str) -> bool: # pattern it never spells out, as `find .docket -name 'ledger.jsonl'` does. if name == ".docket": return True - if not name.endswith(LEDGER_SUFFIXES): + if not LEDGER_NAME.search(name): return False if ".docket" in resolved.parts: return True diff --git a/skills/docket/SKILL.md b/skills/docket/SKILL.md index 2646f75..e2c960b 100644 --- a/skills/docket/SKILL.md +++ b/skills/docket/SKILL.md @@ -5,7 +5,7 @@ description: Use when making a design choice, relying on a premise that may need # docket -Docket is an append-only schema 2 ledger of typed claims, decisions, and questions that survives conversation compaction. Read the current context before starting work. Run docket by the absolute command path on the `# command:` line of the briefing header; the examples say `docket`. +Docket is an append-only ledger of typed claims, decisions, and questions that survives conversation compaction. Read the current context before starting work. Run docket by the absolute command path on the `# command:` line of the briefing header; the examples say `docket`. ## Record types and states @@ -120,7 +120,7 @@ Work the briefing in this order: A delegated agent runs step 3 for its own scope and reports the revision it used, so the delegator knows which briefing the work rests on. -`list` and `graph` accept `--kind`, `--state`, and `--where QUERY`, which combines words with `kind:`, `state:`, `scope:PATH`, `is:pinned`, `is:retired`, `author:`, and `after:YYYY-MM-DD`; see [the query language](../../docs/commands.md#query-language). `scope:PATH` asks which records govern that file; `scope:DIR/` covers a directory. +`list` and `graph` accept `--kind`, `--state`, and `--where QUERY`, which combines words with `kind:`, `state:`, `scope:PATH`, `is:pinned`, `is:retired`, `author:`, `after:YYYY-MM-DD`, and `was:ID`, which finds a record by the ID it had before a migration; see [the query language](../../docs/commands.md#query-language). `scope:PATH` asks which records govern that file; `scope:DIR/` covers a directory. `list --json` prints every field of every record, which is large: pass `--fields id,kind,state,text` for what you need. It and `show --json` drop the schema 1 `legacy` field unless you pass `--legacy`. See [the JSON shapes](../../docs/commands.md#json-shapes) for derived fields such as `recorded_state`, `applicable`, and `blocked_by`. @@ -130,5 +130,5 @@ Evidence is recorder-supplied provenance; docket does not check it. Re-run `dock - Graph export and `graph --web`, for a person to read: [reading your ledger](../../docs/reading.md#export-the-graph). - Ledger location, `docket init`, `DOCKET_HOME`: [environment](../../docs/environment.md). -- A schema 1 ledger needs `docket migrate`; never guess record types from prose. [Migrating](../../docs/ledger.md#migrating-a-schema-1-ledger). +- A ledger older than this docket needs `docket migrate`; add `--rewrite FILE...` for tracked, clean files that cite ledger IDs, and never guess record types from prose. After a migration an old ID can name a different record: `docket list --where was:ID` finds the record that carried it. [Migrating](../../docs/ledger.md#migrating-to-schema-3). - An unreadable ledger: `docket check`. A git conflict after two branches both recorded: `docket rebase OTHER --dry-run`, never a hand edit. Two branches that decided one question differently leave two adopted decisions; supersede one. [Sharing and maintenance](../../docs/maintenance.md). diff --git a/tests/golden/context_snapshots.json b/tests/golden/context_snapshots.json index 6568096..a6d1ec9 100644 --- a/tests/golden/context_snapshots.json +++ b/tests/golden/context_snapshots.json @@ -1,38 +1,38 @@ { -"n5_qnone_fno_b900": "# docket: repo | revision: e41bec7c6101 | latest: q5@e41bec7c6101\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n### q5 | question | open [selected]\ntext: Record q5 about module 5\nscope: [\"lib/mod5/**\"]\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### q2 | question | open [selected]\ntext: Record q2 about module 2\nscope: [\"lib/mod2/**\"]\n\n# index: 2 more current records\nc4 claim unassessed Record c4 about module 4\nc1 claim unassessed Record c1 about module 1\n\n# full text: 3; index: 2; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n5_qnone_fno_b8000": "# docket: repo | revision: e41bec7c6101 | latest: q5@e41bec7c6101\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n### q5 | question | open [selected]\ntext: Record q5 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c4 | claim | unassessed [selected]\ntext: Record c4 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### q2 | question | open [selected]\ntext: Record q2 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c1 | claim | unassessed [selected]\ntext: Record c1 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# full text: 5; index: 0; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n5_qnone_fno_bdefault": "# docket: repo | revision: e41bec7c6101 | latest: q5@e41bec7c6101\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n### q5 | question | open [selected]\ntext: Record q5 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c4 | claim | unassessed [selected]\ntext: Record c4 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### q2 | question | open [selected]\ntext: Record q2 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c1 | claim | unassessed [selected]\ntext: Record c1 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# full text: 5; index: 0; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n5_qmodule 3_fno_b900": "# docket: repo | revision: e41bec7c6101 | latest: q5@e41bec7c6101\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### q5 | question | open [selected]\ntext: Record q5 about module 5\nscope: [\"lib/mod5/**\"]\n\n### q2 | question | open [selected]\ntext: Record q2 about module 2\nscope: [\"lib/mod2/**\"]\n\n# index: 2 more current records\nc4 claim unassessed Record c4 about module 4\nc1 claim unassessed Record c1 about module 1\n\n# full text: 3; index: 2; retired: 0.\n# Coverage: partial, 2 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n5_qmodule 3_fno_b8000": "# docket: repo | revision: e41bec7c6101 | latest: q5@e41bec7c6101\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### q5 | question | open [selected]\ntext: Record q5 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c4 | claim | unassessed [selected]\ntext: Record c4 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q2 | question | open [selected]\ntext: Record q2 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c1 | claim | unassessed [selected]\ntext: Record c1 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# full text: 5; index: 0; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n5_qmodule 3_fno_bdefault": "# docket: repo | revision: e41bec7c6101 | latest: q5@e41bec7c6101\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### q5 | question | open [selected]\ntext: Record q5 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c4 | claim | unassessed [selected]\ntext: Record c4 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q2 | question | open [selected]\ntext: Record q2 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c1 | claim | unassessed [selected]\ntext: Record c1 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# full text: 5; index: 0; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n5_qnone_fyes_b900": "# docket: repo | revision: e41bec7c6101 | latest: q5@e41bec7c6101\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n# index: 4 more current records\nq5 question open Record q5 about module 5\nc4 claim unassessed Record c4 about module 4\nq2 question open Record q2 about module 2\nc1 claim unassessed Record c1 about module 1\n\n# full text: 1; index: 4; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n5_qnone_fyes_b8000": "# docket: repo | revision: e41bec7c6101 | latest: q5@e41bec7c6101\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n# index: 4 more current records\nq5 question open Record q5 about module 5\nc4 claim unassessed Record c4 about module 4\nq2 question open Record q2 about module 2\nc1 claim unassessed Record c1 about module 1\n\n# full text: 1; index: 4; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n5_qnone_fyes_bdefault": "# docket: repo | revision: e41bec7c6101 | latest: q5@e41bec7c6101\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n# index: 4 more current records\nq5 question open Record q5 about module 5\nc4 claim unassessed Record c4 about module 4\nq2 question open Record q2 about module 2\nc1 claim unassessed Record c1 about module 1\n\n# full text: 1; index: 4; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n60_qnone_fno_b900": "# docket: repo | revision: 625d1cadda38 | latest: d60@625d1cadda38\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n# index: d60, q59, c58, d57, q56, c55, d54, q53, c52, d51, q50, c49, d48, d18, q47, c46, d45, q44, c43, d42, q41, c40, d39, q38, c37, d36, q35, c34, c4, d33, q32, c31, c16, d30, q29, c28, d27, q26, c25, d24\n# and 20 more; docket list\n\n# full text: 0; index: 40; retired: 0.\n# Not listed: 20; reach them with docket list.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n60_qnone_fno_b8000": "# docket: repo | revision: 625d1cadda38 | latest: d60@625d1cadda38\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n### d60 | decision | adopted [selected]\ntext: Record d60 about module 4\nchoice: Choice 60\napplicable: false\nblocked_by: [\"d6\", \"c4\"]\nblocked: d6 -> c4 unassessed\nscope: [\"lib/mod4/**\"]\ndepends_on: [\"d6\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q59 | question | open [selected]\ntext: Record q59 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c58 | claim | unassessed [selected]\ntext: Record c58 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d57 | decision | adopted [selected]\ntext: Record d57 about module 1\nchoice: Choice 57\napplicable: false\nblocked_by: [\"c4\"]\nblocked: c4 unassessed\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"c4\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q56 | question | open [selected]\ntext: Record q56 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c55 | claim | unassessed [selected]\ntext: Record c55 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d54 | decision | adopted [selected]\ntext: Record d54 about module 5\nchoice: Choice 54\nscope: [\"lib/mod5/**\"]\n\n### q53 | question | open [selected]\ntext: Record q53 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c52 | claim | unassessed [selected]\ntext: Record c52 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d51 | decision | adopted [selected]\ntext: Record d51 about module 2\nchoice: Choice 51\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"d18\"]\n\n### q50 | question | open [selected]\ntext: Record q50 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c49 | claim | unassessed [selected]\ntext: Record c49 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d48 | decision | adopted [selected]\ntext: Record d48 about module 6\nchoice: Choice 48\nscope: [\"lib/mod6/**\"]\n\n### d18 | decision | adopted [selected]\ntext: Record d18 about module 4\nchoice: Choice 18\nscope: [\"lib/mod4/**\"]\n\n### q47 | question | open [selected]\ntext: Record q47 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c46 | claim | unassessed [selected]\ntext: Record c46 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d45 | decision | adopted [selected]\ntext: Record d45 about module 3\nchoice: Choice 45\nscope: [\"lib/mod3/**\"]\n\n### q44 | question | open [selected]\ntext: Record q44 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c43 | claim | unassessed [selected]\ntext: Record c43 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d42 | decision | adopted [selected]\ntext: Record d42 about module 0\nchoice: Choice 42\nscope: [\"lib/mod0/**\"]\n\n### q41 | question | open [selected]\ntext: Record q41 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c40 | claim | unassessed [selected]\ntext: Record c40 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d39 | decision | adopted [selected]\ntext: Record d39 about module 4\nchoice: Choice 39\nscope: [\"lib/mod4/**\"]\n\n### q38 | question | open [selected]\ntext: Record q38 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c37 | claim | unassessed [selected]\ntext: Record c37 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d36 | decision | adopted [selected]\ntext: Record d36 about module 1\nchoice: Choice 36\nscope: [\"lib/mod1/**\"]\n\n### q35 | question | open [selected]\ntext: Record q35 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c34 | claim | unassessed [selected]\ntext: Record c34 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c4 | claim | unassessed [selected]\ntext: Record c4 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d33 | decision | adopted [selected]\ntext: Record d33 about module 5\nchoice: Choice 33\nscope: [\"lib/mod5/**\"]\ndepends_on: [\"d9\"]\n\n### q32 | question | open [selected]\ntext: Record q32 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c31 | claim | unassessed [selected]\ntext: Record c31 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c16 | claim | unassessed [selected]\ntext: Record c16 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d30 | decision | adopted [selected]\ntext: Record d30 about module 2\nchoice: Choice 30\nscope: [\"lib/mod2/**\"]\n\n### q29 | question | open [selected]\ntext: Record q29 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c28 | claim | unassessed [selected]\ntext: Record c28 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d27 | decision | adopted [selected]\ntext: Record d27 about module 6\nchoice: Choice 27\nscope: [\"lib/mod6/**\"]\n\n### q26 | question | open [selected]\ntext: Record q26 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c25 | claim | unassessed [selected]\ntext: Record c25 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d24 | decision | adopted [selected]\ntext: Record d24 about module 3\nchoice: Choice 24\napplicable: false\nblocked_by: [\"c16\"]\nblocked: c16 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c16\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### d9 | decision | adopted [selected]\ntext: Record d9 about module 2\nchoice: Choice 9\nscope: [\"lib/mod2/**\"]\n\n### q23 | question | open [selected]\ntext: Record q23 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c22 | claim | unassessed [selected]\ntext: Record c22 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d21 | decision | adopted [selected]\ntext: Record d21 about module 0\nchoice: Choice 21\nscope: [\"lib/mod0/**\"]\ndepends_on: [\"d18\"]\n\n### d6 | decision | adopted [selected]\ntext: Record d6 about module 6\nchoice: Choice 6\napplicable: false\nblocked_by: [\"c4\"]\nblocked: c4 unassessed\nscope: [\"lib/mod6/**\"]\ndepends_on: [\"c4\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q20 | question | open [selected]\ntext: Record q20 about module 6\nscope: [\"lib/mod6/**\"]\n\n### q17 | question | open [selected]\ntext: Record q17 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d15 | decision | adopted [selected]\ntext: Record d15 about module 1\nchoice: Choice 15\nscope: [\"lib/mod1/**\"]\n\n# index: 12 more current records\nc19 claim unassessed Record c19 about module 5\nq14 question open Record q14 about module 0\nc13 claim unassessed Record c13 about module 6\nd12 decision adopted Record d12 about module 5\nq11 question open Record q11 about module 4\nc10 claim unassessed Record c10 about module 3\nq8 question open Record q8 about module 1\nc7 claim unassessed Record c7 about module 0\nq5 question open Record q5 about module 5\nd3 decision adopted Record d3 about module 3\nq2 question open Record q2 about module 2\nc1 claim unassessed Record c1 about module 1\n\n# full text: 48; index: 12; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n60_qnone_fno_bdefault": "# docket: repo | revision: 625d1cadda38 | latest: d60@625d1cadda38\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n### d60 | decision | adopted [selected]\ntext: Record d60 about module 4\nchoice: Choice 60\napplicable: false\nblocked_by: [\"d6\", \"c4\"]\nblocked: d6 -> c4 unassessed\nscope: [\"lib/mod4/**\"]\ndepends_on: [\"d6\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q59 | question | open [selected]\ntext: Record q59 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c58 | claim | unassessed [selected]\ntext: Record c58 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d57 | decision | adopted [selected]\ntext: Record d57 about module 1\nchoice: Choice 57\napplicable: false\nblocked_by: [\"c4\"]\nblocked: c4 unassessed\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"c4\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q56 | question | open [selected]\ntext: Record q56 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c55 | claim | unassessed [selected]\ntext: Record c55 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d54 | decision | adopted [selected]\ntext: Record d54 about module 5\nchoice: Choice 54\nscope: [\"lib/mod5/**\"]\n\n### q53 | question | open [selected]\ntext: Record q53 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c52 | claim | unassessed [selected]\ntext: Record c52 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d51 | decision | adopted [selected]\ntext: Record d51 about module 2\nchoice: Choice 51\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"d18\"]\n\n### q50 | question | open [selected]\ntext: Record q50 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c49 | claim | unassessed [selected]\ntext: Record c49 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d48 | decision | adopted [selected]\ntext: Record d48 about module 6\nchoice: Choice 48\nscope: [\"lib/mod6/**\"]\n\n### d18 | decision | adopted [selected]\ntext: Record d18 about module 4\nchoice: Choice 18\nscope: [\"lib/mod4/**\"]\n\n### q47 | question | open [selected]\ntext: Record q47 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c46 | claim | unassessed [selected]\ntext: Record c46 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d45 | decision | adopted [selected]\ntext: Record d45 about module 3\nchoice: Choice 45\nscope: [\"lib/mod3/**\"]\n\n### q44 | question | open [selected]\ntext: Record q44 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c43 | claim | unassessed [selected]\ntext: Record c43 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d42 | decision | adopted [selected]\ntext: Record d42 about module 0\nchoice: Choice 42\nscope: [\"lib/mod0/**\"]\n\n### q41 | question | open [selected]\ntext: Record q41 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c40 | claim | unassessed [selected]\ntext: Record c40 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d39 | decision | adopted [selected]\ntext: Record d39 about module 4\nchoice: Choice 39\nscope: [\"lib/mod4/**\"]\n\n### q38 | question | open [selected]\ntext: Record q38 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c37 | claim | unassessed [selected]\ntext: Record c37 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d36 | decision | adopted [selected]\ntext: Record d36 about module 1\nchoice: Choice 36\nscope: [\"lib/mod1/**\"]\n\n### q35 | question | open [selected]\ntext: Record q35 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c34 | claim | unassessed [selected]\ntext: Record c34 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c4 | claim | unassessed [selected]\ntext: Record c4 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d33 | decision | adopted [selected]\ntext: Record d33 about module 5\nchoice: Choice 33\nscope: [\"lib/mod5/**\"]\ndepends_on: [\"d9\"]\n\n### q32 | question | open [selected]\ntext: Record q32 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c31 | claim | unassessed [selected]\ntext: Record c31 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c16 | claim | unassessed [selected]\ntext: Record c16 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d30 | decision | adopted [selected]\ntext: Record d30 about module 2\nchoice: Choice 30\nscope: [\"lib/mod2/**\"]\n\n### q29 | question | open [selected]\ntext: Record q29 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c28 | claim | unassessed [selected]\ntext: Record c28 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d27 | decision | adopted [selected]\ntext: Record d27 about module 6\nchoice: Choice 27\nscope: [\"lib/mod6/**\"]\n\n### q26 | question | open [selected]\ntext: Record q26 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c25 | claim | unassessed [selected]\ntext: Record c25 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d24 | decision | adopted [selected]\ntext: Record d24 about module 3\nchoice: Choice 24\napplicable: false\nblocked_by: [\"c16\"]\nblocked: c16 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c16\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### d9 | decision | adopted [selected]\ntext: Record d9 about module 2\nchoice: Choice 9\nscope: [\"lib/mod2/**\"]\n\n### q23 | question | open [selected]\ntext: Record q23 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c22 | claim | unassessed [selected]\ntext: Record c22 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d21 | decision | adopted [selected]\ntext: Record d21 about module 0\nchoice: Choice 21\nscope: [\"lib/mod0/**\"]\ndepends_on: [\"d18\"]\n\n### d6 | decision | adopted [selected]\ntext: Record d6 about module 6\nchoice: Choice 6\napplicable: false\nblocked_by: [\"c4\"]\nblocked: c4 unassessed\nscope: [\"lib/mod6/**\"]\ndepends_on: [\"c4\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q20 | question | open [selected]\ntext: Record q20 about module 6\nscope: [\"lib/mod6/**\"]\n\n### q17 | question | open [selected]\ntext: Record q17 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d15 | decision | adopted [selected]\ntext: Record d15 about module 1\nchoice: Choice 15\nscope: [\"lib/mod1/**\"]\n\n# index: 12 more current records\nc19 claim unassessed Record c19 about module 5\nq14 question open Record q14 about module 0\nc13 claim unassessed Record c13 about module 6\nd12 decision adopted Record d12 about module 5\nq11 question open Record q11 about module 4\nc10 claim unassessed Record c10 about module 3\nq8 question open Record q8 about module 1\nc7 claim unassessed Record c7 about module 0\nq5 question open Record q5 about module 5\nd3 decision adopted Record d3 about module 3\nq2 question open Record q2 about module 2\nc1 claim unassessed Record c1 about module 1\n\n# full text: 48; index: 12; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n60_qmodule 3_fno_b900": "# docket: repo | revision: 625d1cadda38 | latest: d60@625d1cadda38\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n# index: q59, c52, d45, q38, c31, d24, q17, c10, d3, q53, c43, d39, c37, d36, q35, c34, d33, q32, d30, q23, c13, d60, c58, d57, q56, c55, d54, d51, q50, c49, d48, d18, q47, c46, q44, d42, q41, c40, c4, c16\n# and 20 more; docket list\n\n# full text: 0; index: 40; retired: 0.\n# Not listed: 20; reach them with docket list.\n# Coverage: partial, 60 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n60_qmodule 3_fno_b8000": "# docket: repo | revision: 625d1cadda38 | latest: d60@625d1cadda38\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n### q59 | question | open [selected]\ntext: Record q59 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c52 | claim | unassessed [selected]\ntext: Record c52 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d45 | decision | adopted [selected]\ntext: Record d45 about module 3\nchoice: Choice 45\nscope: [\"lib/mod3/**\"]\n\n### q38 | question | open [selected]\ntext: Record q38 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c31 | claim | unassessed [selected]\ntext: Record c31 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d24 | decision | adopted [selected]\ntext: Record d24 about module 3\nchoice: Choice 24\napplicable: false\nblocked_by: [\"c16\"]\nblocked: c16 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c16\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q17 | question | open [selected]\ntext: Record q17 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c10 | claim | unassessed [selected]\ntext: Record c10 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### q53 | question | open [selected]\ntext: Record q53 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c43 | claim | unassessed [selected]\ntext: Record c43 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d39 | decision | adopted [selected]\ntext: Record d39 about module 4\nchoice: Choice 39\nscope: [\"lib/mod4/**\"]\n\n### c37 | claim | unassessed [selected]\ntext: Record c37 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d36 | decision | adopted [selected]\ntext: Record d36 about module 1\nchoice: Choice 36\nscope: [\"lib/mod1/**\"]\n\n### q35 | question | open [selected]\ntext: Record q35 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c34 | claim | unassessed [selected]\ntext: Record c34 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d33 | decision | adopted [selected]\ntext: Record d33 about module 5\nchoice: Choice 33\nscope: [\"lib/mod5/**\"]\ndepends_on: [\"d9\"]\n\n### q32 | question | open [selected]\ntext: Record q32 about module 4\nscope: [\"lib/mod4/**\"]\n\n### d30 | decision | adopted [selected]\ntext: Record d30 about module 2\nchoice: Choice 30\nscope: [\"lib/mod2/**\"]\n\n### q23 | question | open [selected]\ntext: Record q23 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c13 | claim | unassessed [selected]\ntext: Record c13 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d60 | decision | adopted [selected]\ntext: Record d60 about module 4\nchoice: Choice 60\napplicable: false\nblocked_by: [\"d6\", \"c4\"]\nblocked: d6 -> c4 unassessed\nscope: [\"lib/mod4/**\"]\ndepends_on: [\"d6\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c58 | claim | unassessed [selected]\ntext: Record c58 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d57 | decision | adopted [selected]\ntext: Record d57 about module 1\nchoice: Choice 57\napplicable: false\nblocked_by: [\"c4\"]\nblocked: c4 unassessed\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"c4\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q56 | question | open [selected]\ntext: Record q56 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c55 | claim | unassessed [selected]\ntext: Record c55 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d54 | decision | adopted [selected]\ntext: Record d54 about module 5\nchoice: Choice 54\nscope: [\"lib/mod5/**\"]\n\n### d51 | decision | adopted [selected]\ntext: Record d51 about module 2\nchoice: Choice 51\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"d18\"]\n\n### q50 | question | open [selected]\ntext: Record q50 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c49 | claim | unassessed [selected]\ntext: Record c49 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d48 | decision | adopted [selected]\ntext: Record d48 about module 6\nchoice: Choice 48\nscope: [\"lib/mod6/**\"]\n\n### d18 | decision | adopted [selected]\ntext: Record d18 about module 4\nchoice: Choice 18\nscope: [\"lib/mod4/**\"]\n\n### q47 | question | open [selected]\ntext: Record q47 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c46 | claim | unassessed [selected]\ntext: Record c46 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q44 | question | open [selected]\ntext: Record q44 about module 2\nscope: [\"lib/mod2/**\"]\n\n### d42 | decision | adopted [selected]\ntext: Record d42 about module 0\nchoice: Choice 42\nscope: [\"lib/mod0/**\"]\n\n### q41 | question | open [selected]\ntext: Record q41 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c40 | claim | unassessed [selected]\ntext: Record c40 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c4 | claim | unassessed [selected]\ntext: Record c4 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c16 | claim | unassessed [selected]\ntext: Record c16 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q29 | question | open [selected]\ntext: Record q29 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c28 | claim | unassessed [selected]\ntext: Record c28 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d27 | decision | adopted [selected]\ntext: Record d27 about module 6\nchoice: Choice 27\nscope: [\"lib/mod6/**\"]\n\n### q26 | question | open [selected]\ntext: Record q26 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c25 | claim | unassessed [selected]\ntext: Record c25 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d9 | decision | adopted [selected]\ntext: Record d9 about module 2\nchoice: Choice 9\nscope: [\"lib/mod2/**\"]\n\n### c22 | claim | unassessed [selected]\ntext: Record c22 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# index: 13 more current records\nd21 decision adopted Record d21 about module 0\nd6 decision adopted Record d6 about module 6\nq20 question open Record q20 about module 6\nc19 claim unassessed Record c19 about module 5\nd15 decision adopted Record d15 about module 1\nq14 question open Record q14 about module 0\nd12 decision adopted Record d12 about module 5\nq11 question open Record q11 about module 4\nq8 question open Record q8 about module 1\nc7 claim unassessed Record c7 about module 0\nq5 question open Record q5 about module 5\nq2 question open Record q2 about module 2\nc1 claim unassessed Record c1 about module 1\n\n# full text: 47; index: 13; retired: 0.\n# Related records in index only: 1; formulas remain complete.\n# Coverage: partial, 13 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n60_qmodule 3_fno_bdefault": "# docket: repo | revision: 625d1cadda38 | latest: d60@625d1cadda38\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n### q59 | question | open [selected]\ntext: Record q59 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c52 | claim | unassessed [selected]\ntext: Record c52 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d45 | decision | adopted [selected]\ntext: Record d45 about module 3\nchoice: Choice 45\nscope: [\"lib/mod3/**\"]\n\n### q38 | question | open [selected]\ntext: Record q38 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c31 | claim | unassessed [selected]\ntext: Record c31 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d24 | decision | adopted [selected]\ntext: Record d24 about module 3\nchoice: Choice 24\napplicable: false\nblocked_by: [\"c16\"]\nblocked: c16 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c16\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q17 | question | open [selected]\ntext: Record q17 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c10 | claim | unassessed [selected]\ntext: Record c10 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### q53 | question | open [selected]\ntext: Record q53 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c43 | claim | unassessed [selected]\ntext: Record c43 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d39 | decision | adopted [selected]\ntext: Record d39 about module 4\nchoice: Choice 39\nscope: [\"lib/mod4/**\"]\n\n### c37 | claim | unassessed [selected]\ntext: Record c37 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d36 | decision | adopted [selected]\ntext: Record d36 about module 1\nchoice: Choice 36\nscope: [\"lib/mod1/**\"]\n\n### q35 | question | open [selected]\ntext: Record q35 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c34 | claim | unassessed [selected]\ntext: Record c34 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d33 | decision | adopted [selected]\ntext: Record d33 about module 5\nchoice: Choice 33\nscope: [\"lib/mod5/**\"]\ndepends_on: [\"d9\"]\n\n### q32 | question | open [selected]\ntext: Record q32 about module 4\nscope: [\"lib/mod4/**\"]\n\n### d30 | decision | adopted [selected]\ntext: Record d30 about module 2\nchoice: Choice 30\nscope: [\"lib/mod2/**\"]\n\n### q23 | question | open [selected]\ntext: Record q23 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c13 | claim | unassessed [selected]\ntext: Record c13 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d60 | decision | adopted [selected]\ntext: Record d60 about module 4\nchoice: Choice 60\napplicable: false\nblocked_by: [\"d6\", \"c4\"]\nblocked: d6 -> c4 unassessed\nscope: [\"lib/mod4/**\"]\ndepends_on: [\"d6\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c58 | claim | unassessed [selected]\ntext: Record c58 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d57 | decision | adopted [selected]\ntext: Record d57 about module 1\nchoice: Choice 57\napplicable: false\nblocked_by: [\"c4\"]\nblocked: c4 unassessed\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"c4\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q56 | question | open [selected]\ntext: Record q56 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c55 | claim | unassessed [selected]\ntext: Record c55 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d54 | decision | adopted [selected]\ntext: Record d54 about module 5\nchoice: Choice 54\nscope: [\"lib/mod5/**\"]\n\n### d51 | decision | adopted [selected]\ntext: Record d51 about module 2\nchoice: Choice 51\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"d18\"]\n\n### q50 | question | open [selected]\ntext: Record q50 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c49 | claim | unassessed [selected]\ntext: Record c49 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d48 | decision | adopted [selected]\ntext: Record d48 about module 6\nchoice: Choice 48\nscope: [\"lib/mod6/**\"]\n\n### d18 | decision | adopted [selected]\ntext: Record d18 about module 4\nchoice: Choice 18\nscope: [\"lib/mod4/**\"]\n\n### q47 | question | open [selected]\ntext: Record q47 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c46 | claim | unassessed [selected]\ntext: Record c46 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q44 | question | open [selected]\ntext: Record q44 about module 2\nscope: [\"lib/mod2/**\"]\n\n### d42 | decision | adopted [selected]\ntext: Record d42 about module 0\nchoice: Choice 42\nscope: [\"lib/mod0/**\"]\n\n### q41 | question | open [selected]\ntext: Record q41 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c40 | claim | unassessed [selected]\ntext: Record c40 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c4 | claim | unassessed [selected]\ntext: Record c4 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c16 | claim | unassessed [selected]\ntext: Record c16 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q29 | question | open [selected]\ntext: Record q29 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c28 | claim | unassessed [selected]\ntext: Record c28 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d27 | decision | adopted [selected]\ntext: Record d27 about module 6\nchoice: Choice 27\nscope: [\"lib/mod6/**\"]\n\n### q26 | question | open [selected]\ntext: Record q26 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c25 | claim | unassessed [selected]\ntext: Record c25 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d9 | decision | adopted [selected]\ntext: Record d9 about module 2\nchoice: Choice 9\nscope: [\"lib/mod2/**\"]\n\n### c22 | claim | unassessed [selected]\ntext: Record c22 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d21 | decision | adopted [selected]\ntext: Record d21 about module 0\nchoice: Choice 21\nscope: [\"lib/mod0/**\"]\ndepends_on: [\"d18\"]\n\n### d6 | decision | adopted [selected]\ntext: Record d6 about module 6\nchoice: Choice 6\napplicable: false\nblocked_by: [\"c4\"]\nblocked: c4 unassessed\nscope: [\"lib/mod6/**\"]\ndepends_on: [\"c4\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q20 | question | open [selected]\ntext: Record q20 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c19 | claim | unassessed [selected]\ntext: Record c19 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d15 | decision | adopted [selected]\ntext: Record d15 about module 1\nchoice: Choice 15\nscope: [\"lib/mod1/**\"]\n\n### q14 | question | open [selected]\ntext: Record q14 about module 0\nscope: [\"lib/mod0/**\"]\n\n### d12 | decision | adopted [selected]\ntext: Record d12 about module 5\nchoice: Choice 12\nscope: [\"lib/mod5/**\"]\n\n### q11 | question | open [selected]\ntext: Record q11 about module 4\nscope: [\"lib/mod4/**\"]\n\n### q8 | question | open [selected]\ntext: Record q8 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c7 | claim | unassessed [selected]\ntext: Record c7 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q5 | question | open [selected]\ntext: Record q5 about module 5\nscope: [\"lib/mod5/**\"]\n\n### q2 | question | open [selected]\ntext: Record q2 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c1 | claim | unassessed [selected]\ntext: Record c1 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# full text: 60; index: 0; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n60_qnone_fyes_b900": "# docket: repo | revision: 625d1cadda38 | latest: d60@625d1cadda38\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n# index: q59, c52, d45, q38, c31, d24, q17, c10, d3, d60, c58, d57, q56, c55, d54, q53, d51, q50, c49, d48, d18, q47, c46, q44, c43, d42, q41, c40, d39, c37, d36, q35, c34, c4, d33, q32, c16, d30, q29, c28\n# and 20 more; docket list\n\n# full text: 0; index: 40; retired: 0.\n# Not listed: 20; reach them with docket list.\n# Coverage: partial, 9 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n60_qnone_fyes_b8000": "# docket: repo | revision: 625d1cadda38 | latest: d60@625d1cadda38\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n### q59 | question | open [selected]\ntext: Record q59 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c52 | claim | unassessed [selected]\ntext: Record c52 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d45 | decision | adopted [selected]\ntext: Record d45 about module 3\nchoice: Choice 45\nscope: [\"lib/mod3/**\"]\n\n### q38 | question | open [selected]\ntext: Record q38 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c31 | claim | unassessed [selected]\ntext: Record c31 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d24 | decision | adopted [selected]\ntext: Record d24 about module 3\nchoice: Choice 24\napplicable: false\nblocked_by: [\"c16\"]\nblocked: c16 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c16\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q17 | question | open [selected]\ntext: Record q17 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c10 | claim | unassessed [selected]\ntext: Record c10 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### c16 | claim | unassessed [blocking prerequisite]\ntext: Record c16 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# index: 40 more current records\nd60 decision adopted Record d60 about module 4\nc58 claim unassessed Record c58 about module 2\nd57 decision adopted Record d57 about module 1\nq56 question open Record q56 about module 0\nc55 claim unassessed Record c55 about module 6\nd54 decision adopted Record d54 about module 5\nq53 question open Record q53 about module 4\nd51 decision adopted Record d51 about module 2\nq50 question open Record q50 about module 1\nc49 claim unassessed Record c49 about module 0\nd48 decision adopted Record d48 about module 6\nd18 decision adopted Record d18 about module 4\nq47 question open Record q47 about module 5\nc46 claim unassessed Record c46 about module 4\nq44 question open Record q44 about module 2\nc43 claim unassessed Record c43 about module 1\nd42 decision adopted Record d42 about module 0\nq41 question open Record q41 about module 6\nc40 claim unassessed Record c40 about module 5\nd39 decision adopted Record d39 about module 4\nc37 claim unassessed Record c37 about module 2\nd36 decision adopted Record d36 about module 1\nq35 question open Record q35 about module 0\nc34 claim unassessed Record c34 about module 6\nc4 claim unassessed Record c4 about module 4\nd33 decision adopted Record d33 about module 5\nq32 question open Record q32 about module 4\nd30 decision adopted Record d30 about module 2\nq29 question open Record q29 about module 1\nc28 claim unassessed Record c28 about module 0\nd27 decision adopted Record d27 about module 6\nq26 question open Record q26 about module 5\nc25 claim unassessed Record c25 about module 4\nd9 decision adopted Record d9 about module 2\nq23 question open Record q23 about module 2\nc22 claim unassessed Record c22 about module 1\nd21 decision adopted Record d21 about module 0\nd6 decision adopted Record d6 about module 6\nq20 question open Record q20 about module 6\nc19 claim unassessed Record c19 about module 5\n# and 10 more; docket list\n\n# full text: 10; index: 40; retired: 0.\n# Not listed: 10; reach them with docket list.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n60_qnone_fyes_bdefault": "# docket: repo | revision: 625d1cadda38 | latest: d60@625d1cadda38\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n### q59 | question | open [selected]\ntext: Record q59 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c52 | claim | unassessed [selected]\ntext: Record c52 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d45 | decision | adopted [selected]\ntext: Record d45 about module 3\nchoice: Choice 45\nscope: [\"lib/mod3/**\"]\n\n### q38 | question | open [selected]\ntext: Record q38 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c31 | claim | unassessed [selected]\ntext: Record c31 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d24 | decision | adopted [selected]\ntext: Record d24 about module 3\nchoice: Choice 24\napplicable: false\nblocked_by: [\"c16\"]\nblocked: c16 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c16\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q17 | question | open [selected]\ntext: Record q17 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c10 | claim | unassessed [selected]\ntext: Record c10 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### c16 | claim | unassessed [blocking prerequisite]\ntext: Record c16 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# index: 40 more current records\nd60 decision adopted Record d60 about module 4\nc58 claim unassessed Record c58 about module 2\nd57 decision adopted Record d57 about module 1\nq56 question open Record q56 about module 0\nc55 claim unassessed Record c55 about module 6\nd54 decision adopted Record d54 about module 5\nq53 question open Record q53 about module 4\nd51 decision adopted Record d51 about module 2\nq50 question open Record q50 about module 1\nc49 claim unassessed Record c49 about module 0\nd48 decision adopted Record d48 about module 6\nd18 decision adopted Record d18 about module 4\nq47 question open Record q47 about module 5\nc46 claim unassessed Record c46 about module 4\nq44 question open Record q44 about module 2\nc43 claim unassessed Record c43 about module 1\nd42 decision adopted Record d42 about module 0\nq41 question open Record q41 about module 6\nc40 claim unassessed Record c40 about module 5\nd39 decision adopted Record d39 about module 4\nc37 claim unassessed Record c37 about module 2\nd36 decision adopted Record d36 about module 1\nq35 question open Record q35 about module 0\nc34 claim unassessed Record c34 about module 6\nc4 claim unassessed Record c4 about module 4\nd33 decision adopted Record d33 about module 5\nq32 question open Record q32 about module 4\nd30 decision adopted Record d30 about module 2\nq29 question open Record q29 about module 1\nc28 claim unassessed Record c28 about module 0\nd27 decision adopted Record d27 about module 6\nq26 question open Record q26 about module 5\nc25 claim unassessed Record c25 about module 4\nd9 decision adopted Record d9 about module 2\nq23 question open Record q23 about module 2\nc22 claim unassessed Record c22 about module 1\nd21 decision adopted Record d21 about module 0\nd6 decision adopted Record d6 about module 6\nq20 question open Record q20 about module 6\nc19 claim unassessed Record c19 about module 5\n# and 10 more; docket list\n\n# full text: 10; index: 40; retired: 0.\n# Not listed: 10; reach them with docket list.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n400_qnone_fno_b900": "# docket: repo | revision: 920de186cdd4 | latest: c400@920de186cdd4\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n# index: d147, c400, d399, c199, q398, c397, d396, q395, c394, d393, q392, c391, d390, q389, c388, d387, q386, c385, d384, q383, c382, d381, q380, c379, d378, q377, c376, d375, q374, c373, d372, q371, c370, d369, q368, c367, d366, q365, c364, d363\n# and 360 more; docket list\n\n# full text: 0; index: 40; retired: 0.\n# Not listed: 360; reach them with docket list.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n400_qnone_fno_b8000": "# docket: repo | revision: 920de186cdd4 | latest: c400@920de186cdd4\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n### d147 | decision | adopted [selected]\ntext: Record d147 about module 0\nchoice: Choice 147\napplicable: false\nblocked_by: [\"c37\"]\nblocked: c37 unassessed\nscope: [\"lib/mod0/**\"]\ndepends_on: [\"c37\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c400 | claim | unassessed [selected]\ntext: Record c400 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d399 | decision | adopted [selected]\ntext: Record d399 about module 0\nchoice: Choice 399\nscope: [\"lib/mod0/**\"]\n\n### c199 | claim | unassessed [selected]\ntext: Record c199 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q398 | question | open [selected]\ntext: Record q398 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c397 | claim | unassessed [selected]\ntext: Record c397 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d396 | decision | adopted [selected]\ntext: Record d396 about module 4\nchoice: Choice 396\nscope: [\"lib/mod4/**\"]\n\n### q395 | question | open [selected]\ntext: Record q395 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c394 | claim | unassessed [selected]\ntext: Record c394 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d393 | decision | adopted [selected]\ntext: Record d393 about module 1\nchoice: Choice 393\nscope: [\"lib/mod1/**\"]\n\n### q392 | question | open [selected]\ntext: Record q392 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c391 | claim | unassessed [selected]\ntext: Record c391 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d390 | decision | adopted [selected]\ntext: Record d390 about module 5\nchoice: Choice 390\nscope: [\"lib/mod5/**\"]\n\n### q389 | question | open [selected]\ntext: Record q389 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c388 | claim | unassessed [selected]\ntext: Record c388 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d387 | decision | adopted [selected]\ntext: Record d387 about module 2\nchoice: Choice 387\nscope: [\"lib/mod2/**\"]\n\n### q386 | question | open [selected]\ntext: Record q386 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c385 | claim | unassessed [selected]\ntext: Record c385 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d384 | decision | adopted [selected]\ntext: Record d384 about module 6\nchoice: Choice 384\nscope: [\"lib/mod6/**\"]\n\n### q383 | question | open [selected]\ntext: Record q383 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c382 | claim | unassessed [selected]\ntext: Record c382 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d381 | decision | adopted [selected]\ntext: Record d381 about module 3\nchoice: Choice 381\nscope: [\"lib/mod3/**\"]\n\n### q380 | question | open [selected]\ntext: Record q380 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c379 | claim | unassessed [selected]\ntext: Record c379 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d378 | decision | adopted [selected]\ntext: Record d378 about module 0\nchoice: Choice 378\nscope: [\"lib/mod0/**\"]\n\n### q377 | question | open [selected]\ntext: Record q377 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c376 | claim | unassessed [selected]\ntext: Record c376 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d375 | decision | adopted [selected]\ntext: Record d375 about module 4\nchoice: Choice 375\nscope: [\"lib/mod4/**\"]\n\n### q374 | question | open [selected]\ntext: Record q374 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c373 | claim | unassessed [selected]\ntext: Record c373 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d372 | decision | adopted [selected]\ntext: Record d372 about module 1\nchoice: Choice 372\nscope: [\"lib/mod1/**\"]\n\n### q371 | question | open [selected]\ntext: Record q371 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c370 | claim | unassessed [selected]\ntext: Record c370 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d369 | decision | adopted [selected]\ntext: Record d369 about module 5\nchoice: Choice 369\napplicable: false\nblocked_by: [\"c109\"]\nblocked: c109 unassessed\nscope: [\"lib/mod5/**\"]\ndepends_on: [\"c109\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q368 | question | open [selected]\ntext: Record q368 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c367 | claim | unassessed [selected]\ntext: Record c367 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d366 | decision | adopted [selected]\ntext: Record d366 about module 2\nchoice: Choice 366\nscope: [\"lib/mod2/**\"]\n\n# index: 40 more current records\nq365 question open Record q365 about module 1\nc364 claim unassessed Record c364 about module 0\nd363 decision adopted Record d363 about module 6\nq362 question open Record q362 about module 5\nc361 claim unassessed Record c361 about module 4\nd360 decision adopted Record d360 about module 3\nq359 question open Record q359 about module 2\nc358 claim unassessed Record c358 about module 1\nd357 decision adopted Record d357 about module 0\nq356 question open Record q356 about module 6\nc355 claim unassessed Record c355 about module 5\nd255 decision adopted Record d255 about module 3\nd354 decision adopted Record d354 about module 4\nq353 question open Record q353 about module 3\nc352 claim unassessed Record c352 about module 2\nd351 decision adopted Record d351 about module 1\nq350 question open Record q350 about module 0\nc349 claim unassessed Record c349 about module 6\nd348 decision adopted Record d348 about module 5\nq347 question open Record q347 about module 4\nc346 claim unassessed Record c346 about module 3\nd345 decision adopted Record d345 about module 2\nq344 question open Record q344 about module 1\nc343 claim unassessed Record c343 about module 0\nd342 decision adopted Record d342 about module 6\nq341 question open Record q341 about module 5\nc340 claim unassessed Record c340 about module 4\nd339 decision adopted Record d339 about module 3\nd240 decision adopted Record d240 about module 2\nq338 question open Record q338 about module 2\nc337 claim unassessed Record c337 about module 1\nd336 decision adopted Record d336 about module 0\nq335 question open Record q335 about module 6\nc334 claim unassessed Record c334 about module 5\nd333 decision adopted Record d333 about module 4\nq332 question open Record q332 about module 3\nc331 claim unassessed Record c331 about module 2\nd330 decision adopted Record d330 about module 1\nq329 question open Record q329 about module 0\nc328 claim unassessed Record c328 about module 6\n# and 323 more; docket list\n\n# full text: 37; index: 40; retired: 0.\n# Not listed: 323; reach them with docket list.\n# Related records in index only: 2; formulas remain complete.\n# Coverage: partial, 2 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n400_qnone_fno_bdefault": "# docket: repo | revision: 920de186cdd4 | latest: c400@920de186cdd4\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n### d147 | decision | adopted [selected]\ntext: Record d147 about module 0\nchoice: Choice 147\napplicable: false\nblocked_by: [\"c37\"]\nblocked: c37 unassessed\nscope: [\"lib/mod0/**\"]\ndepends_on: [\"c37\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c400 | claim | unassessed [selected]\ntext: Record c400 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d399 | decision | adopted [selected]\ntext: Record d399 about module 0\nchoice: Choice 399\nscope: [\"lib/mod0/**\"]\n\n### c199 | claim | unassessed [selected]\ntext: Record c199 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q398 | question | open [selected]\ntext: Record q398 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c397 | claim | unassessed [selected]\ntext: Record c397 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d396 | decision | adopted [selected]\ntext: Record d396 about module 4\nchoice: Choice 396\nscope: [\"lib/mod4/**\"]\n\n### q395 | question | open [selected]\ntext: Record q395 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c394 | claim | unassessed [selected]\ntext: Record c394 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d393 | decision | adopted [selected]\ntext: Record d393 about module 1\nchoice: Choice 393\nscope: [\"lib/mod1/**\"]\n\n### q392 | question | open [selected]\ntext: Record q392 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c391 | claim | unassessed [selected]\ntext: Record c391 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d390 | decision | adopted [selected]\ntext: Record d390 about module 5\nchoice: Choice 390\nscope: [\"lib/mod5/**\"]\n\n### q389 | question | open [selected]\ntext: Record q389 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c388 | claim | unassessed [selected]\ntext: Record c388 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d387 | decision | adopted [selected]\ntext: Record d387 about module 2\nchoice: Choice 387\nscope: [\"lib/mod2/**\"]\n\n### q386 | question | open [selected]\ntext: Record q386 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c385 | claim | unassessed [selected]\ntext: Record c385 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d384 | decision | adopted [selected]\ntext: Record d384 about module 6\nchoice: Choice 384\nscope: [\"lib/mod6/**\"]\n\n### q383 | question | open [selected]\ntext: Record q383 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c382 | claim | unassessed [selected]\ntext: Record c382 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d381 | decision | adopted [selected]\ntext: Record d381 about module 3\nchoice: Choice 381\nscope: [\"lib/mod3/**\"]\n\n### q380 | question | open [selected]\ntext: Record q380 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c379 | claim | unassessed [selected]\ntext: Record c379 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d378 | decision | adopted [selected]\ntext: Record d378 about module 0\nchoice: Choice 378\nscope: [\"lib/mod0/**\"]\n\n### q377 | question | open [selected]\ntext: Record q377 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c376 | claim | unassessed [selected]\ntext: Record c376 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d375 | decision | adopted [selected]\ntext: Record d375 about module 4\nchoice: Choice 375\nscope: [\"lib/mod4/**\"]\n\n### q374 | question | open [selected]\ntext: Record q374 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c373 | claim | unassessed [selected]\ntext: Record c373 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d372 | decision | adopted [selected]\ntext: Record d372 about module 1\nchoice: Choice 372\nscope: [\"lib/mod1/**\"]\n\n### q371 | question | open [selected]\ntext: Record q371 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c370 | claim | unassessed [selected]\ntext: Record c370 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d369 | decision | adopted [selected]\ntext: Record d369 about module 5\nchoice: Choice 369\napplicable: false\nblocked_by: [\"c109\"]\nblocked: c109 unassessed\nscope: [\"lib/mod5/**\"]\ndepends_on: [\"c109\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q368 | question | open [selected]\ntext: Record q368 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c367 | claim | unassessed [selected]\ntext: Record c367 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d366 | decision | adopted [selected]\ntext: Record d366 about module 2\nchoice: Choice 366\nscope: [\"lib/mod2/**\"]\n\n# index: 40 more current records\nq365 question open Record q365 about module 1\nc364 claim unassessed Record c364 about module 0\nd363 decision adopted Record d363 about module 6\nq362 question open Record q362 about module 5\nc361 claim unassessed Record c361 about module 4\nd360 decision adopted Record d360 about module 3\nq359 question open Record q359 about module 2\nc358 claim unassessed Record c358 about module 1\nd357 decision adopted Record d357 about module 0\nq356 question open Record q356 about module 6\nc355 claim unassessed Record c355 about module 5\nd255 decision adopted Record d255 about module 3\nd354 decision adopted Record d354 about module 4\nq353 question open Record q353 about module 3\nc352 claim unassessed Record c352 about module 2\nd351 decision adopted Record d351 about module 1\nq350 question open Record q350 about module 0\nc349 claim unassessed Record c349 about module 6\nd348 decision adopted Record d348 about module 5\nq347 question open Record q347 about module 4\nc346 claim unassessed Record c346 about module 3\nd345 decision adopted Record d345 about module 2\nq344 question open Record q344 about module 1\nc343 claim unassessed Record c343 about module 0\nd342 decision adopted Record d342 about module 6\nq341 question open Record q341 about module 5\nc340 claim unassessed Record c340 about module 4\nd339 decision adopted Record d339 about module 3\nd240 decision adopted Record d240 about module 2\nq338 question open Record q338 about module 2\nc337 claim unassessed Record c337 about module 1\nd336 decision adopted Record d336 about module 0\nq335 question open Record q335 about module 6\nc334 claim unassessed Record c334 about module 5\nd333 decision adopted Record d333 about module 4\nq332 question open Record q332 about module 3\nc331 claim unassessed Record c331 about module 2\nd330 decision adopted Record d330 about module 1\nq329 question open Record q329 about module 0\nc328 claim unassessed Record c328 about module 6\n# and 323 more; docket list\n\n# full text: 37; index: 40; retired: 0.\n# Not listed: 323; reach them with docket list.\n# Related records in index only: 2; formulas remain complete.\n# Coverage: partial, 2 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n400_qmodule 3_fno_b900": "# docket: repo | revision: 920de186cdd4 | latest: c400@920de186cdd4\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n# index: c199, q395, c388, d381, q374, c367, d360, d255, q353, c346, d339, q332, c325, d318, q311, c304, d297, q290, c283, d276, d171, q269, c262, d150, q248, c241, d234, q227, c220, d213, q206, c94, d192, q185, c178, q164, c157, c52, q143, c136\n# and 360 more; docket list\n\n# full text: 0; index: 40; retired: 0.\n# Not listed: 360; reach them with docket list.\n# Coverage: partial, 400 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n400_qmodule 3_fno_b8000": "# docket: repo | revision: 920de186cdd4 | latest: c400@920de186cdd4\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n### c199 | claim | unassessed [selected]\ntext: Record c199 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q395 | question | open [selected]\ntext: Record q395 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c388 | claim | unassessed [selected]\ntext: Record c388 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d381 | decision | adopted [selected]\ntext: Record d381 about module 3\nchoice: Choice 381\nscope: [\"lib/mod3/**\"]\n\n### q374 | question | open [selected]\ntext: Record q374 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c367 | claim | unassessed [selected]\ntext: Record c367 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d360 | decision | adopted [selected]\ntext: Record d360 about module 3\nchoice: Choice 360\napplicable: false\nblocked_by: [\"d171\", \"c127\"]\nblocked: d171 -> c127 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d171\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### d255 | decision | adopted [selected]\ntext: Record d255 about module 3\nchoice: Choice 255\napplicable: false\nblocked_by: [\"c199\"]\nblocked: c199 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c199\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q353 | question | open [selected]\ntext: Record q353 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c346 | claim | unassessed [selected]\ntext: Record c346 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d339 | decision | adopted [selected]\ntext: Record d339 about module 3\nchoice: Choice 339\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d78\"]\n\n### q332 | question | open [selected]\ntext: Record q332 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c325 | claim | unassessed [selected]\ntext: Record c325 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d318 | decision | adopted [selected]\ntext: Record d318 about module 3\nchoice: Choice 318\napplicable: false\nblocked_by: [\"d255\", \"c199\"]\nblocked: d255 -> c199 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d255\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q311 | question | open [selected]\ntext: Record q311 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c304 | claim | unassessed [selected]\ntext: Record c304 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d297 | decision | adopted [selected]\ntext: Record d297 about module 3\nchoice: Choice 297\nscope: [\"lib/mod3/**\"]\n\n### q290 | question | open [selected]\ntext: Record q290 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c283 | claim | unassessed [selected]\ntext: Record c283 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d276 | decision | adopted [selected]\ntext: Record d276 about module 3\nchoice: Choice 276\nscope: [\"lib/mod3/**\"]\n\n### d171 | decision | adopted [selected]\ntext: Record d171 about module 3\nchoice: Choice 171\napplicable: false\nblocked_by: [\"c127\"]\nblocked: c127 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c127\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q269 | question | open [selected]\ntext: Record q269 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c262 | claim | unassessed [selected]\ntext: Record c262 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d150 | decision | adopted [selected]\ntext: Record d150 about module 3\nchoice: Choice 150\napplicable: false\nblocked_by: [\"d147\", \"c37\"]\nblocked: d147 -> c37 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d147\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q248 | question | open [selected]\ntext: Record q248 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c241 | claim | unassessed [selected]\ntext: Record c241 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d234 | decision | adopted [selected]\ntext: Record d234 about module 3\nchoice: Choice 234\napplicable: false\nblocked_by: [\"d147\", \"c37\"]\nblocked: d147 -> c37 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d147\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q227 | question | open [selected]\ntext: Record q227 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c220 | claim | unassessed [selected]\ntext: Record c220 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d213 | decision | adopted [selected]\ntext: Record d213 about module 3\nchoice: Choice 213\napplicable: false\nblocked_by: [\"c49\"]\nblocked: c49 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c49\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q206 | question | open [selected]\ntext: Record q206 about module 3\nscope: [\"lib/mod3/**\"]\n\n### q8 | question | open [selected]\ntext: Record q8 about module 1\nscope: [\"lib/mod1/**\"]\n\n# index: 40 more current records\nc94 claim unassessed Record c94 about module 3\nd192 decision adopted Record d192 about module 3\nq185 question open Record q185 about module 3\nc178 claim unassessed Record c178 about module 3\nq164 question open Record q164 about module 3\nc157 claim unassessed Record c157 about module 3\nc52 claim unassessed Record c52 about module 3\nq143 question open Record q143 about module 3\nc136 claim unassessed Record c136 about module 3\nd129 decision adopted Record d129 about module 3\nd24 decision adopted Record d24 about module 3\nq122 question open Record q122 about module 3\nc115 claim unassessed Record c115 about module 3\nd108 decision adopted Record d108 about module 3\nd3 decision adopted Record d3 about module 3\nq101 question open Record q101 about module 3\nd87 decision adopted Record d87 about module 3\nq80 question open Record q80 about module 3\nc73 claim unassessed Record c73 about module 3\nd66 decision adopted Record d66 about module 3\nq59 question open Record q59 about module 3\nd45 decision adopted Record d45 about module 3\nq38 question open Record q38 about module 3\nc31 claim unassessed Record c31 about module 3\nq17 question open Record q17 about module 3\nc10 claim unassessed Record c10 about module 3\nd399 decision adopted Record d399 about module 0\nq398 question open Record q398 about module 6\nc397 claim unassessed Record c397 about module 5\nd396 decision adopted Record d396 about module 4\nc394 claim unassessed Record c394 about module 2\nd393 decision adopted Record d393 about module 1\nq392 question open Record q392 about module 0\nc391 claim unassessed Record c391 about module 6\nd390 decision adopted Record d390 about module 5\nq389 question open Record q389 about module 4\nd387 decision adopted Record d387 about module 2\nq386 question open Record q386 about module 1\nc385 claim unassessed Record c385 about module 0\nd384 decision adopted Record d384 about module 6\n# and 328 more; docket list\n\n# full text: 32; index: 40; retired: 0.\n# Not listed: 328; reach them with docket list.\n# Related records in index only: 4; formulas remain complete.\n# Coverage: partial, 368 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n400_qmodule 3_fno_bdefault": "# docket: repo | revision: 920de186cdd4 | latest: c400@920de186cdd4\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n### c199 | claim | unassessed [selected]\ntext: Record c199 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q395 | question | open [selected]\ntext: Record q395 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c388 | claim | unassessed [selected]\ntext: Record c388 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d381 | decision | adopted [selected]\ntext: Record d381 about module 3\nchoice: Choice 381\nscope: [\"lib/mod3/**\"]\n\n### q374 | question | open [selected]\ntext: Record q374 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c367 | claim | unassessed [selected]\ntext: Record c367 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d360 | decision | adopted [selected]\ntext: Record d360 about module 3\nchoice: Choice 360\napplicable: false\nblocked_by: [\"d171\", \"c127\"]\nblocked: d171 -> c127 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d171\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### d255 | decision | adopted [selected]\ntext: Record d255 about module 3\nchoice: Choice 255\napplicable: false\nblocked_by: [\"c199\"]\nblocked: c199 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c199\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q353 | question | open [selected]\ntext: Record q353 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c346 | claim | unassessed [selected]\ntext: Record c346 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d339 | decision | adopted [selected]\ntext: Record d339 about module 3\nchoice: Choice 339\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d78\"]\n\n### q332 | question | open [selected]\ntext: Record q332 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c325 | claim | unassessed [selected]\ntext: Record c325 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d318 | decision | adopted [selected]\ntext: Record d318 about module 3\nchoice: Choice 318\napplicable: false\nblocked_by: [\"d255\", \"c199\"]\nblocked: d255 -> c199 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d255\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q311 | question | open [selected]\ntext: Record q311 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c304 | claim | unassessed [selected]\ntext: Record c304 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d297 | decision | adopted [selected]\ntext: Record d297 about module 3\nchoice: Choice 297\nscope: [\"lib/mod3/**\"]\n\n### q290 | question | open [selected]\ntext: Record q290 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c283 | claim | unassessed [selected]\ntext: Record c283 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d276 | decision | adopted [selected]\ntext: Record d276 about module 3\nchoice: Choice 276\nscope: [\"lib/mod3/**\"]\n\n### d171 | decision | adopted [selected]\ntext: Record d171 about module 3\nchoice: Choice 171\napplicable: false\nblocked_by: [\"c127\"]\nblocked: c127 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c127\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q269 | question | open [selected]\ntext: Record q269 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c262 | claim | unassessed [selected]\ntext: Record c262 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d150 | decision | adopted [selected]\ntext: Record d150 about module 3\nchoice: Choice 150\napplicable: false\nblocked_by: [\"d147\", \"c37\"]\nblocked: d147 -> c37 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d147\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q248 | question | open [selected]\ntext: Record q248 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c241 | claim | unassessed [selected]\ntext: Record c241 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d234 | decision | adopted [selected]\ntext: Record d234 about module 3\nchoice: Choice 234\napplicable: false\nblocked_by: [\"d147\", \"c37\"]\nblocked: d147 -> c37 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d147\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q227 | question | open [selected]\ntext: Record q227 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c220 | claim | unassessed [selected]\ntext: Record c220 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d213 | decision | adopted [selected]\ntext: Record d213 about module 3\nchoice: Choice 213\napplicable: false\nblocked_by: [\"c49\"]\nblocked: c49 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c49\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q206 | question | open [selected]\ntext: Record q206 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c94 | claim | unassessed [selected]\ntext: Record c94 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d192 | decision | adopted [selected]\ntext: Record d192 about module 3\nchoice: Choice 192\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d9\"]\n\n### q185 | question | open [selected]\ntext: Record q185 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c178 | claim | unassessed [selected]\ntext: Record c178 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q164 | question | open [selected]\ntext: Record q164 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c157 | claim | unassessed [selected]\ntext: Record c157 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c52 | claim | unassessed [selected]\ntext: Record c52 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q143 | question | open [selected]\ntext: Record q143 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c136 | claim | unassessed [selected]\ntext: Record c136 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d129 | decision | adopted [selected]\ntext: Record d129 about module 3\nchoice: Choice 129\nscope: [\"lib/mod3/**\"]\n\n### d24 | decision | adopted [selected]\ntext: Record d24 about module 3\nchoice: Choice 24\nscope: [\"lib/mod3/**\"]\n\n### q122 | question | open [selected]\ntext: Record q122 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c115 | claim | unassessed [selected]\ntext: Record c115 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d108 | decision | adopted [selected]\ntext: Record d108 about module 3\nchoice: Choice 108\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d30\"]\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### q101 | question | open [selected]\ntext: Record q101 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d87 | decision | adopted [selected]\ntext: Record d87 about module 3\nchoice: Choice 87\nscope: [\"lib/mod3/**\"]\n\n### q80 | question | open [selected]\ntext: Record q80 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c73 | claim | unassessed [selected]\ntext: Record c73 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d66 | decision | adopted [selected]\ntext: Record d66 about module 3\nchoice: Choice 66\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d9\"]\n\n### q59 | question | open [selected]\ntext: Record q59 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d45 | decision | adopted [selected]\ntext: Record d45 about module 3\nchoice: Choice 45\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d24\"]\n\n### q38 | question | open [selected]\ntext: Record q38 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c31 | claim | unassessed [selected]\ntext: Record c31 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q17 | question | open [selected]\ntext: Record q17 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c10 | claim | unassessed [selected]\ntext: Record c10 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d399 | decision | adopted [selected]\ntext: Record d399 about module 0\nchoice: Choice 399\nscope: [\"lib/mod0/**\"]\n\n### q398 | question | open [selected]\ntext: Record q398 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c397 | claim | unassessed [selected]\ntext: Record c397 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d396 | decision | adopted [selected]\ntext: Record d396 about module 4\nchoice: Choice 396\nscope: [\"lib/mod4/**\"]\n\n### c394 | claim | unassessed [selected]\ntext: Record c394 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d393 | decision | adopted [selected]\ntext: Record d393 about module 1\nchoice: Choice 393\nscope: [\"lib/mod1/**\"]\n\n### q392 | question | open [selected]\ntext: Record q392 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c391 | claim | unassessed [selected]\ntext: Record c391 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d390 | decision | adopted [selected]\ntext: Record d390 about module 5\nchoice: Choice 390\nscope: [\"lib/mod5/**\"]\n\n### q389 | question | open [selected]\ntext: Record q389 about module 4\nscope: [\"lib/mod4/**\"]\n\n### d387 | decision | adopted [selected]\ntext: Record d387 about module 2\nchoice: Choice 387\nscope: [\"lib/mod2/**\"]\n\n### q386 | question | open [selected]\ntext: Record q386 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c385 | claim | unassessed [selected]\ntext: Record c385 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d384 | decision | adopted [selected]\ntext: Record d384 about module 6\nchoice: Choice 384\nscope: [\"lib/mod6/**\"]\n\n### q383 | question | open [selected]\ntext: Record q383 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c382 | claim | unassessed [selected]\ntext: Record c382 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q380 | question | open [selected]\ntext: Record q380 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c379 | claim | unassessed [selected]\ntext: Record c379 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d378 | decision | adopted [selected]\ntext: Record d378 about module 0\nchoice: Choice 378\nscope: [\"lib/mod0/**\"]\n\n### q377 | question | open [selected]\ntext: Record q377 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c376 | claim | unassessed [selected]\ntext: Record c376 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d375 | decision | adopted [selected]\ntext: Record d375 about module 4\nchoice: Choice 375\nscope: [\"lib/mod4/**\"]\n\n### c373 | claim | unassessed [selected]\ntext: Record c373 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d372 | decision | adopted [selected]\ntext: Record d372 about module 1\nchoice: Choice 372\nscope: [\"lib/mod1/**\"]\n\n### q371 | question | open [selected]\ntext: Record q371 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c370 | claim | unassessed [selected]\ntext: Record c370 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d369 | decision | adopted [selected]\ntext: Record d369 about module 5\nchoice: Choice 369\napplicable: false\nblocked_by: [\"c109\"]\nblocked: c109 unassessed\nscope: [\"lib/mod5/**\"]\ndepends_on: [\"c109\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q368 | question | open [selected]\ntext: Record q368 about module 4\nscope: [\"lib/mod4/**\"]\n\n### d366 | decision | adopted [selected]\ntext: Record d366 about module 2\nchoice: Choice 366\nscope: [\"lib/mod2/**\"]\n\n### q365 | question | open [selected]\ntext: Record q365 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c364 | claim | unassessed [selected]\ntext: Record c364 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d363 | decision | adopted [selected]\ntext: Record d363 about module 6\nchoice: Choice 363\nscope: [\"lib/mod6/**\"]\n\n### q362 | question | open [selected]\ntext: Record q362 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c361 | claim | unassessed [selected]\ntext: Record c361 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q359 | question | open [selected]\ntext: Record q359 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c358 | claim | unassessed [selected]\ntext: Record c358 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d357 | decision | adopted [selected]\ntext: Record d357 about module 0\nchoice: Choice 357\nscope: [\"lib/mod0/**\"]\n\n### q356 | question | open [selected]\ntext: Record q356 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c355 | claim | unassessed [selected]\ntext: Record c355 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d354 | decision | adopted [selected]\ntext: Record d354 about module 4\nchoice: Choice 354\nscope: [\"lib/mod4/**\"]\n\n### c352 | claim | unassessed [selected]\ntext: Record c352 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d351 | decision | adopted [selected]\ntext: Record d351 about module 1\nchoice: Choice 351\napplicable: false\nblocked_by: [\"c199\"]\nblocked: c199 unassessed\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"c199\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q350 | question | open [selected]\ntext: Record q350 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c349 | claim | unassessed [selected]\ntext: Record c349 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d348 | decision | adopted [selected]\ntext: Record d348 about module 5\nchoice: Choice 348\nscope: [\"lib/mod5/**\"]\n\n### q347 | question | open [selected]\ntext: Record q347 about module 4\nscope: [\"lib/mod4/**\"]\n\n### d345 | decision | adopted [selected]\ntext: Record d345 about module 2\nchoice: Choice 345\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"d33\"]\n\n### q344 | question | open [selected]\ntext: Record q344 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c343 | claim | unassessed [selected]\ntext: Record c343 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d342 | decision | adopted [selected]\ntext: Record d342 about module 6\nchoice: Choice 342\napplicable: false\nblocked_by: [\"c112\"]\nblocked: c112 unassessed\nscope: [\"lib/mod6/**\"]\ndepends_on: [\"c112\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q341 | question | open [selected]\ntext: Record q341 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c340 | claim | unassessed [selected]\ntext: Record c340 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q338 | question | open [selected]\ntext: Record q338 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c337 | claim | unassessed [selected]\ntext: Record c337 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d336 | decision | adopted [selected]\ntext: Record d336 about module 0\nchoice: Choice 336\nscope: [\"lib/mod0/**\"]\n\n### q335 | question | open [selected]\ntext: Record q335 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c334 | claim | unassessed [selected]\ntext: Record c334 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d333 | decision | adopted [selected]\ntext: Record d333 about module 4\nchoice: Choice 333\nscope: [\"lib/mod4/**\"]\n\n### c331 | claim | unassessed [selected]\ntext: Record c331 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d330 | decision | adopted [selected]\ntext: Record d330 about module 1\nchoice: Choice 330\napplicable: false\nblocked_by: [\"c142\"]\nblocked: c142 unassessed\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"c142\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q329 | question | open [selected]\ntext: Record q329 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c328 | claim | unassessed [selected]\ntext: Record c328 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d327 | decision | adopted [selected]\ntext: Record d327 about module 5\nchoice: Choice 327\nscope: [\"lib/mod5/**\"]\n\n### q326 | question | open [selected]\ntext: Record q326 about module 4\nscope: [\"lib/mod4/**\"]\n\n### d324 | decision | adopted [selected]\ntext: Record d324 about module 2\nchoice: Choice 324\nscope: [\"lib/mod2/**\"]\n\n### q323 | question | open [selected]\ntext: Record q323 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c322 | claim | unassessed [selected]\ntext: Record c322 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d321 | decision | adopted [selected]\ntext: Record d321 about module 6\nchoice: Choice 321\nscope: [\"lib/mod6/**\"]\n\n### q320 | question | open [selected]\ntext: Record q320 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c319 | claim | unassessed [selected]\ntext: Record c319 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q317 | question | open [selected]\ntext: Record q317 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c316 | claim | unassessed [selected]\ntext: Record c316 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d315 | decision | adopted [selected]\ntext: Record d315 about module 0\nchoice: Choice 315\nscope: [\"lib/mod0/**\"]\n\n### q314 | question | open [selected]\ntext: Record q314 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c313 | claim | unassessed [selected]\ntext: Record c313 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d312 | decision | adopted [selected]\ntext: Record d312 about module 4\nchoice: Choice 312\nscope: [\"lib/mod4/**\"]\n\n### c310 | claim | unassessed [selected]\ntext: Record c310 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d309 | decision | adopted [selected]\ntext: Record d309 about module 1\nchoice: Choice 309\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"d30\"]\n\n### q308 | question | open [selected]\ntext: Record q308 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c307 | claim | unassessed [selected]\ntext: Record c307 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d306 | decision | adopted [selected]\ntext: Record d306 about module 5\nchoice: Choice 306\nscope: [\"lib/mod5/**\"]\n\n### q305 | question | open [selected]\ntext: Record q305 about module 4\nscope: [\"lib/mod4/**\"]\n\n### d303 | decision | adopted [selected]\ntext: Record d303 about module 2\nchoice: Choice 303\napplicable: false\nblocked_by: [\"d150\", \"d147\", \"c37\"]\nblocked: d150 -> d147 -> c37 unassessed\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"d150\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q302 | question | open [selected]\ntext: Record q302 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c301 | claim | unassessed [selected]\ntext: Record c301 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d300 | decision | adopted [selected]\ntext: Record d300 about module 6\nchoice: Choice 300\nscope: [\"lib/mod6/**\"]\n\n### q293 | question | open [selected]\ntext: Record q293 about module 6\nscope: [\"lib/mod6/**\"]\n\n### d273 | decision | adopted [selected]\ntext: Record d273 about module 0\nchoice: Choice 273\nscope: [\"lib/mod0/**\"]\n\n# index: 40 more current records\nq263 question open Record q263 about module 4\nc253 claim unassessed Record c253 about module 1\nd243 decision adopted Record d243 about module 5\nq239 question open Record q239 about module 1\nc238 claim unassessed Record c238 about module 0\nd237 decision adopted Record d237 about module 6\nc37 claim unassessed Record c37 about module 2\nq236 question open Record q236 about module 5\nc235 claim unassessed Record c235 about module 4\nq233 question open Record q233 about module 2\nc133 claim unassessed Record c133 about module 0\nd33 decision adopted Record d33 about module 5\nc232 claim unassessed Record c232 about module 1\nd231 decision adopted Record d231 about module 0\nq230 question open Record q230 about module 6\nd30 decision adopted Record d30 about module 2\nc223 claim unassessed Record c223 about module 6\nq203 question open Record q203 about module 0\nc193 claim unassessed Record c193 about module 4\nd183 decision adopted Record d183 about module 1\nq173 question open Record q173 about module 5\nc163 claim unassessed Record c163 about module 2\nd153 decision adopted Record d153 about module 6\nc43 claim unassessed Record c43 about module 1\nc139 claim unassessed Record c139 about module 6\nd138 decision adopted Record d138 about module 5\nq137 question open Record q137 about module 4\nd135 decision adopted Record d135 about module 2\nq134 question open Record q134 about module 1\nd132 decision adopted Record d132 about module 6\nq131 question open Record q131 about module 5\nc130 claim unassessed Record c130 about module 4\nd123 decision adopted Record d123 about module 4\nq113 question open Record q113 about module 1\nc103 claim unassessed Record c103 about module 5\nd93 decision adopted Record d93 about module 2\nq83 question open Record q83 about module 6\nd63 decision adopted Record d63 about module 0\nq53 question open Record q53 about module 4\nd39 decision adopted Record d39 about module 4\n# and 215 more; docket list\n\n# full text: 145; index: 40; retired: 0.\n# Not listed: 215; reach them with docket list.\n# Related records in index only: 10; formulas remain complete.\n# Coverage: partial, 255 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n400_qnone_fyes_b900": "# docket: repo | revision: 920de186cdd4 | latest: c400@920de186cdd4\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n# index: c199, q395, c388, d381, q374, c367, d360, d255, q353, c346, d339, q332, c325, d318, q311, c304, d297, q290, c283, d276, d171, q269, c262, d150, q248, c241, d234, q227, c220, d213, q206, c94, d192, q185, c178, q164, c157, c52, q143, c136\n# and 360 more; docket list\n\n# full text: 0; index: 40; retired: 0.\n# Not listed: 360; reach them with docket list.\n# Coverage: partial, 57 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n400_qnone_fyes_b8000": "# docket: repo | revision: 920de186cdd4 | latest: c400@920de186cdd4\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n### c199 | claim | unassessed [selected]\ntext: Record c199 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q395 | question | open [selected]\ntext: Record q395 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c388 | claim | unassessed [selected]\ntext: Record c388 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d381 | decision | adopted [selected]\ntext: Record d381 about module 3\nchoice: Choice 381\nscope: [\"lib/mod3/**\"]\n\n### q374 | question | open [selected]\ntext: Record q374 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c367 | claim | unassessed [selected]\ntext: Record c367 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d360 | decision | adopted [selected]\ntext: Record d360 about module 3\nchoice: Choice 360\napplicable: false\nblocked_by: [\"d171\", \"c127\"]\nblocked: d171 -> c127 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d171\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### d255 | decision | adopted [selected]\ntext: Record d255 about module 3\nchoice: Choice 255\napplicable: false\nblocked_by: [\"c199\"]\nblocked: c199 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c199\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q353 | question | open [selected]\ntext: Record q353 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c346 | claim | unassessed [selected]\ntext: Record c346 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d339 | decision | adopted [selected]\ntext: Record d339 about module 3\nchoice: Choice 339\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d78\"]\n\n### q332 | question | open [selected]\ntext: Record q332 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c325 | claim | unassessed [selected]\ntext: Record c325 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d318 | decision | adopted [selected]\ntext: Record d318 about module 3\nchoice: Choice 318\napplicable: false\nblocked_by: [\"d255\", \"c199\"]\nblocked: d255 -> c199 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d255\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q311 | question | open [selected]\ntext: Record q311 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c304 | claim | unassessed [selected]\ntext: Record c304 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d297 | decision | adopted [selected]\ntext: Record d297 about module 3\nchoice: Choice 297\nscope: [\"lib/mod3/**\"]\n\n### q290 | question | open [selected]\ntext: Record q290 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c283 | claim | unassessed [selected]\ntext: Record c283 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d276 | decision | adopted [selected]\ntext: Record d276 about module 3\nchoice: Choice 276\nscope: [\"lib/mod3/**\"]\n\n### d171 | decision | adopted [selected]\ntext: Record d171 about module 3\nchoice: Choice 171\napplicable: false\nblocked_by: [\"c127\"]\nblocked: c127 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c127\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q269 | question | open [selected]\ntext: Record q269 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c262 | claim | unassessed [selected]\ntext: Record c262 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d150 | decision | adopted [selected]\ntext: Record d150 about module 3\nchoice: Choice 150\napplicable: false\nblocked_by: [\"d147\", \"c37\"]\nblocked: d147 -> c37 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d147\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q248 | question | open [selected]\ntext: Record q248 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c241 | claim | unassessed [selected]\ntext: Record c241 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d234 | decision | adopted [selected]\ntext: Record d234 about module 3\nchoice: Choice 234\napplicable: false\nblocked_by: [\"d147\", \"c37\"]\nblocked: d147 -> c37 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d147\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q227 | question | open [selected]\ntext: Record q227 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c220 | claim | unassessed [selected]\ntext: Record c220 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d213 | decision | adopted [selected]\ntext: Record d213 about module 3\nchoice: Choice 213\napplicable: false\nblocked_by: [\"c49\"]\nblocked: c49 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c49\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q206 | question | open [selected]\ntext: Record q206 about module 3\nscope: [\"lib/mod3/**\"]\n\n# index: 40 more current records\nc94 claim unassessed Record c94 about module 3\nd192 decision adopted Record d192 about module 3\nq185 question open Record q185 about module 3\nc178 claim unassessed Record c178 about module 3\nq164 question open Record q164 about module 3\nc157 claim unassessed Record c157 about module 3\nc52 claim unassessed Record c52 about module 3\nq143 question open Record q143 about module 3\nc136 claim unassessed Record c136 about module 3\nd129 decision adopted Record d129 about module 3\nd24 decision adopted Record d24 about module 3\nq122 question open Record q122 about module 3\nc115 claim unassessed Record c115 about module 3\nd108 decision adopted Record d108 about module 3\nd3 decision adopted Record d3 about module 3\nq101 question open Record q101 about module 3\nd87 decision adopted Record d87 about module 3\nq80 question open Record q80 about module 3\nc73 claim unassessed Record c73 about module 3\nd66 decision adopted Record d66 about module 3\nq59 question open Record q59 about module 3\nd45 decision adopted Record d45 about module 3\nq38 question open Record q38 about module 3\nc31 claim unassessed Record c31 about module 3\nq17 question open Record q17 about module 3\nc10 claim unassessed Record c10 about module 3\nd147 decision adopted Record d147 about module 0\nc400 claim unassessed Record c400 about module 1\nd399 decision adopted Record d399 about module 0\nq398 question open Record q398 about module 6\nc397 claim unassessed Record c397 about module 5\nd396 decision adopted Record d396 about module 4\nc394 claim unassessed Record c394 about module 2\nd393 decision adopted Record d393 about module 1\nq392 question open Record q392 about module 0\nc391 claim unassessed Record c391 about module 6\nd390 decision adopted Record d390 about module 5\nq389 question open Record q389 about module 4\nd387 decision adopted Record d387 about module 2\nq386 question open Record q386 about module 1\n# and 329 more; docket list\n\n# full text: 31; index: 40; retired: 0.\n# Not listed: 329; reach them with docket list.\n# Related records in index only: 4; formulas remain complete.\n# Coverage: partial, 30 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n400_qnone_fyes_bdefault": "# docket: repo | revision: 920de186cdd4 | latest: c400@920de186cdd4\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n### c199 | claim | unassessed [selected]\ntext: Record c199 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q395 | question | open [selected]\ntext: Record q395 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c388 | claim | unassessed [selected]\ntext: Record c388 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d381 | decision | adopted [selected]\ntext: Record d381 about module 3\nchoice: Choice 381\nscope: [\"lib/mod3/**\"]\n\n### q374 | question | open [selected]\ntext: Record q374 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c367 | claim | unassessed [selected]\ntext: Record c367 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d360 | decision | adopted [selected]\ntext: Record d360 about module 3\nchoice: Choice 360\napplicable: false\nblocked_by: [\"d171\", \"c127\"]\nblocked: d171 -> c127 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d171\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### d255 | decision | adopted [selected]\ntext: Record d255 about module 3\nchoice: Choice 255\napplicable: false\nblocked_by: [\"c199\"]\nblocked: c199 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c199\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q353 | question | open [selected]\ntext: Record q353 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c346 | claim | unassessed [selected]\ntext: Record c346 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d339 | decision | adopted [selected]\ntext: Record d339 about module 3\nchoice: Choice 339\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d78\"]\n\n### q332 | question | open [selected]\ntext: Record q332 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c325 | claim | unassessed [selected]\ntext: Record c325 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d318 | decision | adopted [selected]\ntext: Record d318 about module 3\nchoice: Choice 318\napplicable: false\nblocked_by: [\"d255\", \"c199\"]\nblocked: d255 -> c199 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d255\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q311 | question | open [selected]\ntext: Record q311 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c304 | claim | unassessed [selected]\ntext: Record c304 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d297 | decision | adopted [selected]\ntext: Record d297 about module 3\nchoice: Choice 297\nscope: [\"lib/mod3/**\"]\n\n### q290 | question | open [selected]\ntext: Record q290 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c283 | claim | unassessed [selected]\ntext: Record c283 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d276 | decision | adopted [selected]\ntext: Record d276 about module 3\nchoice: Choice 276\nscope: [\"lib/mod3/**\"]\n\n### d171 | decision | adopted [selected]\ntext: Record d171 about module 3\nchoice: Choice 171\napplicable: false\nblocked_by: [\"c127\"]\nblocked: c127 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c127\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q269 | question | open [selected]\ntext: Record q269 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c262 | claim | unassessed [selected]\ntext: Record c262 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d150 | decision | adopted [selected]\ntext: Record d150 about module 3\nchoice: Choice 150\napplicable: false\nblocked_by: [\"d147\", \"c37\"]\nblocked: d147 -> c37 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d147\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q248 | question | open [selected]\ntext: Record q248 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c241 | claim | unassessed [selected]\ntext: Record c241 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d234 | decision | adopted [selected]\ntext: Record d234 about module 3\nchoice: Choice 234\napplicable: false\nblocked_by: [\"d147\", \"c37\"]\nblocked: d147 -> c37 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d147\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q227 | question | open [selected]\ntext: Record q227 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c220 | claim | unassessed [selected]\ntext: Record c220 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d213 | decision | adopted [selected]\ntext: Record d213 about module 3\nchoice: Choice 213\napplicable: false\nblocked_by: [\"c49\"]\nblocked: c49 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c49\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q206 | question | open [selected]\ntext: Record q206 about module 3\nscope: [\"lib/mod3/**\"]\n\n# index: 40 more current records\nc94 claim unassessed Record c94 about module 3\nd192 decision adopted Record d192 about module 3\nq185 question open Record q185 about module 3\nc178 claim unassessed Record c178 about module 3\nq164 question open Record q164 about module 3\nc157 claim unassessed Record c157 about module 3\nc52 claim unassessed Record c52 about module 3\nq143 question open Record q143 about module 3\nc136 claim unassessed Record c136 about module 3\nd129 decision adopted Record d129 about module 3\nd24 decision adopted Record d24 about module 3\nq122 question open Record q122 about module 3\nc115 claim unassessed Record c115 about module 3\nd108 decision adopted Record d108 about module 3\nd3 decision adopted Record d3 about module 3\nq101 question open Record q101 about module 3\nd87 decision adopted Record d87 about module 3\nq80 question open Record q80 about module 3\nc73 claim unassessed Record c73 about module 3\nd66 decision adopted Record d66 about module 3\nq59 question open Record q59 about module 3\nd45 decision adopted Record d45 about module 3\nq38 question open Record q38 about module 3\nc31 claim unassessed Record c31 about module 3\nq17 question open Record q17 about module 3\nc10 claim unassessed Record c10 about module 3\nd147 decision adopted Record d147 about module 0\nc400 claim unassessed Record c400 about module 1\nd399 decision adopted Record d399 about module 0\nq398 question open Record q398 about module 6\nc397 claim unassessed Record c397 about module 5\nd396 decision adopted Record d396 about module 4\nc394 claim unassessed Record c394 about module 2\nd393 decision adopted Record d393 about module 1\nq392 question open Record q392 about module 0\nc391 claim unassessed Record c391 about module 6\nd390 decision adopted Record d390 about module 5\nq389 question open Record q389 about module 4\nd387 decision adopted Record d387 about module 2\nq386 question open Record q386 about module 1\n# and 329 more; docket list\n\n# full text: 31; index: 40; retired: 0.\n# Not listed: 329; reach them with docket list.\n# Related records in index only: 4; formulas remain complete.\n# Coverage: partial, 30 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n1500_qnone_fno_b900": "# docket: repo | revision: 48161f778c9d | latest: d1500@48161f778c9d\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n# index: c1300, c1435, c676, c1399, c1006, d1335, c1264, c1186, c817, c796, d1170, c1156, d18, d9, d1500, q1499, c1498, d1497, q1496, c1495, d1494, q1493, d1122, c748, c1492, d1491, q1490, c1489, d1488, q1487, c1486, d1485, q1484, c1483, d1482, q1481, c1480, d1479, q1478, c358\n# and 1460 more; docket list\n\n# full text: 0; index: 40; retired: 0.\n# Not listed: 1460; reach them with docket list.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n1500_qnone_fno_b8000": "# docket: repo | revision: 48161f778c9d | latest: d1500@48161f778c9d\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n### c1300 | claim | unassessed [selected]\ntext: Record c1300 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c1435 | claim | unassessed [selected]\ntext: Record c1435 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c676 | claim | unassessed [selected]\ntext: Record c676 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c1399 | claim | unassessed [selected]\ntext: Record c1399 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c1006 | claim | unassessed [selected]\ntext: Record c1006 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1335 | decision | adopted [selected]\ntext: Record d1335 about module 5\nchoice: Choice 1335\nscope: [\"lib/mod5/**\"]\ndepends_on: [\"d420\"]\n\n### c1264 | claim | unassessed [selected]\ntext: Record c1264 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c1186 | claim | unassessed [selected]\ntext: Record c1186 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c817 | claim | unassessed [selected]\ntext: Record c817 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c796 | claim | unassessed [selected]\ntext: Record c796 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1170 | decision | adopted [selected]\ntext: Record d1170 about module 1\nchoice: Choice 1170\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"d234\"]\n\n### c1156 | claim | unassessed [selected]\ntext: Record c1156 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d18 | decision | adopted [selected]\ntext: Record d18 about module 4\nchoice: Choice 18\nscope: [\"lib/mod4/**\"]\ndepends_on: [\"d9\"]\n\n### d9 | decision | adopted [selected]\ntext: Record d9 about module 2\nchoice: Choice 9\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"d3\"]\n\n### d1500 | decision | adopted [selected]\ntext: Record d1500 about module 2\nchoice: Choice 1500\nscope: [\"lib/mod2/**\"]\n\n### q1499 | question | open [selected]\ntext: Record q1499 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c1498 | claim | unassessed [selected]\ntext: Record c1498 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1497 | decision | adopted [selected]\ntext: Record d1497 about module 6\nchoice: Choice 1497\napplicable: false\nblocked_by: [\"c28\"]\nblocked: c28 unassessed\nscope: [\"lib/mod6/**\"]\ndepends_on: [\"c28\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q1496 | question | open [selected]\ntext: Record q1496 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c1495 | claim | unassessed [selected]\ntext: Record c1495 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1494 | decision | adopted [selected]\ntext: Record d1494 about module 3\nchoice: Choice 1494\nscope: [\"lib/mod3/**\"]\n\n### q1493 | question | open [selected]\ntext: Record q1493 about module 2\nscope: [\"lib/mod2/**\"]\n\n### d1122 | decision | adopted [selected]\ntext: Record d1122 about module 2\nchoice: Choice 1122\napplicable: false\nblocked_by: [\"c895\"]\nblocked: c895 unassessed\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"c895\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c748 | claim | unassessed [selected]\ntext: Record c748 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c1492 | claim | unassessed [selected]\ntext: Record c1492 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1491 | decision | adopted [selected]\ntext: Record d1491 about module 0\nchoice: Choice 1491\nscope: [\"lib/mod0/**\"]\n\n### q1490 | question | open [selected]\ntext: Record q1490 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c1489 | claim | unassessed [selected]\ntext: Record c1489 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1488 | decision | adopted [selected]\ntext: Record d1488 about module 4\nchoice: Choice 1488\nscope: [\"lib/mod4/**\"]\n\n### q1487 | question | open [selected]\ntext: Record q1487 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1486 | claim | unassessed [selected]\ntext: Record c1486 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q1484 | question | open [selected]\ntext: Record q1484 about module 0\nscope: [\"lib/mod0/**\"]\n\n### q1481 | question | open [selected]\ntext: Record q1481 about module 4\nscope: [\"lib/mod4/**\"]\n\n# index: 40 more current records\nd1485 decision adopted Record d1485 about module 1\nc1483 claim unassessed Record c1483 about module 6\nd1482 decision adopted Record d1482 about module 5\nc1480 claim unassessed Record c1480 about module 3\nd1479 decision adopted Record d1479 about module 2\nq1478 question open Record q1478 about module 1\nc358 claim unassessed Record c358 about module 1\nc1477 claim unassessed Record c1477 about module 0\nd1476 decision adopted Record d1476 about module 6\nq1475 question open Record q1475 about module 5\nc1474 claim unassessed Record c1474 about module 4\nd1473 decision adopted Record d1473 about module 3\nq1472 question open Record q1472 about module 2\nc1471 claim unassessed Record c1471 about module 1\nd1470 decision adopted Record d1470 about module 0\nq1469 question open Record q1469 about module 6\nc1468 claim unassessed Record c1468 about module 5\nd1467 decision adopted Record d1467 about module 4\nq1466 question open Record q1466 about module 3\nc1465 claim unassessed Record c1465 about module 2\nd1464 decision adopted Record d1464 about module 1\nq1463 question open Record q1463 about module 0\nc1462 claim unassessed Record c1462 about module 6\nd1461 decision adopted Record d1461 about module 5\nq1460 question open Record q1460 about module 4\nc1459 claim unassessed Record c1459 about module 3\nd1458 decision adopted Record d1458 about module 2\nq1457 question open Record q1457 about module 1\nc1456 claim unassessed Record c1456 about module 0\nd1455 decision adopted Record d1455 about module 6\nq1454 question open Record q1454 about module 5\nc1453 claim unassessed Record c1453 about module 4\nd1452 decision adopted Record d1452 about module 3\nq1451 question open Record q1451 about module 2\nc1450 claim unassessed Record c1450 about module 1\nd1449 decision adopted Record d1449 about module 0\nq1448 question open Record q1448 about module 6\nd705 decision adopted Record d705 about module 5\nc1447 claim unassessed Record c1447 about module 5\nd1446 decision adopted Record d1446 about module 4\n# and 1427 more; docket list\n\n# full text: 33; index: 40; retired: 0.\n# Not listed: 1427; reach them with docket list.\n# Related records in index only: 5; formulas remain complete.\n# Coverage: partial, 2 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n1500_qnone_fno_bdefault": "# docket: repo | revision: 48161f778c9d | latest: d1500@48161f778c9d\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n### c1300 | claim | unassessed [selected]\ntext: Record c1300 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c1435 | claim | unassessed [selected]\ntext: Record c1435 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c676 | claim | unassessed [selected]\ntext: Record c676 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c1399 | claim | unassessed [selected]\ntext: Record c1399 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c1006 | claim | unassessed [selected]\ntext: Record c1006 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1335 | decision | adopted [selected]\ntext: Record d1335 about module 5\nchoice: Choice 1335\nscope: [\"lib/mod5/**\"]\ndepends_on: [\"d420\"]\n\n### c1264 | claim | unassessed [selected]\ntext: Record c1264 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c1186 | claim | unassessed [selected]\ntext: Record c1186 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c817 | claim | unassessed [selected]\ntext: Record c817 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c796 | claim | unassessed [selected]\ntext: Record c796 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1170 | decision | adopted [selected]\ntext: Record d1170 about module 1\nchoice: Choice 1170\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"d234\"]\n\n### c1156 | claim | unassessed [selected]\ntext: Record c1156 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d18 | decision | adopted [selected]\ntext: Record d18 about module 4\nchoice: Choice 18\nscope: [\"lib/mod4/**\"]\ndepends_on: [\"d9\"]\n\n### d9 | decision | adopted [selected]\ntext: Record d9 about module 2\nchoice: Choice 9\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"d3\"]\n\n### d1500 | decision | adopted [selected]\ntext: Record d1500 about module 2\nchoice: Choice 1500\nscope: [\"lib/mod2/**\"]\n\n### q1499 | question | open [selected]\ntext: Record q1499 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c1498 | claim | unassessed [selected]\ntext: Record c1498 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1497 | decision | adopted [selected]\ntext: Record d1497 about module 6\nchoice: Choice 1497\napplicable: false\nblocked_by: [\"c28\"]\nblocked: c28 unassessed\nscope: [\"lib/mod6/**\"]\ndepends_on: [\"c28\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q1496 | question | open [selected]\ntext: Record q1496 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c1495 | claim | unassessed [selected]\ntext: Record c1495 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1494 | decision | adopted [selected]\ntext: Record d1494 about module 3\nchoice: Choice 1494\nscope: [\"lib/mod3/**\"]\n\n### q1493 | question | open [selected]\ntext: Record q1493 about module 2\nscope: [\"lib/mod2/**\"]\n\n### d1122 | decision | adopted [selected]\ntext: Record d1122 about module 2\nchoice: Choice 1122\napplicable: false\nblocked_by: [\"c895\"]\nblocked: c895 unassessed\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"c895\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c748 | claim | unassessed [selected]\ntext: Record c748 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c1492 | claim | unassessed [selected]\ntext: Record c1492 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1491 | decision | adopted [selected]\ntext: Record d1491 about module 0\nchoice: Choice 1491\nscope: [\"lib/mod0/**\"]\n\n### q1490 | question | open [selected]\ntext: Record q1490 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c1489 | claim | unassessed [selected]\ntext: Record c1489 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1488 | decision | adopted [selected]\ntext: Record d1488 about module 4\nchoice: Choice 1488\nscope: [\"lib/mod4/**\"]\n\n### q1487 | question | open [selected]\ntext: Record q1487 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1486 | claim | unassessed [selected]\ntext: Record c1486 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q1484 | question | open [selected]\ntext: Record q1484 about module 0\nscope: [\"lib/mod0/**\"]\n\n### q1481 | question | open [selected]\ntext: Record q1481 about module 4\nscope: [\"lib/mod4/**\"]\n\n# index: 40 more current records\nd1485 decision adopted Record d1485 about module 1\nc1483 claim unassessed Record c1483 about module 6\nd1482 decision adopted Record d1482 about module 5\nc1480 claim unassessed Record c1480 about module 3\nd1479 decision adopted Record d1479 about module 2\nq1478 question open Record q1478 about module 1\nc358 claim unassessed Record c358 about module 1\nc1477 claim unassessed Record c1477 about module 0\nd1476 decision adopted Record d1476 about module 6\nq1475 question open Record q1475 about module 5\nc1474 claim unassessed Record c1474 about module 4\nd1473 decision adopted Record d1473 about module 3\nq1472 question open Record q1472 about module 2\nc1471 claim unassessed Record c1471 about module 1\nd1470 decision adopted Record d1470 about module 0\nq1469 question open Record q1469 about module 6\nc1468 claim unassessed Record c1468 about module 5\nd1467 decision adopted Record d1467 about module 4\nq1466 question open Record q1466 about module 3\nc1465 claim unassessed Record c1465 about module 2\nd1464 decision adopted Record d1464 about module 1\nq1463 question open Record q1463 about module 0\nc1462 claim unassessed Record c1462 about module 6\nd1461 decision adopted Record d1461 about module 5\nq1460 question open Record q1460 about module 4\nc1459 claim unassessed Record c1459 about module 3\nd1458 decision adopted Record d1458 about module 2\nq1457 question open Record q1457 about module 1\nc1456 claim unassessed Record c1456 about module 0\nd1455 decision adopted Record d1455 about module 6\nq1454 question open Record q1454 about module 5\nc1453 claim unassessed Record c1453 about module 4\nd1452 decision adopted Record d1452 about module 3\nq1451 question open Record q1451 about module 2\nc1450 claim unassessed Record c1450 about module 1\nd1449 decision adopted Record d1449 about module 0\nq1448 question open Record q1448 about module 6\nd705 decision adopted Record d705 about module 5\nc1447 claim unassessed Record c1447 about module 5\nd1446 decision adopted Record d1446 about module 4\n# and 1427 more; docket list\n\n# full text: 33; index: 40; retired: 0.\n# Not listed: 1427; reach them with docket list.\n# Related records in index only: 5; formulas remain complete.\n# Coverage: partial, 2 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n1500_qmodule 3_fno_b900": "# docket: repo | revision: 48161f778c9d | latest: d1500@48161f778c9d\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n# index: c1186, d1494, q1487, c1480, d1473, q1466, c1459, d1452, q1445, c1438, d1431, q1424, c1417, c1039, d1410, q1403, c1396, d1389, q1382, c1375, d1368, c619, q1361, c1354, d1347, q1340, c1333, d1326, q1319, c1312, d1305, q1298, c1291, d1284, q1277, c1270, d1263, q1256, c1249, d1242\n# and 1460 more; docket list\n\n# full text: 0; index: 40; retired: 0.\n# Not listed: 1460; reach them with docket list.\n# Coverage: partial, 595 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n1500_qmodule 3_fno_b8000": "# docket: repo | revision: 48161f778c9d | latest: d1500@48161f778c9d\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n### c1186 | claim | unassessed [selected]\ntext: Record c1186 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1494 | decision | adopted [selected]\ntext: Record d1494 about module 3\nchoice: Choice 1494\nscope: [\"lib/mod3/**\"]\n\n### q1487 | question | open [selected]\ntext: Record q1487 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1480 | claim | unassessed [selected]\ntext: Record c1480 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1473 | decision | adopted [selected]\ntext: Record d1473 about module 3\nchoice: Choice 1473\nscope: [\"lib/mod3/**\"]\n\n### q1466 | question | open [selected]\ntext: Record q1466 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1459 | claim | unassessed [selected]\ntext: Record c1459 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1452 | decision | adopted [selected]\ntext: Record d1452 about module 3\nchoice: Choice 1452\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d1170\"]\n\n### q1445 | question | open [selected]\ntext: Record q1445 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1438 | claim | unassessed [selected]\ntext: Record c1438 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1431 | decision | adopted [selected]\ntext: Record d1431 about module 3\nchoice: Choice 1431\nscope: [\"lib/mod3/**\"]\n\n### q1424 | question | open [selected]\ntext: Record q1424 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1417 | claim | unassessed [selected]\ntext: Record c1417 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c1039 | claim | unassessed [selected]\ntext: Record c1039 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1410 | decision | adopted [selected]\ntext: Record d1410 about module 3\nchoice: Choice 1410\nscope: [\"lib/mod3/**\"]\n\n### q1403 | question | open [selected]\ntext: Record q1403 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1396 | claim | unassessed [selected]\ntext: Record c1396 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1389 | decision | adopted [selected]\ntext: Record d1389 about module 3\nchoice: Choice 1389\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d453\"]\n\n### q1382 | question | open [selected]\ntext: Record q1382 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1375 | claim | unassessed [selected]\ntext: Record c1375 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1368 | decision | adopted [selected]\ntext: Record d1368 about module 3\nchoice: Choice 1368\napplicable: false\nblocked_by: [\"d1122\", \"c895\"]\nblocked: d1122 -> c895 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d1122\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c619 | claim | unassessed [selected]\ntext: Record c619 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q1361 | question | open [selected]\ntext: Record q1361 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1354 | claim | unassessed [selected]\ntext: Record c1354 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1347 | decision | adopted [selected]\ntext: Record d1347 about module 3\nchoice: Choice 1347\nscope: [\"lib/mod3/**\"]\n\n### q1340 | question | open [selected]\ntext: Record q1340 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1333 | claim | unassessed [selected]\ntext: Record c1333 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1326 | decision | adopted [selected]\ntext: Record d1326 about module 3\nchoice: Choice 1326\napplicable: false\nblocked_by: [\"c442\"]\nblocked: c442 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c442\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q1319 | question | open [selected]\ntext: Record q1319 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1312 | claim | unassessed [selected]\ntext: Record c1312 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1305 | decision | adopted [selected]\ntext: Record d1305 about module 3\nchoice: Choice 1305\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d822\"]\n\n### q1298 | question | open [selected]\ntext: Record q1298 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1291 | claim | unassessed [selected]\ntext: Record c1291 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1284 | decision | adopted [selected]\ntext: Record d1284 about module 3\nchoice: Choice 1284\nscope: [\"lib/mod3/**\"]\n\n### q1277 | question | open [selected]\ntext: Record q1277 about module 3\nscope: [\"lib/mod3/**\"]\n\n# index: 40 more current records\nc1270 claim unassessed Record c1270 about module 3\nd1263 decision adopted Record d1263 about module 3\nq1256 question open Record q1256 about module 3\nc1249 claim unassessed Record c1249 about module 3\nd1242 decision adopted Record d1242 about module 3\nq1235 question open Record q1235 about module 3\nc1228 claim unassessed Record c1228 about module 3\nd1221 decision adopted Record d1221 about module 3\nq1214 question open Record q1214 about module 3\nc1207 claim unassessed Record c1207 about module 3\nd1200 decision adopted Record d1200 about module 3\nq1193 question open Record q1193 about module 3\nd822 decision adopted Record d822 about module 3\nd1179 decision adopted Record d1179 about module 3\nq1172 question open Record q1172 about module 3\nc1165 claim unassessed Record c1165 about module 3\nd1158 decision adopted Record d1158 about module 3\nq1151 question open Record q1151 about module 3\nc1144 claim unassessed Record c1144 about module 3\nd1137 decision adopted Record d1137 about module 3\nq1130 question open Record q1130 about module 3\nd3 decision adopted Record d3 about module 3\nc1123 claim unassessed Record c1123 about module 3\nd1116 decision adopted Record d1116 about module 3\nq1109 question open Record q1109 about module 3\nc1102 claim unassessed Record c1102 about module 3\nc724 claim unassessed Record c724 about module 3\nd1095 decision adopted Record d1095 about module 3\nq1088 question open Record q1088 about module 3\nd717 decision adopted Record d717 about module 3\nc1081 claim unassessed Record c1081 about module 3\nd1074 decision adopted Record d1074 about module 3\nq1067 question open Record q1067 about module 3\nd696 decision adopted Record d696 about module 3\nc1060 claim unassessed Record c1060 about module 3\nd1053 decision adopted Record d1053 about module 3\nq1046 question open Record q1046 about module 3\nd1032 decision adopted Record d1032 about module 3\nq1025 question open Record q1025 about module 3\nc1018 claim unassessed Record c1018 about module 3\n# and 1425 more; docket list\n\n# full text: 35; index: 40; retired: 0.\n# Not listed: 1425; reach them with docket list.\n# Related records in index only: 5; formulas remain complete.\n# Coverage: partial, 563 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n1500_qmodule 3_fno_bdefault": "# docket: repo | revision: 48161f778c9d | latest: d1500@48161f778c9d\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n### c1186 | claim | unassessed [selected]\ntext: Record c1186 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1494 | decision | adopted [selected]\ntext: Record d1494 about module 3\nchoice: Choice 1494\nscope: [\"lib/mod3/**\"]\n\n### q1487 | question | open [selected]\ntext: Record q1487 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1480 | claim | unassessed [selected]\ntext: Record c1480 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1473 | decision | adopted [selected]\ntext: Record d1473 about module 3\nchoice: Choice 1473\nscope: [\"lib/mod3/**\"]\n\n### q1466 | question | open [selected]\ntext: Record q1466 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1459 | claim | unassessed [selected]\ntext: Record c1459 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1452 | decision | adopted [selected]\ntext: Record d1452 about module 3\nchoice: Choice 1452\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d1170\"]\n\n### q1445 | question | open [selected]\ntext: Record q1445 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1438 | claim | unassessed [selected]\ntext: Record c1438 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1431 | decision | adopted [selected]\ntext: Record d1431 about module 3\nchoice: Choice 1431\nscope: [\"lib/mod3/**\"]\n\n### q1424 | question | open [selected]\ntext: Record q1424 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1417 | claim | unassessed [selected]\ntext: Record c1417 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c1039 | claim | unassessed [selected]\ntext: Record c1039 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1410 | decision | adopted [selected]\ntext: Record d1410 about module 3\nchoice: Choice 1410\nscope: [\"lib/mod3/**\"]\n\n### q1403 | question | open [selected]\ntext: Record q1403 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1396 | claim | unassessed [selected]\ntext: Record c1396 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1389 | decision | adopted [selected]\ntext: Record d1389 about module 3\nchoice: Choice 1389\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d453\"]\n\n### q1382 | question | open [selected]\ntext: Record q1382 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1375 | claim | unassessed [selected]\ntext: Record c1375 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1368 | decision | adopted [selected]\ntext: Record d1368 about module 3\nchoice: Choice 1368\napplicable: false\nblocked_by: [\"d1122\", \"c895\"]\nblocked: d1122 -> c895 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d1122\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c619 | claim | unassessed [selected]\ntext: Record c619 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q1361 | question | open [selected]\ntext: Record q1361 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1354 | claim | unassessed [selected]\ntext: Record c1354 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1347 | decision | adopted [selected]\ntext: Record d1347 about module 3\nchoice: Choice 1347\nscope: [\"lib/mod3/**\"]\n\n### q1340 | question | open [selected]\ntext: Record q1340 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1333 | claim | unassessed [selected]\ntext: Record c1333 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1326 | decision | adopted [selected]\ntext: Record d1326 about module 3\nchoice: Choice 1326\napplicable: false\nblocked_by: [\"c442\"]\nblocked: c442 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c442\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q1319 | question | open [selected]\ntext: Record q1319 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1312 | claim | unassessed [selected]\ntext: Record c1312 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1305 | decision | adopted [selected]\ntext: Record d1305 about module 3\nchoice: Choice 1305\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d822\"]\n\n### q1298 | question | open [selected]\ntext: Record q1298 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1291 | claim | unassessed [selected]\ntext: Record c1291 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1284 | decision | adopted [selected]\ntext: Record d1284 about module 3\nchoice: Choice 1284\nscope: [\"lib/mod3/**\"]\n\n### q1277 | question | open [selected]\ntext: Record q1277 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1270 | claim | unassessed [selected]\ntext: Record c1270 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1263 | decision | adopted [selected]\ntext: Record d1263 about module 3\nchoice: Choice 1263\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d186\"]\n\n### q1256 | question | open [selected]\ntext: Record q1256 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1249 | claim | unassessed [selected]\ntext: Record c1249 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1242 | decision | adopted [selected]\ntext: Record d1242 about module 3\nchoice: Choice 1242\nscope: [\"lib/mod3/**\"]\n\n### q1235 | question | open [selected]\ntext: Record q1235 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1228 | claim | unassessed [selected]\ntext: Record c1228 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1221 | decision | adopted [selected]\ntext: Record d1221 about module 3\nchoice: Choice 1221\nscope: [\"lib/mod3/**\"]\n\n### q1214 | question | open [selected]\ntext: Record q1214 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1207 | claim | unassessed [selected]\ntext: Record c1207 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1200 | decision | adopted [selected]\ntext: Record d1200 about module 3\nchoice: Choice 1200\nscope: [\"lib/mod3/**\"]\n\n### q1193 | question | open [selected]\ntext: Record q1193 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d822 | decision | adopted [selected]\ntext: Record d822 about module 3\nchoice: Choice 822\nscope: [\"lib/mod3/**\"]\n\n### d1179 | decision | adopted [selected]\ntext: Record d1179 about module 3\nchoice: Choice 1179\napplicable: false\nblocked_by: [\"c1012\"]\nblocked: c1012 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c1012\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q1172 | question | open [selected]\ntext: Record q1172 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1165 | claim | unassessed [selected]\ntext: Record c1165 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1158 | decision | adopted [selected]\ntext: Record d1158 about module 3\nchoice: Choice 1158\napplicable: false\nblocked_by: [\"c262\"]\nblocked: c262 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c262\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q1151 | question | open [selected]\ntext: Record q1151 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1144 | claim | unassessed [selected]\ntext: Record c1144 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1137 | decision | adopted [selected]\ntext: Record d1137 about module 3\nchoice: Choice 1137\napplicable: false\nblocked_by: [\"c571\"]\nblocked: c571 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c571\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q1130 | question | open [selected]\ntext: Record q1130 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### c1123 | claim | unassessed [selected]\ntext: Record c1123 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1116 | decision | adopted [selected]\ntext: Record d1116 about module 3\nchoice: Choice 1116\nscope: [\"lib/mod3/**\"]\n\n### q1109 | question | open [selected]\ntext: Record q1109 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1102 | claim | unassessed [selected]\ntext: Record c1102 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c724 | claim | unassessed [selected]\ntext: Record c724 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1095 | decision | adopted [selected]\ntext: Record d1095 about module 3\nchoice: Choice 1095\nscope: [\"lib/mod3/**\"]\n\n### q1088 | question | open [selected]\ntext: Record q1088 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d717 | decision | adopted [selected]\ntext: Record d717 about module 3\nchoice: Choice 717\napplicable: false\nblocked_by: [\"d705\", \"c277\"]\nblocked: d705 -> c277 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d705\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c1081 | claim | unassessed [selected]\ntext: Record c1081 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1074 | decision | adopted [selected]\ntext: Record d1074 about module 3\nchoice: Choice 1074\napplicable: false\nblocked_by: [\"c91\"]\nblocked: c91 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c91\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q1067 | question | open [selected]\ntext: Record q1067 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d696 | decision | adopted [selected]\ntext: Record d696 about module 3\nchoice: Choice 696\napplicable: false\nblocked_by: [\"c583\"]\nblocked: c583 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c583\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c1060 | claim | unassessed [selected]\ntext: Record c1060 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1053 | decision | adopted [selected]\ntext: Record d1053 about module 3\nchoice: Choice 1053\napplicable: false\nblocked_by: [\"d696\", \"c583\"]\nblocked: d696 -> c583 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d696\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q1046 | question | open [selected]\ntext: Record q1046 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d1032 | decision | adopted [selected]\ntext: Record d1032 about module 3\nchoice: Choice 1032\napplicable: false\nblocked_by: [\"c418\"]\nblocked: c418 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c418\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q1025 | question | open [selected]\ntext: Record q1025 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1018 | claim | unassessed [selected]\ntext: Record c1018 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1011 | decision | adopted [selected]\ntext: Record d1011 about module 3\nchoice: Choice 1011\nscope: [\"lib/mod3/**\"]\n\n### q1004 | question | open [selected]\ntext: Record q1004 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c997 | claim | unassessed [selected]\ntext: Record c997 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d990 | decision | adopted [selected]\ntext: Record d990 about module 3\nchoice: Choice 990\nscope: [\"lib/mod3/**\"]\n\n### q983 | question | open [selected]\ntext: Record q983 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d234 | decision | adopted [selected]\ntext: Record d234 about module 3\nchoice: Choice 234\nscope: [\"lib/mod3/**\"]\n\n### c976 | claim | unassessed [selected]\ntext: Record c976 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d969 | decision | adopted [selected]\ntext: Record d969 about module 3\nchoice: Choice 969\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d153\"]\n\n### q962 | question | open [selected]\ntext: Record q962 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c955 | claim | unassessed [selected]\ntext: Record c955 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d948 | decision | adopted [selected]\ntext: Record d948 about module 3\nchoice: Choice 948\napplicable: false\nblocked_by: [\"c844\"]\nblocked: c844 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c844\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q941 | question | open [selected]\ntext: Record q941 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c934 | claim | unassessed [selected]\ntext: Record c934 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d927 | decision | adopted [selected]\ntext: Record d927 about module 3\nchoice: Choice 927\nscope: [\"lib/mod3/**\"]\n\n### q920 | question | open [selected]\ntext: Record q920 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c913 | claim | unassessed [selected]\ntext: Record c913 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d906 | decision | adopted [selected]\ntext: Record d906 about module 3\nchoice: Choice 906\napplicable: false\nblocked_by: [\"c97\"]\nblocked: c97 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c97\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q899 | question | open [selected]\ntext: Record q899 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c892 | claim | unassessed [selected]\ntext: Record c892 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d885 | decision | adopted [selected]\ntext: Record d885 about module 3\nchoice: Choice 885\nscope: [\"lib/mod3/**\"]\n\n### q878 | question | open [selected]\ntext: Record q878 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c871 | claim | unassessed [selected]\ntext: Record c871 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d864 | decision | adopted [selected]\ntext: Record d864 about module 3\nchoice: Choice 864\nscope: [\"lib/mod3/**\"]\n\n### q857 | question | open [selected]\ntext: Record q857 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d486 | decision | adopted [selected]\ntext: Record d486 about module 3\nchoice: Choice 486\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d396\"]\n\n### c850 | claim | unassessed [selected]\ntext: Record c850 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d843 | decision | adopted [selected]\ntext: Record d843 about module 3\nchoice: Choice 843\nscope: [\"lib/mod3/**\"]\n\n### q836 | question | open [selected]\ntext: Record q836 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d465 | decision | adopted [selected]\ntext: Record d465 about module 3\nchoice: Choice 465\nscope: [\"lib/mod3/**\"]\n\n### c829 | claim | unassessed [selected]\ntext: Record c829 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q815 | question | open [selected]\ntext: Record q815 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c808 | claim | unassessed [selected]\ntext: Record c808 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d801 | decision | adopted [selected]\ntext: Record d801 about module 3\nchoice: Choice 801\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d18\"]\n\n### q794 | question | open [selected]\ntext: Record q794 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c787 | claim | unassessed [selected]\ntext: Record c787 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c31 | claim | unassessed [selected]\ntext: Record c31 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d780 | decision | adopted [selected]\ntext: Record d780 about module 3\nchoice: Choice 780\nscope: [\"lib/mod3/**\"]\n\n### q773 | question | open [selected]\ntext: Record q773 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c766 | claim | unassessed [selected]\ntext: Record c766 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d759 | decision | adopted [selected]\ntext: Record d759 about module 3\nchoice: Choice 759\nscope: [\"lib/mod3/**\"]\n\n### q752 | question | open [selected]\ntext: Record q752 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c745 | claim | unassessed [selected]\ntext: Record c745 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d738 | decision | adopted [selected]\ntext: Record d738 about module 3\nchoice: Choice 738\nscope: [\"lib/mod3/**\"]\n\n### q731 | question | open [selected]\ntext: Record q731 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c346 | claim | unassessed [selected]\ntext: Record c346 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q710 | question | open [selected]\ntext: Record q710 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c703 | claim | unassessed [selected]\ntext: Record c703 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d318 | decision | adopted [selected]\ntext: Record d318 about module 3\nchoice: Choice 318\napplicable: false\nblocked_by: [\"c70\"]\nblocked: c70 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c70\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q689 | question | open [selected]\ntext: Record q689 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c682 | claim | unassessed [selected]\ntext: Record c682 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c304 | claim | unassessed [selected]\ntext: Record c304 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d675 | decision | adopted [selected]\ntext: Record d675 about module 3\nchoice: Choice 675\nscope: [\"lib/mod3/**\"]\n\n### q668 | question | open [selected]\ntext: Record q668 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c661 | claim | unassessed [selected]\ntext: Record c661 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d654 | decision | adopted [selected]\ntext: Record d654 about module 3\nchoice: Choice 654\napplicable: false\nblocked_by: [\"c226\"]\nblocked: c226 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c226\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q647 | question | open [selected]\ntext: Record q647 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c640 | claim | unassessed [selected]\ntext: Record c640 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d633 | decision | adopted [selected]\ntext: Record d633 about module 3\nchoice: Choice 633\nscope: [\"lib/mod3/**\"]\n\n### c262 | claim | unassessed [selected]\ntext: Record c262 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q626 | question | open [selected]\ntext: Record q626 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d612 | decision | adopted [selected]\ntext: Record d612 about module 3\nchoice: Choice 612\nscope: [\"lib/mod3/**\"]\n\n### q605 | question | open [selected]\ntext: Record q605 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c598 | claim | unassessed [selected]\ntext: Record c598 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c220 | claim | unassessed [selected]\ntext: Record c220 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# index: 40 more current records\nd591 decision adopted Record d591 about module 3\nq584 question open Record q584 about module 3\nc577 claim unassessed Record c577 about module 3\nd570 decision adopted Record d570 about module 3\nq563 question open Record q563 about module 3\nc556 claim unassessed Record c556 about module 3\nd549 decision adopted Record d549 about module 3\nq542 question open Record q542 about module 3\nc535 claim unassessed Record c535 about module 3\nd528 decision adopted Record d528 about module 3\nq521 question open Record q521 about module 3\nd150 decision adopted Record d150 about module 3\nc514 claim unassessed Record c514 about module 3\nd507 decision adopted Record d507 about module 3\nd129 decision adopted Record d129 about module 3\nq500 question open Record q500 about module 3\nc493 claim unassessed Record c493 about module 3\nc115 claim unassessed Record c115 about module 3\nq479 question open Record q479 about module 3\nc472 claim unassessed Record c472 about module 3\nd87 decision adopted Record d87 about module 3\nq458 question open Record q458 about module 3\nc451 claim unassessed Record c451 about module 3\nd444 decision adopted Record d444 about module 3\nq437 question open Record q437 about module 3\nd66 decision adopted Record d66 about module 3\nc430 claim unassessed Record c430 about module 3\nd423 decision adopted Record d423 about module 3\nq416 question open Record q416 about module 3\nc409 claim unassessed Record c409 about module 3\nd402 decision adopted Record d402 about module 3\nd24 decision adopted Record d24 about module 3\nq395 question open Record q395 about module 3\nc388 claim unassessed Record c388 about module 3\nc10 claim unassessed Record c10 about module 3\nd381 decision adopted Record d381 about module 3\nq374 question open Record q374 about module 3\nc367 claim unassessed Record c367 about module 3\nd360 decision adopted Record d360 about module 3\nq353 question open Record q353 about module 3\n# and 1321 more; docket list\n\n# full text: 139; index: 40; retired: 0.\n# Not listed: 1321; reach them with docket list.\n# Related records in index only: 18; formulas remain complete.\n# Coverage: partial, 469 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n1500_qnone_fyes_b900": "# docket: repo | revision: 48161f778c9d | latest: d1500@48161f778c9d\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n# index: c1186, d1494, q1487, c1480, d1473, q1466, c1459, d1452, q1445, c1438, d1431, q1424, c1417, c1039, d1410, q1403, c1396, d1389, q1382, c1375, d1368, c619, q1361, c1354, d1347, q1340, c1333, d1326, q1319, c1312, d1305, q1298, c1291, d1284, q1277, c1270, d1263, q1256, c1249, d1242\n# and 1460 more; docket list\n\n# full text: 0; index: 40; retired: 0.\n# Not listed: 1460; reach them with docket list.\n# Coverage: partial, 214 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n1500_qnone_fyes_b8000": "# docket: repo | revision: 48161f778c9d | latest: d1500@48161f778c9d\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n### c1186 | claim | unassessed [selected]\ntext: Record c1186 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1494 | decision | adopted [selected]\ntext: Record d1494 about module 3\nchoice: Choice 1494\nscope: [\"lib/mod3/**\"]\n\n### q1487 | question | open [selected]\ntext: Record q1487 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1480 | claim | unassessed [selected]\ntext: Record c1480 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1473 | decision | adopted [selected]\ntext: Record d1473 about module 3\nchoice: Choice 1473\nscope: [\"lib/mod3/**\"]\n\n### q1466 | question | open [selected]\ntext: Record q1466 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1459 | claim | unassessed [selected]\ntext: Record c1459 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1452 | decision | adopted [selected]\ntext: Record d1452 about module 3\nchoice: Choice 1452\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d1170\"]\n\n### q1445 | question | open [selected]\ntext: Record q1445 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1438 | claim | unassessed [selected]\ntext: Record c1438 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1431 | decision | adopted [selected]\ntext: Record d1431 about module 3\nchoice: Choice 1431\nscope: [\"lib/mod3/**\"]\n\n### q1424 | question | open [selected]\ntext: Record q1424 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1417 | claim | unassessed [selected]\ntext: Record c1417 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c1039 | claim | unassessed [selected]\ntext: Record c1039 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1410 | decision | adopted [selected]\ntext: Record d1410 about module 3\nchoice: Choice 1410\nscope: [\"lib/mod3/**\"]\n\n### q1403 | question | open [selected]\ntext: Record q1403 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1396 | claim | unassessed [selected]\ntext: Record c1396 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1389 | decision | adopted [selected]\ntext: Record d1389 about module 3\nchoice: Choice 1389\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d453\"]\n\n### q1382 | question | open [selected]\ntext: Record q1382 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1375 | claim | unassessed [selected]\ntext: Record c1375 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1368 | decision | adopted [selected]\ntext: Record d1368 about module 3\nchoice: Choice 1368\napplicable: false\nblocked_by: [\"d1122\", \"c895\"]\nblocked: d1122 -> c895 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d1122\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c619 | claim | unassessed [selected]\ntext: Record c619 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q1361 | question | open [selected]\ntext: Record q1361 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1354 | claim | unassessed [selected]\ntext: Record c1354 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1347 | decision | adopted [selected]\ntext: Record d1347 about module 3\nchoice: Choice 1347\nscope: [\"lib/mod3/**\"]\n\n### q1340 | question | open [selected]\ntext: Record q1340 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1333 | claim | unassessed [selected]\ntext: Record c1333 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1326 | decision | adopted [selected]\ntext: Record d1326 about module 3\nchoice: Choice 1326\napplicable: false\nblocked_by: [\"c442\"]\nblocked: c442 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c442\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q1319 | question | open [selected]\ntext: Record q1319 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1312 | claim | unassessed [selected]\ntext: Record c1312 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1305 | decision | adopted [selected]\ntext: Record d1305 about module 3\nchoice: Choice 1305\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d822\"]\n\n### q1298 | question | open [selected]\ntext: Record q1298 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1291 | claim | unassessed [selected]\ntext: Record c1291 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1284 | decision | adopted [selected]\ntext: Record d1284 about module 3\nchoice: Choice 1284\nscope: [\"lib/mod3/**\"]\n\n### q1277 | question | open [selected]\ntext: Record q1277 about module 3\nscope: [\"lib/mod3/**\"]\n\n# index: 40 more current records\nc1270 claim unassessed Record c1270 about module 3\nd1263 decision adopted Record d1263 about module 3\nq1256 question open Record q1256 about module 3\nc1249 claim unassessed Record c1249 about module 3\nd1242 decision adopted Record d1242 about module 3\nq1235 question open Record q1235 about module 3\nc1228 claim unassessed Record c1228 about module 3\nd1221 decision adopted Record d1221 about module 3\nq1214 question open Record q1214 about module 3\nc1207 claim unassessed Record c1207 about module 3\nd1200 decision adopted Record d1200 about module 3\nq1193 question open Record q1193 about module 3\nd822 decision adopted Record d822 about module 3\nd1179 decision adopted Record d1179 about module 3\nq1172 question open Record q1172 about module 3\nc1165 claim unassessed Record c1165 about module 3\nd1158 decision adopted Record d1158 about module 3\nq1151 question open Record q1151 about module 3\nc1144 claim unassessed Record c1144 about module 3\nd1137 decision adopted Record d1137 about module 3\nq1130 question open Record q1130 about module 3\nd3 decision adopted Record d3 about module 3\nc1123 claim unassessed Record c1123 about module 3\nd1116 decision adopted Record d1116 about module 3\nq1109 question open Record q1109 about module 3\nc1102 claim unassessed Record c1102 about module 3\nc724 claim unassessed Record c724 about module 3\nd1095 decision adopted Record d1095 about module 3\nq1088 question open Record q1088 about module 3\nd717 decision adopted Record d717 about module 3\nc1081 claim unassessed Record c1081 about module 3\nd1074 decision adopted Record d1074 about module 3\nq1067 question open Record q1067 about module 3\nd696 decision adopted Record d696 about module 3\nc1060 claim unassessed Record c1060 about module 3\nd1053 decision adopted Record d1053 about module 3\nq1046 question open Record q1046 about module 3\nd1032 decision adopted Record d1032 about module 3\nq1025 question open Record q1025 about module 3\nc1018 claim unassessed Record c1018 about module 3\n# and 1425 more; docket list\n\n# full text: 35; index: 40; retired: 0.\n# Not listed: 1425; reach them with docket list.\n# Related records in index only: 5; formulas remain complete.\n# Coverage: partial, 182 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", -"n1500_qnone_fyes_bdefault": "# docket: repo | revision: 48161f778c9d | latest: d1500@48161f778c9d\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n### c1186 | claim | unassessed [selected]\ntext: Record c1186 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1494 | decision | adopted [selected]\ntext: Record d1494 about module 3\nchoice: Choice 1494\nscope: [\"lib/mod3/**\"]\n\n### q1487 | question | open [selected]\ntext: Record q1487 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1480 | claim | unassessed [selected]\ntext: Record c1480 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1473 | decision | adopted [selected]\ntext: Record d1473 about module 3\nchoice: Choice 1473\nscope: [\"lib/mod3/**\"]\n\n### q1466 | question | open [selected]\ntext: Record q1466 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1459 | claim | unassessed [selected]\ntext: Record c1459 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1452 | decision | adopted [selected]\ntext: Record d1452 about module 3\nchoice: Choice 1452\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d1170\"]\n\n### q1445 | question | open [selected]\ntext: Record q1445 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1438 | claim | unassessed [selected]\ntext: Record c1438 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1431 | decision | adopted [selected]\ntext: Record d1431 about module 3\nchoice: Choice 1431\nscope: [\"lib/mod3/**\"]\n\n### q1424 | question | open [selected]\ntext: Record q1424 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1417 | claim | unassessed [selected]\ntext: Record c1417 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c1039 | claim | unassessed [selected]\ntext: Record c1039 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1410 | decision | adopted [selected]\ntext: Record d1410 about module 3\nchoice: Choice 1410\nscope: [\"lib/mod3/**\"]\n\n### q1403 | question | open [selected]\ntext: Record q1403 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1396 | claim | unassessed [selected]\ntext: Record c1396 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1389 | decision | adopted [selected]\ntext: Record d1389 about module 3\nchoice: Choice 1389\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d453\"]\n\n### q1382 | question | open [selected]\ntext: Record q1382 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1375 | claim | unassessed [selected]\ntext: Record c1375 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1368 | decision | adopted [selected]\ntext: Record d1368 about module 3\nchoice: Choice 1368\napplicable: false\nblocked_by: [\"d1122\", \"c895\"]\nblocked: d1122 -> c895 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d1122\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c619 | claim | unassessed [selected]\ntext: Record c619 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q1361 | question | open [selected]\ntext: Record q1361 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1354 | claim | unassessed [selected]\ntext: Record c1354 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1347 | decision | adopted [selected]\ntext: Record d1347 about module 3\nchoice: Choice 1347\nscope: [\"lib/mod3/**\"]\n\n### q1340 | question | open [selected]\ntext: Record q1340 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1333 | claim | unassessed [selected]\ntext: Record c1333 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1326 | decision | adopted [selected]\ntext: Record d1326 about module 3\nchoice: Choice 1326\napplicable: false\nblocked_by: [\"c442\"]\nblocked: c442 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c442\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q1319 | question | open [selected]\ntext: Record q1319 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1312 | claim | unassessed [selected]\ntext: Record c1312 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1305 | decision | adopted [selected]\ntext: Record d1305 about module 3\nchoice: Choice 1305\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d822\"]\n\n### q1298 | question | open [selected]\ntext: Record q1298 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c1291 | claim | unassessed [selected]\ntext: Record c1291 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1284 | decision | adopted [selected]\ntext: Record d1284 about module 3\nchoice: Choice 1284\nscope: [\"lib/mod3/**\"]\n\n### q1277 | question | open [selected]\ntext: Record q1277 about module 3\nscope: [\"lib/mod3/**\"]\n\n# index: 40 more current records\nc1270 claim unassessed Record c1270 about module 3\nd1263 decision adopted Record d1263 about module 3\nq1256 question open Record q1256 about module 3\nc1249 claim unassessed Record c1249 about module 3\nd1242 decision adopted Record d1242 about module 3\nq1235 question open Record q1235 about module 3\nc1228 claim unassessed Record c1228 about module 3\nd1221 decision adopted Record d1221 about module 3\nq1214 question open Record q1214 about module 3\nc1207 claim unassessed Record c1207 about module 3\nd1200 decision adopted Record d1200 about module 3\nq1193 question open Record q1193 about module 3\nd822 decision adopted Record d822 about module 3\nd1179 decision adopted Record d1179 about module 3\nq1172 question open Record q1172 about module 3\nc1165 claim unassessed Record c1165 about module 3\nd1158 decision adopted Record d1158 about module 3\nq1151 question open Record q1151 about module 3\nc1144 claim unassessed Record c1144 about module 3\nd1137 decision adopted Record d1137 about module 3\nq1130 question open Record q1130 about module 3\nd3 decision adopted Record d3 about module 3\nc1123 claim unassessed Record c1123 about module 3\nd1116 decision adopted Record d1116 about module 3\nq1109 question open Record q1109 about module 3\nc1102 claim unassessed Record c1102 about module 3\nc724 claim unassessed Record c724 about module 3\nd1095 decision adopted Record d1095 about module 3\nq1088 question open Record q1088 about module 3\nd717 decision adopted Record d717 about module 3\nc1081 claim unassessed Record c1081 about module 3\nd1074 decision adopted Record d1074 about module 3\nq1067 question open Record q1067 about module 3\nd696 decision adopted Record d696 about module 3\nc1060 claim unassessed Record c1060 about module 3\nd1053 decision adopted Record d1053 about module 3\nq1046 question open Record q1046 about module 3\nd1032 decision adopted Record d1032 about module 3\nq1025 question open Record q1025 about module 3\nc1018 claim unassessed Record c1018 about module 3\n# and 1425 more; docket list\n\n# full text: 35; index: 40; retired: 0.\n# Not listed: 1425; reach them with docket list.\n# Related records in index only: 5; formulas remain complete.\n# Coverage: partial, 182 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n" +"n5_qnone_fno_b900": "# docket: repo | revision: 48bf2994aa90 | latest: q2@48bf2994aa90\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n### q2 | question | open [selected]\ntext: Record q2 about module 5\nscope: [\"lib/mod5/**\"]\n\n### d1 | decision | adopted [selected]\ntext: Record d1 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### q1 | question | open [selected]\ntext: Record q1 about module 2\nscope: [\"lib/mod2/**\"]\n\n# index: 2 more current records\nc2 claim unassessed Record c2 about module 4\nc1 claim unassessed Record c1 about module 1\n\n# full text: 3; index: 2; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n5_qnone_fno_b8000": "# docket: repo | revision: 48bf2994aa90 | latest: q2@48bf2994aa90\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n### q2 | question | open [selected]\ntext: Record q2 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c2 | claim | unassessed [selected]\ntext: Record c2 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1 | decision | adopted [selected]\ntext: Record d1 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### q1 | question | open [selected]\ntext: Record q1 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c1 | claim | unassessed [selected]\ntext: Record c1 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# full text: 5; index: 0; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n5_qnone_fno_bdefault": "# docket: repo | revision: 48bf2994aa90 | latest: q2@48bf2994aa90\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n### q2 | question | open [selected]\ntext: Record q2 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c2 | claim | unassessed [selected]\ntext: Record c2 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1 | decision | adopted [selected]\ntext: Record d1 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### q1 | question | open [selected]\ntext: Record q1 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c1 | claim | unassessed [selected]\ntext: Record c1 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# full text: 5; index: 0; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n5_qmodule 3_fno_b900": "# docket: repo | revision: 48bf2994aa90 | latest: q2@48bf2994aa90\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n### d1 | decision | adopted [selected]\ntext: Record d1 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### q2 | question | open [selected]\ntext: Record q2 about module 5\nscope: [\"lib/mod5/**\"]\n\n### q1 | question | open [selected]\ntext: Record q1 about module 2\nscope: [\"lib/mod2/**\"]\n\n# index: 2 more current records\nc2 claim unassessed Record c2 about module 4\nc1 claim unassessed Record c1 about module 1\n\n# full text: 3; index: 2; retired: 0.\n# Coverage: partial, 2 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n5_qmodule 3_fno_b8000": "# docket: repo | revision: 48bf2994aa90 | latest: q2@48bf2994aa90\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n### d1 | decision | adopted [selected]\ntext: Record d1 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### q2 | question | open [selected]\ntext: Record q2 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c2 | claim | unassessed [selected]\ntext: Record c2 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q1 | question | open [selected]\ntext: Record q1 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c1 | claim | unassessed [selected]\ntext: Record c1 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# full text: 5; index: 0; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n5_qmodule 3_fno_bdefault": "# docket: repo | revision: 48bf2994aa90 | latest: q2@48bf2994aa90\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n### d1 | decision | adopted [selected]\ntext: Record d1 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### q2 | question | open [selected]\ntext: Record q2 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c2 | claim | unassessed [selected]\ntext: Record c2 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q1 | question | open [selected]\ntext: Record q1 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c1 | claim | unassessed [selected]\ntext: Record c1 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# full text: 5; index: 0; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n5_qnone_fyes_b900": "# docket: repo | revision: 48bf2994aa90 | latest: q2@48bf2994aa90\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n### d1 | decision | adopted [selected]\ntext: Record d1 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n# index: 4 more current records\nq2 question open Record q2 about module 5\nc2 claim unassessed Record c2 about module 4\nq1 question open Record q1 about module 2\nc1 claim unassessed Record c1 about module 1\n\n# full text: 1; index: 4; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n5_qnone_fyes_b8000": "# docket: repo | revision: 48bf2994aa90 | latest: q2@48bf2994aa90\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n### d1 | decision | adopted [selected]\ntext: Record d1 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n# index: 4 more current records\nq2 question open Record q2 about module 5\nc2 claim unassessed Record c2 about module 4\nq1 question open Record q1 about module 2\nc1 claim unassessed Record c1 about module 1\n\n# full text: 1; index: 4; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n5_qnone_fyes_bdefault": "# docket: repo | revision: 48bf2994aa90 | latest: q2@48bf2994aa90\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n### d1 | decision | adopted [selected]\ntext: Record d1 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n# index: 4 more current records\nq2 question open Record q2 about module 5\nc2 claim unassessed Record c2 about module 4\nq1 question open Record q1 about module 2\nc1 claim unassessed Record c1 about module 1\n\n# full text: 1; index: 4; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n60_qnone_fno_b900": "# docket: repo | revision: 1318945994d0 | latest: d20@1318945994d0\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n# index: d20, q20, c20, d19, q19, c19, d18, q18, c18, d17, q17, c17, d16, d6, q16, c16, d15, q15, c15, d14, q14, c14, d13, q13, c13, d12, q12, c12, c2, d11, q11, c11, c6, d10, q10, c10, d9, q9, c9, d8\n# and 20 more; docket list\n\n# full text: 0; index: 40; retired: 0.\n# Not listed: 20; reach them with docket list.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n60_qnone_fno_b8000": "# docket: repo | revision: 1318945994d0 | latest: d20@1318945994d0\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n### d20 | decision | adopted [selected]\ntext: Record d20 about module 4\nchoice: Choice 60\napplicable: false\nblocked_by: [\"d2\", \"c2\"]\nblocked: d2 -> c2 unassessed\nscope: [\"lib/mod4/**\"]\ndepends_on: [\"d2\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q20 | question | open [selected]\ntext: Record q20 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c20 | claim | unassessed [selected]\ntext: Record c20 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d19 | decision | adopted [selected]\ntext: Record d19 about module 1\nchoice: Choice 57\napplicable: false\nblocked_by: [\"c2\"]\nblocked: c2 unassessed\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"c2\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q19 | question | open [selected]\ntext: Record q19 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c19 | claim | unassessed [selected]\ntext: Record c19 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d18 | decision | adopted [selected]\ntext: Record d18 about module 5\nchoice: Choice 54\nscope: [\"lib/mod5/**\"]\n\n### q18 | question | open [selected]\ntext: Record q18 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c18 | claim | unassessed [selected]\ntext: Record c18 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d17 | decision | adopted [selected]\ntext: Record d17 about module 2\nchoice: Choice 51\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"d6\"]\n\n### q17 | question | open [selected]\ntext: Record q17 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c17 | claim | unassessed [selected]\ntext: Record c17 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d16 | decision | adopted [selected]\ntext: Record d16 about module 6\nchoice: Choice 48\nscope: [\"lib/mod6/**\"]\n\n### d6 | decision | adopted [selected]\ntext: Record d6 about module 4\nchoice: Choice 18\nscope: [\"lib/mod4/**\"]\n\n### q16 | question | open [selected]\ntext: Record q16 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c16 | claim | unassessed [selected]\ntext: Record c16 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d15 | decision | adopted [selected]\ntext: Record d15 about module 3\nchoice: Choice 45\nscope: [\"lib/mod3/**\"]\n\n### q15 | question | open [selected]\ntext: Record q15 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c15 | claim | unassessed [selected]\ntext: Record c15 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d14 | decision | adopted [selected]\ntext: Record d14 about module 0\nchoice: Choice 42\nscope: [\"lib/mod0/**\"]\n\n### q14 | question | open [selected]\ntext: Record q14 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c14 | claim | unassessed [selected]\ntext: Record c14 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d13 | decision | adopted [selected]\ntext: Record d13 about module 4\nchoice: Choice 39\nscope: [\"lib/mod4/**\"]\n\n### q13 | question | open [selected]\ntext: Record q13 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c13 | claim | unassessed [selected]\ntext: Record c13 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d12 | decision | adopted [selected]\ntext: Record d12 about module 1\nchoice: Choice 36\nscope: [\"lib/mod1/**\"]\n\n### q12 | question | open [selected]\ntext: Record q12 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c12 | claim | unassessed [selected]\ntext: Record c12 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c2 | claim | unassessed [selected]\ntext: Record c2 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d11 | decision | adopted [selected]\ntext: Record d11 about module 5\nchoice: Choice 33\nscope: [\"lib/mod5/**\"]\ndepends_on: [\"d3\"]\n\n### q11 | question | open [selected]\ntext: Record q11 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c11 | claim | unassessed [selected]\ntext: Record c11 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c6 | claim | unassessed [selected]\ntext: Record c6 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d10 | decision | adopted [selected]\ntext: Record d10 about module 2\nchoice: Choice 30\nscope: [\"lib/mod2/**\"]\n\n### q10 | question | open [selected]\ntext: Record q10 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c10 | claim | unassessed [selected]\ntext: Record c10 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d9 | decision | adopted [selected]\ntext: Record d9 about module 6\nchoice: Choice 27\nscope: [\"lib/mod6/**\"]\n\n### q9 | question | open [selected]\ntext: Record q9 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c9 | claim | unassessed [selected]\ntext: Record c9 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d8 | decision | adopted [selected]\ntext: Record d8 about module 3\nchoice: Choice 24\napplicable: false\nblocked_by: [\"c6\"]\nblocked: c6 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c6\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 2\nchoice: Choice 9\nscope: [\"lib/mod2/**\"]\n\n### q8 | question | open [selected]\ntext: Record q8 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c8 | claim | unassessed [selected]\ntext: Record c8 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d7 | decision | adopted [selected]\ntext: Record d7 about module 0\nchoice: Choice 21\nscope: [\"lib/mod0/**\"]\ndepends_on: [\"d6\"]\n\n### d2 | decision | adopted [selected]\ntext: Record d2 about module 6\nchoice: Choice 6\napplicable: false\nblocked_by: [\"c2\"]\nblocked: c2 unassessed\nscope: [\"lib/mod6/**\"]\ndepends_on: [\"c2\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q7 | question | open [selected]\ntext: Record q7 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c7 | claim | unassessed [selected]\ntext: Record c7 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# index: 13 more current records\nq6 question open Record q6 about module 3\nd5 decision adopted Record d5 about module 1\nq5 question open Record q5 about module 0\nc5 claim unassessed Record c5 about module 6\nd4 decision adopted Record d4 about module 5\nq4 question open Record q4 about module 4\nc4 claim unassessed Record c4 about module 3\nq3 question open Record q3 about module 1\nc3 claim unassessed Record c3 about module 0\nq2 question open Record q2 about module 5\nd1 decision adopted Record d1 about module 3\nq1 question open Record q1 about module 2\nc1 claim unassessed Record c1 about module 1\n\n# full text: 47; index: 13; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n60_qnone_fno_bdefault": "# docket: repo | revision: 1318945994d0 | latest: d20@1318945994d0\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n### d20 | decision | adopted [selected]\ntext: Record d20 about module 4\nchoice: Choice 60\napplicable: false\nblocked_by: [\"d2\", \"c2\"]\nblocked: d2 -> c2 unassessed\nscope: [\"lib/mod4/**\"]\ndepends_on: [\"d2\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q20 | question | open [selected]\ntext: Record q20 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c20 | claim | unassessed [selected]\ntext: Record c20 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d19 | decision | adopted [selected]\ntext: Record d19 about module 1\nchoice: Choice 57\napplicable: false\nblocked_by: [\"c2\"]\nblocked: c2 unassessed\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"c2\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q19 | question | open [selected]\ntext: Record q19 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c19 | claim | unassessed [selected]\ntext: Record c19 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d18 | decision | adopted [selected]\ntext: Record d18 about module 5\nchoice: Choice 54\nscope: [\"lib/mod5/**\"]\n\n### q18 | question | open [selected]\ntext: Record q18 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c18 | claim | unassessed [selected]\ntext: Record c18 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d17 | decision | adopted [selected]\ntext: Record d17 about module 2\nchoice: Choice 51\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"d6\"]\n\n### q17 | question | open [selected]\ntext: Record q17 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c17 | claim | unassessed [selected]\ntext: Record c17 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d16 | decision | adopted [selected]\ntext: Record d16 about module 6\nchoice: Choice 48\nscope: [\"lib/mod6/**\"]\n\n### d6 | decision | adopted [selected]\ntext: Record d6 about module 4\nchoice: Choice 18\nscope: [\"lib/mod4/**\"]\n\n### q16 | question | open [selected]\ntext: Record q16 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c16 | claim | unassessed [selected]\ntext: Record c16 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d15 | decision | adopted [selected]\ntext: Record d15 about module 3\nchoice: Choice 45\nscope: [\"lib/mod3/**\"]\n\n### q15 | question | open [selected]\ntext: Record q15 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c15 | claim | unassessed [selected]\ntext: Record c15 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d14 | decision | adopted [selected]\ntext: Record d14 about module 0\nchoice: Choice 42\nscope: [\"lib/mod0/**\"]\n\n### q14 | question | open [selected]\ntext: Record q14 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c14 | claim | unassessed [selected]\ntext: Record c14 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d13 | decision | adopted [selected]\ntext: Record d13 about module 4\nchoice: Choice 39\nscope: [\"lib/mod4/**\"]\n\n### q13 | question | open [selected]\ntext: Record q13 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c13 | claim | unassessed [selected]\ntext: Record c13 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d12 | decision | adopted [selected]\ntext: Record d12 about module 1\nchoice: Choice 36\nscope: [\"lib/mod1/**\"]\n\n### q12 | question | open [selected]\ntext: Record q12 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c12 | claim | unassessed [selected]\ntext: Record c12 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c2 | claim | unassessed [selected]\ntext: Record c2 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d11 | decision | adopted [selected]\ntext: Record d11 about module 5\nchoice: Choice 33\nscope: [\"lib/mod5/**\"]\ndepends_on: [\"d3\"]\n\n### q11 | question | open [selected]\ntext: Record q11 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c11 | claim | unassessed [selected]\ntext: Record c11 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c6 | claim | unassessed [selected]\ntext: Record c6 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d10 | decision | adopted [selected]\ntext: Record d10 about module 2\nchoice: Choice 30\nscope: [\"lib/mod2/**\"]\n\n### q10 | question | open [selected]\ntext: Record q10 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c10 | claim | unassessed [selected]\ntext: Record c10 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d9 | decision | adopted [selected]\ntext: Record d9 about module 6\nchoice: Choice 27\nscope: [\"lib/mod6/**\"]\n\n### q9 | question | open [selected]\ntext: Record q9 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c9 | claim | unassessed [selected]\ntext: Record c9 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d8 | decision | adopted [selected]\ntext: Record d8 about module 3\nchoice: Choice 24\napplicable: false\nblocked_by: [\"c6\"]\nblocked: c6 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c6\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 2\nchoice: Choice 9\nscope: [\"lib/mod2/**\"]\n\n### q8 | question | open [selected]\ntext: Record q8 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c8 | claim | unassessed [selected]\ntext: Record c8 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d7 | decision | adopted [selected]\ntext: Record d7 about module 0\nchoice: Choice 21\nscope: [\"lib/mod0/**\"]\ndepends_on: [\"d6\"]\n\n### d2 | decision | adopted [selected]\ntext: Record d2 about module 6\nchoice: Choice 6\napplicable: false\nblocked_by: [\"c2\"]\nblocked: c2 unassessed\nscope: [\"lib/mod6/**\"]\ndepends_on: [\"c2\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q7 | question | open [selected]\ntext: Record q7 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c7 | claim | unassessed [selected]\ntext: Record c7 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# index: 13 more current records\nq6 question open Record q6 about module 3\nd5 decision adopted Record d5 about module 1\nq5 question open Record q5 about module 0\nc5 claim unassessed Record c5 about module 6\nd4 decision adopted Record d4 about module 5\nq4 question open Record q4 about module 4\nc4 claim unassessed Record c4 about module 3\nq3 question open Record q3 about module 1\nc3 claim unassessed Record c3 about module 0\nq2 question open Record q2 about module 5\nd1 decision adopted Record d1 about module 3\nq1 question open Record q1 about module 2\nc1 claim unassessed Record c1 about module 1\n\n# full text: 47; index: 13; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n60_qmodule 3_fno_b900": "# docket: repo | revision: 1318945994d0 | latest: d20@1318945994d0\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n# index: q20, c18, d15, q13, c11, d8, q6, c4, d1, d13, c13, d12, d11, d10, d3, q3, c3, d20, c20, d19, q19, c19, d18, q18, d17, q17, c17, d16, d6, q16, c16, q15, c15, d14, q14, c14, q12, c12, c2, q11\n# and 20 more; docket list\n\n# full text: 0; index: 40; retired: 0.\n# Not listed: 20; reach them with docket list.\n# Coverage: partial, 60 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n60_qmodule 3_fno_b8000": "# docket: repo | revision: 1318945994d0 | latest: d20@1318945994d0\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n### q20 | question | open [selected]\ntext: Record q20 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c18 | claim | unassessed [selected]\ntext: Record c18 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d15 | decision | adopted [selected]\ntext: Record d15 about module 3\nchoice: Choice 45\nscope: [\"lib/mod3/**\"]\n\n### q13 | question | open [selected]\ntext: Record q13 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c11 | claim | unassessed [selected]\ntext: Record c11 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d8 | decision | adopted [selected]\ntext: Record d8 about module 3\nchoice: Choice 24\napplicable: false\nblocked_by: [\"c6\"]\nblocked: c6 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c6\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q6 | question | open [selected]\ntext: Record q6 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c4 | claim | unassessed [selected]\ntext: Record c4 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1 | decision | adopted [selected]\ntext: Record d1 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### d13 | decision | adopted [selected]\ntext: Record d13 about module 4\nchoice: Choice 39\nscope: [\"lib/mod4/**\"]\n\n### c13 | claim | unassessed [selected]\ntext: Record c13 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d12 | decision | adopted [selected]\ntext: Record d12 about module 1\nchoice: Choice 36\nscope: [\"lib/mod1/**\"]\n\n### d11 | decision | adopted [selected]\ntext: Record d11 about module 5\nchoice: Choice 33\nscope: [\"lib/mod5/**\"]\ndepends_on: [\"d3\"]\n\n### d10 | decision | adopted [selected]\ntext: Record d10 about module 2\nchoice: Choice 30\nscope: [\"lib/mod2/**\"]\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 2\nchoice: Choice 9\nscope: [\"lib/mod2/**\"]\n\n### q3 | question | open [selected]\ntext: Record q3 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c3 | claim | unassessed [selected]\ntext: Record c3 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d20 | decision | adopted [selected]\ntext: Record d20 about module 4\nchoice: Choice 60\napplicable: false\nblocked_by: [\"d2\", \"c2\"]\nblocked: d2 -> c2 unassessed\nscope: [\"lib/mod4/**\"]\ndepends_on: [\"d2\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c20 | claim | unassessed [selected]\ntext: Record c20 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d19 | decision | adopted [selected]\ntext: Record d19 about module 1\nchoice: Choice 57\napplicable: false\nblocked_by: [\"c2\"]\nblocked: c2 unassessed\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"c2\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q19 | question | open [selected]\ntext: Record q19 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c19 | claim | unassessed [selected]\ntext: Record c19 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d18 | decision | adopted [selected]\ntext: Record d18 about module 5\nchoice: Choice 54\nscope: [\"lib/mod5/**\"]\n\n### q18 | question | open [selected]\ntext: Record q18 about module 4\nscope: [\"lib/mod4/**\"]\n\n### d17 | decision | adopted [selected]\ntext: Record d17 about module 2\nchoice: Choice 51\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"d6\"]\n\n### q17 | question | open [selected]\ntext: Record q17 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c17 | claim | unassessed [selected]\ntext: Record c17 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d16 | decision | adopted [selected]\ntext: Record d16 about module 6\nchoice: Choice 48\nscope: [\"lib/mod6/**\"]\n\n### d6 | decision | adopted [selected]\ntext: Record d6 about module 4\nchoice: Choice 18\nscope: [\"lib/mod4/**\"]\n\n### q16 | question | open [selected]\ntext: Record q16 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c16 | claim | unassessed [selected]\ntext: Record c16 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q15 | question | open [selected]\ntext: Record q15 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c15 | claim | unassessed [selected]\ntext: Record c15 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d14 | decision | adopted [selected]\ntext: Record d14 about module 0\nchoice: Choice 42\nscope: [\"lib/mod0/**\"]\n\n### q14 | question | open [selected]\ntext: Record q14 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c14 | claim | unassessed [selected]\ntext: Record c14 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q12 | question | open [selected]\ntext: Record q12 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c12 | claim | unassessed [selected]\ntext: Record c12 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c2 | claim | unassessed [selected]\ntext: Record c2 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q11 | question | open [selected]\ntext: Record q11 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c6 | claim | unassessed [selected]\ntext: Record c6 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q10 | question | open [selected]\ntext: Record q10 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c10 | claim | unassessed [selected]\ntext: Record c10 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d9 | decision | adopted [selected]\ntext: Record d9 about module 6\nchoice: Choice 27\nscope: [\"lib/mod6/**\"]\n\n### q9 | question | open [selected]\ntext: Record q9 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c9 | claim | unassessed [selected]\ntext: Record c9 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q8 | question | open [selected]\ntext: Record q8 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c8 | claim | unassessed [selected]\ntext: Record c8 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# index: 12 more current records\nd7 decision adopted Record d7 about module 0\nd2 decision adopted Record d2 about module 6\nq7 question open Record q7 about module 6\nc7 claim unassessed Record c7 about module 5\nd5 decision adopted Record d5 about module 1\nq5 question open Record q5 about module 0\nc5 claim unassessed Record c5 about module 6\nd4 decision adopted Record d4 about module 5\nq4 question open Record q4 about module 4\nq2 question open Record q2 about module 5\nq1 question open Record q1 about module 2\nc1 claim unassessed Record c1 about module 1\n\n# full text: 48; index: 12; retired: 0.\n# Related records in index only: 1; formulas remain complete.\n# Coverage: partial, 12 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n60_qmodule 3_fno_bdefault": "# docket: repo | revision: 1318945994d0 | latest: d20@1318945994d0\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n### q20 | question | open [selected]\ntext: Record q20 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c18 | claim | unassessed [selected]\ntext: Record c18 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d15 | decision | adopted [selected]\ntext: Record d15 about module 3\nchoice: Choice 45\nscope: [\"lib/mod3/**\"]\n\n### q13 | question | open [selected]\ntext: Record q13 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c11 | claim | unassessed [selected]\ntext: Record c11 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d8 | decision | adopted [selected]\ntext: Record d8 about module 3\nchoice: Choice 24\napplicable: false\nblocked_by: [\"c6\"]\nblocked: c6 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c6\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q6 | question | open [selected]\ntext: Record q6 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c4 | claim | unassessed [selected]\ntext: Record c4 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1 | decision | adopted [selected]\ntext: Record d1 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### d13 | decision | adopted [selected]\ntext: Record d13 about module 4\nchoice: Choice 39\nscope: [\"lib/mod4/**\"]\n\n### c13 | claim | unassessed [selected]\ntext: Record c13 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d12 | decision | adopted [selected]\ntext: Record d12 about module 1\nchoice: Choice 36\nscope: [\"lib/mod1/**\"]\n\n### d11 | decision | adopted [selected]\ntext: Record d11 about module 5\nchoice: Choice 33\nscope: [\"lib/mod5/**\"]\ndepends_on: [\"d3\"]\n\n### d10 | decision | adopted [selected]\ntext: Record d10 about module 2\nchoice: Choice 30\nscope: [\"lib/mod2/**\"]\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 2\nchoice: Choice 9\nscope: [\"lib/mod2/**\"]\n\n### q3 | question | open [selected]\ntext: Record q3 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c3 | claim | unassessed [selected]\ntext: Record c3 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d20 | decision | adopted [selected]\ntext: Record d20 about module 4\nchoice: Choice 60\napplicable: false\nblocked_by: [\"d2\", \"c2\"]\nblocked: d2 -> c2 unassessed\nscope: [\"lib/mod4/**\"]\ndepends_on: [\"d2\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c20 | claim | unassessed [selected]\ntext: Record c20 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d19 | decision | adopted [selected]\ntext: Record d19 about module 1\nchoice: Choice 57\napplicable: false\nblocked_by: [\"c2\"]\nblocked: c2 unassessed\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"c2\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q19 | question | open [selected]\ntext: Record q19 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c19 | claim | unassessed [selected]\ntext: Record c19 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d18 | decision | adopted [selected]\ntext: Record d18 about module 5\nchoice: Choice 54\nscope: [\"lib/mod5/**\"]\n\n### q18 | question | open [selected]\ntext: Record q18 about module 4\nscope: [\"lib/mod4/**\"]\n\n### d17 | decision | adopted [selected]\ntext: Record d17 about module 2\nchoice: Choice 51\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"d6\"]\n\n### q17 | question | open [selected]\ntext: Record q17 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c17 | claim | unassessed [selected]\ntext: Record c17 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d16 | decision | adopted [selected]\ntext: Record d16 about module 6\nchoice: Choice 48\nscope: [\"lib/mod6/**\"]\n\n### d6 | decision | adopted [selected]\ntext: Record d6 about module 4\nchoice: Choice 18\nscope: [\"lib/mod4/**\"]\n\n### q16 | question | open [selected]\ntext: Record q16 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c16 | claim | unassessed [selected]\ntext: Record c16 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q15 | question | open [selected]\ntext: Record q15 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c15 | claim | unassessed [selected]\ntext: Record c15 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d14 | decision | adopted [selected]\ntext: Record d14 about module 0\nchoice: Choice 42\nscope: [\"lib/mod0/**\"]\n\n### q14 | question | open [selected]\ntext: Record q14 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c14 | claim | unassessed [selected]\ntext: Record c14 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q12 | question | open [selected]\ntext: Record q12 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c12 | claim | unassessed [selected]\ntext: Record c12 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c2 | claim | unassessed [selected]\ntext: Record c2 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q11 | question | open [selected]\ntext: Record q11 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c6 | claim | unassessed [selected]\ntext: Record c6 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q10 | question | open [selected]\ntext: Record q10 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c10 | claim | unassessed [selected]\ntext: Record c10 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d9 | decision | adopted [selected]\ntext: Record d9 about module 6\nchoice: Choice 27\nscope: [\"lib/mod6/**\"]\n\n### q9 | question | open [selected]\ntext: Record q9 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c9 | claim | unassessed [selected]\ntext: Record c9 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q8 | question | open [selected]\ntext: Record q8 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c8 | claim | unassessed [selected]\ntext: Record c8 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d7 | decision | adopted [selected]\ntext: Record d7 about module 0\nchoice: Choice 21\nscope: [\"lib/mod0/**\"]\ndepends_on: [\"d6\"]\n\n### d2 | decision | adopted [selected]\ntext: Record d2 about module 6\nchoice: Choice 6\napplicable: false\nblocked_by: [\"c2\"]\nblocked: c2 unassessed\nscope: [\"lib/mod6/**\"]\ndepends_on: [\"c2\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q7 | question | open [selected]\ntext: Record q7 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c7 | claim | unassessed [selected]\ntext: Record c7 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d5 | decision | adopted [selected]\ntext: Record d5 about module 1\nchoice: Choice 15\nscope: [\"lib/mod1/**\"]\n\n### q5 | question | open [selected]\ntext: Record q5 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c5 | claim | unassessed [selected]\ntext: Record c5 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d4 | decision | adopted [selected]\ntext: Record d4 about module 5\nchoice: Choice 12\nscope: [\"lib/mod5/**\"]\n\n### q4 | question | open [selected]\ntext: Record q4 about module 4\nscope: [\"lib/mod4/**\"]\n\n### q2 | question | open [selected]\ntext: Record q2 about module 5\nscope: [\"lib/mod5/**\"]\n\n### q1 | question | open [selected]\ntext: Record q1 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c1 | claim | unassessed [selected]\ntext: Record c1 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# full text: 60; index: 0; retired: 0.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n60_qnone_fyes_b900": "# docket: repo | revision: 1318945994d0 | latest: d20@1318945994d0\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n# index: q20, c18, d15, q13, c11, d8, q6, c4, d1, d20, c20, d19, q19, c19, d18, q18, d17, q17, c17, d16, d6, q16, c16, q15, c15, d14, q14, c14, d13, c13, d12, q12, c12, c2, d11, q11, c6, d10, q10, c10\n# and 20 more; docket list\n\n# full text: 0; index: 40; retired: 0.\n# Not listed: 20; reach them with docket list.\n# Coverage: partial, 9 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n60_qnone_fyes_b8000": "# docket: repo | revision: 1318945994d0 | latest: d20@1318945994d0\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n### q20 | question | open [selected]\ntext: Record q20 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c18 | claim | unassessed [selected]\ntext: Record c18 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d15 | decision | adopted [selected]\ntext: Record d15 about module 3\nchoice: Choice 45\nscope: [\"lib/mod3/**\"]\n\n### q13 | question | open [selected]\ntext: Record q13 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c11 | claim | unassessed [selected]\ntext: Record c11 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d8 | decision | adopted [selected]\ntext: Record d8 about module 3\nchoice: Choice 24\napplicable: false\nblocked_by: [\"c6\"]\nblocked: c6 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c6\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q6 | question | open [selected]\ntext: Record q6 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c4 | claim | unassessed [selected]\ntext: Record c4 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1 | decision | adopted [selected]\ntext: Record d1 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### c6 | claim | unassessed [blocking prerequisite]\ntext: Record c6 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# index: 40 more current records\nd20 decision adopted Record d20 about module 4\nc20 claim unassessed Record c20 about module 2\nd19 decision adopted Record d19 about module 1\nq19 question open Record q19 about module 0\nc19 claim unassessed Record c19 about module 6\nd18 decision adopted Record d18 about module 5\nq18 question open Record q18 about module 4\nd17 decision adopted Record d17 about module 2\nq17 question open Record q17 about module 1\nc17 claim unassessed Record c17 about module 0\nd16 decision adopted Record d16 about module 6\nd6 decision adopted Record d6 about module 4\nq16 question open Record q16 about module 5\nc16 claim unassessed Record c16 about module 4\nq15 question open Record q15 about module 2\nc15 claim unassessed Record c15 about module 1\nd14 decision adopted Record d14 about module 0\nq14 question open Record q14 about module 6\nc14 claim unassessed Record c14 about module 5\nd13 decision adopted Record d13 about module 4\nc13 claim unassessed Record c13 about module 2\nd12 decision adopted Record d12 about module 1\nq12 question open Record q12 about module 0\nc12 claim unassessed Record c12 about module 6\nc2 claim unassessed Record c2 about module 4\nd11 decision adopted Record d11 about module 5\nq11 question open Record q11 about module 4\nd10 decision adopted Record d10 about module 2\nq10 question open Record q10 about module 1\nc10 claim unassessed Record c10 about module 0\nd9 decision adopted Record d9 about module 6\nq9 question open Record q9 about module 5\nc9 claim unassessed Record c9 about module 4\nd3 decision adopted Record d3 about module 2\nq8 question open Record q8 about module 2\nc8 claim unassessed Record c8 about module 1\nd7 decision adopted Record d7 about module 0\nd2 decision adopted Record d2 about module 6\nq7 question open Record q7 about module 6\nc7 claim unassessed Record c7 about module 5\n# and 10 more; docket list\n\n# full text: 10; index: 40; retired: 0.\n# Not listed: 10; reach them with docket list.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n60_qnone_fyes_bdefault": "# docket: repo | revision: 1318945994d0 | latest: d20@1318945994d0\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n### q20 | question | open [selected]\ntext: Record q20 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c18 | claim | unassessed [selected]\ntext: Record c18 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d15 | decision | adopted [selected]\ntext: Record d15 about module 3\nchoice: Choice 45\nscope: [\"lib/mod3/**\"]\n\n### q13 | question | open [selected]\ntext: Record q13 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c11 | claim | unassessed [selected]\ntext: Record c11 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d8 | decision | adopted [selected]\ntext: Record d8 about module 3\nchoice: Choice 24\napplicable: false\nblocked_by: [\"c6\"]\nblocked: c6 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c6\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q6 | question | open [selected]\ntext: Record q6 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c4 | claim | unassessed [selected]\ntext: Record c4 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d1 | decision | adopted [selected]\ntext: Record d1 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### c6 | claim | unassessed [blocking prerequisite]\ntext: Record c6 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# index: 40 more current records\nd20 decision adopted Record d20 about module 4\nc20 claim unassessed Record c20 about module 2\nd19 decision adopted Record d19 about module 1\nq19 question open Record q19 about module 0\nc19 claim unassessed Record c19 about module 6\nd18 decision adopted Record d18 about module 5\nq18 question open Record q18 about module 4\nd17 decision adopted Record d17 about module 2\nq17 question open Record q17 about module 1\nc17 claim unassessed Record c17 about module 0\nd16 decision adopted Record d16 about module 6\nd6 decision adopted Record d6 about module 4\nq16 question open Record q16 about module 5\nc16 claim unassessed Record c16 about module 4\nq15 question open Record q15 about module 2\nc15 claim unassessed Record c15 about module 1\nd14 decision adopted Record d14 about module 0\nq14 question open Record q14 about module 6\nc14 claim unassessed Record c14 about module 5\nd13 decision adopted Record d13 about module 4\nc13 claim unassessed Record c13 about module 2\nd12 decision adopted Record d12 about module 1\nq12 question open Record q12 about module 0\nc12 claim unassessed Record c12 about module 6\nc2 claim unassessed Record c2 about module 4\nd11 decision adopted Record d11 about module 5\nq11 question open Record q11 about module 4\nd10 decision adopted Record d10 about module 2\nq10 question open Record q10 about module 1\nc10 claim unassessed Record c10 about module 0\nd9 decision adopted Record d9 about module 6\nq9 question open Record q9 about module 5\nc9 claim unassessed Record c9 about module 4\nd3 decision adopted Record d3 about module 2\nq8 question open Record q8 about module 2\nc8 claim unassessed Record c8 about module 1\nd7 decision adopted Record d7 about module 0\nd2 decision adopted Record d2 about module 6\nq7 question open Record q7 about module 6\nc7 claim unassessed Record c7 about module 5\n# and 10 more; docket list\n\n# full text: 10; index: 40; retired: 0.\n# Not listed: 10; reach them with docket list.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n400_qnone_fno_b900": "# docket: repo | revision: 4cc469337b96 | latest: c134@4cc469337b96\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n# index: d49, c134, d133, c67, q133, c133, d132, q132, c132, d131, q131, c131, d130, q130, c130, d129, q129, c129, d128, q128, c128, d127, q127, c127, d126, q126, c126, d125, q125, c125, d124, q124, c124, d123, q123, c123, d122, q122, c122, d121\n# and 360 more; docket list\n\n# full text: 0; index: 40; retired: 0.\n# Not listed: 360; reach them with docket list.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n400_qnone_fno_b8000": "# docket: repo | revision: 4cc469337b96 | latest: c134@4cc469337b96\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n### d49 | decision | adopted [selected]\ntext: Record d49 about module 0\nchoice: Choice 147\napplicable: false\nblocked_by: [\"c13\"]\nblocked: c13 unassessed\nscope: [\"lib/mod0/**\"]\ndepends_on: [\"c13\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c134 | claim | unassessed [selected]\ntext: Record c134 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d133 | decision | adopted [selected]\ntext: Record d133 about module 0\nchoice: Choice 399\nscope: [\"lib/mod0/**\"]\n\n### c67 | claim | unassessed [selected]\ntext: Record c67 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q133 | question | open [selected]\ntext: Record q133 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c133 | claim | unassessed [selected]\ntext: Record c133 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d132 | decision | adopted [selected]\ntext: Record d132 about module 4\nchoice: Choice 396\nscope: [\"lib/mod4/**\"]\n\n### q132 | question | open [selected]\ntext: Record q132 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c132 | claim | unassessed [selected]\ntext: Record c132 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d131 | decision | adopted [selected]\ntext: Record d131 about module 1\nchoice: Choice 393\nscope: [\"lib/mod1/**\"]\n\n### q131 | question | open [selected]\ntext: Record q131 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c131 | claim | unassessed [selected]\ntext: Record c131 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d130 | decision | adopted [selected]\ntext: Record d130 about module 5\nchoice: Choice 390\nscope: [\"lib/mod5/**\"]\n\n### q130 | question | open [selected]\ntext: Record q130 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c130 | claim | unassessed [selected]\ntext: Record c130 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d129 | decision | adopted [selected]\ntext: Record d129 about module 2\nchoice: Choice 387\nscope: [\"lib/mod2/**\"]\n\n### q129 | question | open [selected]\ntext: Record q129 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c129 | claim | unassessed [selected]\ntext: Record c129 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d128 | decision | adopted [selected]\ntext: Record d128 about module 6\nchoice: Choice 384\nscope: [\"lib/mod6/**\"]\n\n### q128 | question | open [selected]\ntext: Record q128 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c128 | claim | unassessed [selected]\ntext: Record c128 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d127 | decision | adopted [selected]\ntext: Record d127 about module 3\nchoice: Choice 381\nscope: [\"lib/mod3/**\"]\n\n### q127 | question | open [selected]\ntext: Record q127 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c127 | claim | unassessed [selected]\ntext: Record c127 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d126 | decision | adopted [selected]\ntext: Record d126 about module 0\nchoice: Choice 378\nscope: [\"lib/mod0/**\"]\n\n### q126 | question | open [selected]\ntext: Record q126 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c126 | claim | unassessed [selected]\ntext: Record c126 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d125 | decision | adopted [selected]\ntext: Record d125 about module 4\nchoice: Choice 375\nscope: [\"lib/mod4/**\"]\n\n### q125 | question | open [selected]\ntext: Record q125 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c125 | claim | unassessed [selected]\ntext: Record c125 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d124 | decision | adopted [selected]\ntext: Record d124 about module 1\nchoice: Choice 372\nscope: [\"lib/mod1/**\"]\n\n### q124 | question | open [selected]\ntext: Record q124 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c124 | claim | unassessed [selected]\ntext: Record c124 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d123 | decision | adopted [selected]\ntext: Record d123 about module 5\nchoice: Choice 369\napplicable: false\nblocked_by: [\"c37\"]\nblocked: c37 unassessed\nscope: [\"lib/mod5/**\"]\ndepends_on: [\"c37\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q123 | question | open [selected]\ntext: Record q123 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c123 | claim | unassessed [selected]\ntext: Record c123 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d122 | decision | adopted [selected]\ntext: Record d122 about module 2\nchoice: Choice 366\nscope: [\"lib/mod2/**\"]\n\n### q109 | question | open [selected]\ntext: Record q109 about module 4\nscope: [\"lib/mod4/**\"]\n\n# index: 40 more current records\nq122 question open Record q122 about module 1\nc122 claim unassessed Record c122 about module 0\nd121 decision adopted Record d121 about module 6\nq121 question open Record q121 about module 5\nc121 claim unassessed Record c121 about module 4\nd120 decision adopted Record d120 about module 3\nq120 question open Record q120 about module 2\nc120 claim unassessed Record c120 about module 1\nd119 decision adopted Record d119 about module 0\nq119 question open Record q119 about module 6\nc119 claim unassessed Record c119 about module 5\nd85 decision adopted Record d85 about module 3\nd118 decision adopted Record d118 about module 4\nq118 question open Record q118 about module 3\nc118 claim unassessed Record c118 about module 2\nd117 decision adopted Record d117 about module 1\nq117 question open Record q117 about module 0\nc117 claim unassessed Record c117 about module 6\nd116 decision adopted Record d116 about module 5\nq116 question open Record q116 about module 4\nc116 claim unassessed Record c116 about module 3\nd115 decision adopted Record d115 about module 2\nq115 question open Record q115 about module 1\nc115 claim unassessed Record c115 about module 0\nd114 decision adopted Record d114 about module 6\nq114 question open Record q114 about module 5\nc114 claim unassessed Record c114 about module 4\nd113 decision adopted Record d113 about module 3\nd80 decision adopted Record d80 about module 2\nq113 question open Record q113 about module 2\nc113 claim unassessed Record c113 about module 1\nd112 decision adopted Record d112 about module 0\nq112 question open Record q112 about module 6\nc112 claim unassessed Record c112 about module 5\nd111 decision adopted Record d111 about module 4\nq111 question open Record q111 about module 3\nc111 claim unassessed Record c111 about module 2\nd110 decision adopted Record d110 about module 1\nq110 question open Record q110 about module 0\nc110 claim unassessed Record c110 about module 6\n# and 322 more; docket list\n\n# full text: 38; index: 40; retired: 0.\n# Not listed: 322; reach them with docket list.\n# Related records in index only: 2; formulas remain complete.\n# Coverage: partial, 2 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n400_qnone_fno_bdefault": "# docket: repo | revision: 4cc469337b96 | latest: c134@4cc469337b96\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n### d49 | decision | adopted [selected]\ntext: Record d49 about module 0\nchoice: Choice 147\napplicable: false\nblocked_by: [\"c13\"]\nblocked: c13 unassessed\nscope: [\"lib/mod0/**\"]\ndepends_on: [\"c13\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c134 | claim | unassessed [selected]\ntext: Record c134 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d133 | decision | adopted [selected]\ntext: Record d133 about module 0\nchoice: Choice 399\nscope: [\"lib/mod0/**\"]\n\n### c67 | claim | unassessed [selected]\ntext: Record c67 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q133 | question | open [selected]\ntext: Record q133 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c133 | claim | unassessed [selected]\ntext: Record c133 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d132 | decision | adopted [selected]\ntext: Record d132 about module 4\nchoice: Choice 396\nscope: [\"lib/mod4/**\"]\n\n### q132 | question | open [selected]\ntext: Record q132 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c132 | claim | unassessed [selected]\ntext: Record c132 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d131 | decision | adopted [selected]\ntext: Record d131 about module 1\nchoice: Choice 393\nscope: [\"lib/mod1/**\"]\n\n### q131 | question | open [selected]\ntext: Record q131 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c131 | claim | unassessed [selected]\ntext: Record c131 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d130 | decision | adopted [selected]\ntext: Record d130 about module 5\nchoice: Choice 390\nscope: [\"lib/mod5/**\"]\n\n### q130 | question | open [selected]\ntext: Record q130 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c130 | claim | unassessed [selected]\ntext: Record c130 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d129 | decision | adopted [selected]\ntext: Record d129 about module 2\nchoice: Choice 387\nscope: [\"lib/mod2/**\"]\n\n### q129 | question | open [selected]\ntext: Record q129 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c129 | claim | unassessed [selected]\ntext: Record c129 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d128 | decision | adopted [selected]\ntext: Record d128 about module 6\nchoice: Choice 384\nscope: [\"lib/mod6/**\"]\n\n### q128 | question | open [selected]\ntext: Record q128 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c128 | claim | unassessed [selected]\ntext: Record c128 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d127 | decision | adopted [selected]\ntext: Record d127 about module 3\nchoice: Choice 381\nscope: [\"lib/mod3/**\"]\n\n### q127 | question | open [selected]\ntext: Record q127 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c127 | claim | unassessed [selected]\ntext: Record c127 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d126 | decision | adopted [selected]\ntext: Record d126 about module 0\nchoice: Choice 378\nscope: [\"lib/mod0/**\"]\n\n### q126 | question | open [selected]\ntext: Record q126 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c126 | claim | unassessed [selected]\ntext: Record c126 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d125 | decision | adopted [selected]\ntext: Record d125 about module 4\nchoice: Choice 375\nscope: [\"lib/mod4/**\"]\n\n### q125 | question | open [selected]\ntext: Record q125 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c125 | claim | unassessed [selected]\ntext: Record c125 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d124 | decision | adopted [selected]\ntext: Record d124 about module 1\nchoice: Choice 372\nscope: [\"lib/mod1/**\"]\n\n### q124 | question | open [selected]\ntext: Record q124 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c124 | claim | unassessed [selected]\ntext: Record c124 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d123 | decision | adopted [selected]\ntext: Record d123 about module 5\nchoice: Choice 369\napplicable: false\nblocked_by: [\"c37\"]\nblocked: c37 unassessed\nscope: [\"lib/mod5/**\"]\ndepends_on: [\"c37\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q123 | question | open [selected]\ntext: Record q123 about module 4\nscope: [\"lib/mod4/**\"]\n\n### c123 | claim | unassessed [selected]\ntext: Record c123 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d122 | decision | adopted [selected]\ntext: Record d122 about module 2\nchoice: Choice 366\nscope: [\"lib/mod2/**\"]\n\n### q109 | question | open [selected]\ntext: Record q109 about module 4\nscope: [\"lib/mod4/**\"]\n\n# index: 40 more current records\nq122 question open Record q122 about module 1\nc122 claim unassessed Record c122 about module 0\nd121 decision adopted Record d121 about module 6\nq121 question open Record q121 about module 5\nc121 claim unassessed Record c121 about module 4\nd120 decision adopted Record d120 about module 3\nq120 question open Record q120 about module 2\nc120 claim unassessed Record c120 about module 1\nd119 decision adopted Record d119 about module 0\nq119 question open Record q119 about module 6\nc119 claim unassessed Record c119 about module 5\nd85 decision adopted Record d85 about module 3\nd118 decision adopted Record d118 about module 4\nq118 question open Record q118 about module 3\nc118 claim unassessed Record c118 about module 2\nd117 decision adopted Record d117 about module 1\nq117 question open Record q117 about module 0\nc117 claim unassessed Record c117 about module 6\nd116 decision adopted Record d116 about module 5\nq116 question open Record q116 about module 4\nc116 claim unassessed Record c116 about module 3\nd115 decision adopted Record d115 about module 2\nq115 question open Record q115 about module 1\nc115 claim unassessed Record c115 about module 0\nd114 decision adopted Record d114 about module 6\nq114 question open Record q114 about module 5\nc114 claim unassessed Record c114 about module 4\nd113 decision adopted Record d113 about module 3\nd80 decision adopted Record d80 about module 2\nq113 question open Record q113 about module 2\nc113 claim unassessed Record c113 about module 1\nd112 decision adopted Record d112 about module 0\nq112 question open Record q112 about module 6\nc112 claim unassessed Record c112 about module 5\nd111 decision adopted Record d111 about module 4\nq111 question open Record q111 about module 3\nc111 claim unassessed Record c111 about module 2\nd110 decision adopted Record d110 about module 1\nq110 question open Record q110 about module 0\nc110 claim unassessed Record c110 about module 6\n# and 322 more; docket list\n\n# full text: 38; index: 40; retired: 0.\n# Not listed: 322; reach them with docket list.\n# Related records in index only: 2; formulas remain complete.\n# Coverage: partial, 2 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n400_qmodule 3_fno_b900": "# docket: repo | revision: 4cc469337b96 | latest: c134@4cc469337b96\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n# index: c67, q132, c130, d127, q125, c123, d120, d85, q118, c116, d113, q111, c109, d106, q104, c102, d99, q97, c95, d92, d57, q90, c88, d50, q83, c81, d78, q76, c74, d71, q69, c32, d64, q62, c60, q55, c53, c18, q48, c46\n# and 360 more; docket list\n\n# full text: 0; index: 40; retired: 0.\n# Not listed: 360; reach them with docket list.\n# Coverage: partial, 400 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n400_qmodule 3_fno_b8000": "# docket: repo | revision: 4cc469337b96 | latest: c134@4cc469337b96\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n### c67 | claim | unassessed [selected]\ntext: Record c67 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q132 | question | open [selected]\ntext: Record q132 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c130 | claim | unassessed [selected]\ntext: Record c130 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d127 | decision | adopted [selected]\ntext: Record d127 about module 3\nchoice: Choice 381\nscope: [\"lib/mod3/**\"]\n\n### q125 | question | open [selected]\ntext: Record q125 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c123 | claim | unassessed [selected]\ntext: Record c123 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d120 | decision | adopted [selected]\ntext: Record d120 about module 3\nchoice: Choice 360\napplicable: false\nblocked_by: [\"d57\", \"c43\"]\nblocked: d57 -> c43 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d57\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### d85 | decision | adopted [selected]\ntext: Record d85 about module 3\nchoice: Choice 255\napplicable: false\nblocked_by: [\"c67\"]\nblocked: c67 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c67\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q118 | question | open [selected]\ntext: Record q118 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c116 | claim | unassessed [selected]\ntext: Record c116 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d113 | decision | adopted [selected]\ntext: Record d113 about module 3\nchoice: Choice 339\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d26\"]\n\n### q111 | question | open [selected]\ntext: Record q111 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c109 | claim | unassessed [selected]\ntext: Record c109 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d106 | decision | adopted [selected]\ntext: Record d106 about module 3\nchoice: Choice 318\napplicable: false\nblocked_by: [\"d85\", \"c67\"]\nblocked: d85 -> c67 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d85\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q104 | question | open [selected]\ntext: Record q104 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c102 | claim | unassessed [selected]\ntext: Record c102 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d99 | decision | adopted [selected]\ntext: Record d99 about module 3\nchoice: Choice 297\nscope: [\"lib/mod3/**\"]\n\n### q97 | question | open [selected]\ntext: Record q97 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c95 | claim | unassessed [selected]\ntext: Record c95 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d92 | decision | adopted [selected]\ntext: Record d92 about module 3\nchoice: Choice 276\nscope: [\"lib/mod3/**\"]\n\n### d57 | decision | adopted [selected]\ntext: Record d57 about module 3\nchoice: Choice 171\napplicable: false\nblocked_by: [\"c43\"]\nblocked: c43 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c43\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q90 | question | open [selected]\ntext: Record q90 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c88 | claim | unassessed [selected]\ntext: Record c88 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d50 | decision | adopted [selected]\ntext: Record d50 about module 3\nchoice: Choice 150\napplicable: false\nblocked_by: [\"d49\", \"c13\"]\nblocked: d49 -> c13 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d49\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q83 | question | open [selected]\ntext: Record q83 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c81 | claim | unassessed [selected]\ntext: Record c81 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d78 | decision | adopted [selected]\ntext: Record d78 about module 3\nchoice: Choice 234\napplicable: false\nblocked_by: [\"d49\", \"c13\"]\nblocked: d49 -> c13 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d49\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q76 | question | open [selected]\ntext: Record q76 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c74 | claim | unassessed [selected]\ntext: Record c74 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d71 | decision | adopted [selected]\ntext: Record d71 about module 3\nchoice: Choice 213\napplicable: false\nblocked_by: [\"c17\"]\nblocked: c17 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c17\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q69 | question | open [selected]\ntext: Record q69 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d64 | decision | adopted [selected]\ntext: Record d64 about module 3\nchoice: Choice 192\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d3\"]\n\n# index: 40 more current records\nc32 claim unassessed Record c32 about module 3\nq62 question open Record q62 about module 3\nc60 claim unassessed Record c60 about module 3\nq55 question open Record q55 about module 3\nc53 claim unassessed Record c53 about module 3\nc18 claim unassessed Record c18 about module 3\nq48 question open Record q48 about module 3\nc46 claim unassessed Record c46 about module 3\nd43 decision adopted Record d43 about module 3\nd8 decision adopted Record d8 about module 3\nq41 question open Record q41 about module 3\nc39 claim unassessed Record c39 about module 3\nd36 decision adopted Record d36 about module 3\nd1 decision adopted Record d1 about module 3\nq34 question open Record q34 about module 3\nd29 decision adopted Record d29 about module 3\nq27 question open Record q27 about module 3\nc25 claim unassessed Record c25 about module 3\nd22 decision adopted Record d22 about module 3\nq20 question open Record q20 about module 3\nd15 decision adopted Record d15 about module 3\nq13 question open Record q13 about module 3\nc11 claim unassessed Record c11 about module 3\nq6 question open Record q6 about module 3\nc4 claim unassessed Record c4 about module 3\nc134 claim unassessed Record c134 about module 1\nd133 decision adopted Record d133 about module 0\nq133 question open Record q133 about module 6\nc133 claim unassessed Record c133 about module 5\nd132 decision adopted Record d132 about module 4\nc132 claim unassessed Record c132 about module 2\nd131 decision adopted Record d131 about module 1\nq131 question open Record q131 about module 0\nc131 claim unassessed Record c131 about module 6\nd130 decision adopted Record d130 about module 5\nq130 question open Record q130 about module 4\nd129 decision adopted Record d129 about module 2\nd128 decision adopted Record d128 about module 6\nd126 decision adopted Record d126 about module 0\nd125 decision adopted Record d125 about module 4\n# and 328 more; docket list\n\n# full text: 32; index: 40; retired: 0.\n# Not listed: 328; reach them with docket list.\n# Related records in index only: 5; formulas remain complete.\n# Coverage: partial, 368 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n400_qmodule 3_fno_bdefault": "# docket: repo | revision: 4cc469337b96 | latest: c134@4cc469337b96\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n### c67 | claim | unassessed [selected]\ntext: Record c67 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q132 | question | open [selected]\ntext: Record q132 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c130 | claim | unassessed [selected]\ntext: Record c130 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d127 | decision | adopted [selected]\ntext: Record d127 about module 3\nchoice: Choice 381\nscope: [\"lib/mod3/**\"]\n\n### q125 | question | open [selected]\ntext: Record q125 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c123 | claim | unassessed [selected]\ntext: Record c123 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d120 | decision | adopted [selected]\ntext: Record d120 about module 3\nchoice: Choice 360\napplicable: false\nblocked_by: [\"d57\", \"c43\"]\nblocked: d57 -> c43 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d57\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### d85 | decision | adopted [selected]\ntext: Record d85 about module 3\nchoice: Choice 255\napplicable: false\nblocked_by: [\"c67\"]\nblocked: c67 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c67\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q118 | question | open [selected]\ntext: Record q118 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c116 | claim | unassessed [selected]\ntext: Record c116 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d113 | decision | adopted [selected]\ntext: Record d113 about module 3\nchoice: Choice 339\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d26\"]\n\n### q111 | question | open [selected]\ntext: Record q111 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c109 | claim | unassessed [selected]\ntext: Record c109 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d106 | decision | adopted [selected]\ntext: Record d106 about module 3\nchoice: Choice 318\napplicable: false\nblocked_by: [\"d85\", \"c67\"]\nblocked: d85 -> c67 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d85\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q104 | question | open [selected]\ntext: Record q104 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c102 | claim | unassessed [selected]\ntext: Record c102 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d99 | decision | adopted [selected]\ntext: Record d99 about module 3\nchoice: Choice 297\nscope: [\"lib/mod3/**\"]\n\n### q97 | question | open [selected]\ntext: Record q97 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c95 | claim | unassessed [selected]\ntext: Record c95 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d92 | decision | adopted [selected]\ntext: Record d92 about module 3\nchoice: Choice 276\nscope: [\"lib/mod3/**\"]\n\n### d57 | decision | adopted [selected]\ntext: Record d57 about module 3\nchoice: Choice 171\napplicable: false\nblocked_by: [\"c43\"]\nblocked: c43 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c43\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q90 | question | open [selected]\ntext: Record q90 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c88 | claim | unassessed [selected]\ntext: Record c88 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d50 | decision | adopted [selected]\ntext: Record d50 about module 3\nchoice: Choice 150\napplicable: false\nblocked_by: [\"d49\", \"c13\"]\nblocked: d49 -> c13 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d49\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q83 | question | open [selected]\ntext: Record q83 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c81 | claim | unassessed [selected]\ntext: Record c81 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d78 | decision | adopted [selected]\ntext: Record d78 about module 3\nchoice: Choice 234\napplicable: false\nblocked_by: [\"d49\", \"c13\"]\nblocked: d49 -> c13 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d49\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q76 | question | open [selected]\ntext: Record q76 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c74 | claim | unassessed [selected]\ntext: Record c74 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d71 | decision | adopted [selected]\ntext: Record d71 about module 3\nchoice: Choice 213\napplicable: false\nblocked_by: [\"c17\"]\nblocked: c17 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c17\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q69 | question | open [selected]\ntext: Record q69 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c32 | claim | unassessed [selected]\ntext: Record c32 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d64 | decision | adopted [selected]\ntext: Record d64 about module 3\nchoice: Choice 192\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d3\"]\n\n### q62 | question | open [selected]\ntext: Record q62 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c60 | claim | unassessed [selected]\ntext: Record c60 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q55 | question | open [selected]\ntext: Record q55 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c53 | claim | unassessed [selected]\ntext: Record c53 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c18 | claim | unassessed [selected]\ntext: Record c18 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q48 | question | open [selected]\ntext: Record q48 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c46 | claim | unassessed [selected]\ntext: Record c46 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d43 | decision | adopted [selected]\ntext: Record d43 about module 3\nchoice: Choice 129\nscope: [\"lib/mod3/**\"]\n\n### d8 | decision | adopted [selected]\ntext: Record d8 about module 3\nchoice: Choice 24\nscope: [\"lib/mod3/**\"]\n\n### q41 | question | open [selected]\ntext: Record q41 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c39 | claim | unassessed [selected]\ntext: Record c39 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d36 | decision | adopted [selected]\ntext: Record d36 about module 3\nchoice: Choice 108\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d10\"]\n\n### d1 | decision | adopted [selected]\ntext: Record d1 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### q34 | question | open [selected]\ntext: Record q34 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d29 | decision | adopted [selected]\ntext: Record d29 about module 3\nchoice: Choice 87\nscope: [\"lib/mod3/**\"]\n\n### q27 | question | open [selected]\ntext: Record q27 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c25 | claim | unassessed [selected]\ntext: Record c25 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d22 | decision | adopted [selected]\ntext: Record d22 about module 3\nchoice: Choice 66\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d3\"]\n\n### q20 | question | open [selected]\ntext: Record q20 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d15 | decision | adopted [selected]\ntext: Record d15 about module 3\nchoice: Choice 45\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d8\"]\n\n### q13 | question | open [selected]\ntext: Record q13 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c11 | claim | unassessed [selected]\ntext: Record c11 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q6 | question | open [selected]\ntext: Record q6 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c4 | claim | unassessed [selected]\ntext: Record c4 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c134 | claim | unassessed [selected]\ntext: Record c134 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d133 | decision | adopted [selected]\ntext: Record d133 about module 0\nchoice: Choice 399\nscope: [\"lib/mod0/**\"]\n\n### q133 | question | open [selected]\ntext: Record q133 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c133 | claim | unassessed [selected]\ntext: Record c133 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d132 | decision | adopted [selected]\ntext: Record d132 about module 4\nchoice: Choice 396\nscope: [\"lib/mod4/**\"]\n\n### c132 | claim | unassessed [selected]\ntext: Record c132 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d131 | decision | adopted [selected]\ntext: Record d131 about module 1\nchoice: Choice 393\nscope: [\"lib/mod1/**\"]\n\n### q131 | question | open [selected]\ntext: Record q131 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c131 | claim | unassessed [selected]\ntext: Record c131 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d130 | decision | adopted [selected]\ntext: Record d130 about module 5\nchoice: Choice 390\nscope: [\"lib/mod5/**\"]\n\n### q130 | question | open [selected]\ntext: Record q130 about module 4\nscope: [\"lib/mod4/**\"]\n\n### d129 | decision | adopted [selected]\ntext: Record d129 about module 2\nchoice: Choice 387\nscope: [\"lib/mod2/**\"]\n\n### d128 | decision | adopted [selected]\ntext: Record d128 about module 6\nchoice: Choice 384\nscope: [\"lib/mod6/**\"]\n\n### d126 | decision | adopted [selected]\ntext: Record d126 about module 0\nchoice: Choice 378\nscope: [\"lib/mod0/**\"]\n\n### d125 | decision | adopted [selected]\ntext: Record d125 about module 4\nchoice: Choice 375\nscope: [\"lib/mod4/**\"]\n\n### d124 | decision | adopted [selected]\ntext: Record d124 about module 1\nchoice: Choice 372\nscope: [\"lib/mod1/**\"]\n\n### d123 | decision | adopted [selected]\ntext: Record d123 about module 5\nchoice: Choice 369\napplicable: false\nblocked_by: [\"c37\"]\nblocked: c37 unassessed\nscope: [\"lib/mod5/**\"]\ndepends_on: [\"c37\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q123 | question | open [selected]\ntext: Record q123 about module 4\nscope: [\"lib/mod4/**\"]\n\n### d122 | decision | adopted [selected]\ntext: Record d122 about module 2\nchoice: Choice 366\nscope: [\"lib/mod2/**\"]\n\n### d121 | decision | adopted [selected]\ntext: Record d121 about module 6\nchoice: Choice 363\nscope: [\"lib/mod6/**\"]\n\n### d119 | decision | adopted [selected]\ntext: Record d119 about module 0\nchoice: Choice 357\nscope: [\"lib/mod0/**\"]\n\n### d118 | decision | adopted [selected]\ntext: Record d118 about module 4\nchoice: Choice 354\nscope: [\"lib/mod4/**\"]\n\n### d117 | decision | adopted [selected]\ntext: Record d117 about module 1\nchoice: Choice 351\napplicable: false\nblocked_by: [\"c67\"]\nblocked: c67 unassessed\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"c67\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### d116 | decision | adopted [selected]\ntext: Record d116 about module 5\nchoice: Choice 348\nscope: [\"lib/mod5/**\"]\n\n### d115 | decision | adopted [selected]\ntext: Record d115 about module 2\nchoice: Choice 345\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"d11\"]\n\n### d114 | decision | adopted [selected]\ntext: Record d114 about module 6\nchoice: Choice 342\napplicable: false\nblocked_by: [\"c38\"]\nblocked: c38 unassessed\nscope: [\"lib/mod6/**\"]\ndepends_on: [\"c38\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q113 | question | open [selected]\ntext: Record q113 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c113 | claim | unassessed [selected]\ntext: Record c113 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d112 | decision | adopted [selected]\ntext: Record d112 about module 0\nchoice: Choice 336\nscope: [\"lib/mod0/**\"]\n\n### d111 | decision | adopted [selected]\ntext: Record d111 about module 4\nchoice: Choice 333\nscope: [\"lib/mod4/**\"]\n\n### d110 | decision | adopted [selected]\ntext: Record d110 about module 1\nchoice: Choice 330\napplicable: false\nblocked_by: [\"c48\"]\nblocked: c48 unassessed\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"c48\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### d109 | decision | adopted [selected]\ntext: Record d109 about module 5\nchoice: Choice 327\nscope: [\"lib/mod5/**\"]\n\n### d108 | decision | adopted [selected]\ntext: Record d108 about module 2\nchoice: Choice 324\nscope: [\"lib/mod2/**\"]\n\n### d107 | decision | adopted [selected]\ntext: Record d107 about module 6\nchoice: Choice 321\nscope: [\"lib/mod6/**\"]\n\n### d105 | decision | adopted [selected]\ntext: Record d105 about module 0\nchoice: Choice 315\nscope: [\"lib/mod0/**\"]\n\n### d104 | decision | adopted [selected]\ntext: Record d104 about module 4\nchoice: Choice 312\nscope: [\"lib/mod4/**\"]\n\n### d103 | decision | adopted [selected]\ntext: Record d103 about module 1\nchoice: Choice 309\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"d10\"]\n\n### q103 | question | open [selected]\ntext: Record q103 about module 0\nscope: [\"lib/mod0/**\"]\n\n### c103 | claim | unassessed [selected]\ntext: Record c103 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d102 | decision | adopted [selected]\ntext: Record d102 about module 5\nchoice: Choice 306\nscope: [\"lib/mod5/**\"]\n\n### d101 | decision | adopted [selected]\ntext: Record d101 about module 2\nchoice: Choice 303\napplicable: false\nblocked_by: [\"d50\", \"d49\", \"c13\"]\nblocked: d50 -> d49 -> c13 unassessed\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"d50\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### d100 | decision | adopted [selected]\ntext: Record d100 about module 6\nchoice: Choice 300\nscope: [\"lib/mod6/**\"]\n\n### d93 | decision | adopted [selected]\ntext: Record d93 about module 6\nchoice: Choice 279\nscope: [\"lib/mod6/**\"]\n\n### q93 | question | open [selected]\ntext: Record q93 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c93 | claim | unassessed [selected]\ntext: Record c93 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d91 | decision | adopted [selected]\ntext: Record d91 about module 0\nchoice: Choice 273\nscope: [\"lib/mod0/**\"]\n\n### d83 | decision | adopted [selected]\ntext: Record d83 about module 4\nchoice: Choice 249\nscope: [\"lib/mod4/**\"]\n\n### c83 | claim | unassessed [selected]\ntext: Record c83 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d81 | decision | adopted [selected]\ntext: Record d81 about module 5\nchoice: Choice 243\nscope: [\"lib/mod5/**\"]\n\n### d79 | decision | adopted [selected]\ntext: Record d79 about module 6\nchoice: Choice 237\napplicable: false\nblocked_by: [\"c59\"]\nblocked: c59 unassessed\nscope: [\"lib/mod6/**\"]\ndepends_on: [\"c59\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c13 | claim | unassessed [selected]\ntext: Record c13 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d11 | decision | adopted [selected]\ntext: Record d11 about module 5\nchoice: Choice 33\nscope: [\"lib/mod5/**\"]\n\n### d77 | decision | adopted [selected]\ntext: Record d77 about module 0\nchoice: Choice 231\nscope: [\"lib/mod0/**\"]\n\n### d10 | decision | adopted [selected]\ntext: Record d10 about module 2\nchoice: Choice 30\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"d5\"]\n\n### c43 | claim | unassessed [selected]\ntext: Record c43 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d73 | decision | adopted [selected]\ntext: Record d73 about module 2\nchoice: Choice 219\nscope: [\"lib/mod2/**\"]\n\n### q73 | question | open [selected]\ntext: Record q73 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c73 | claim | unassessed [selected]\ntext: Record c73 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d39 | decision | adopted [selected]\ntext: Record d39 about module 5\nchoice: Choice 117\nscope: [\"lib/mod5/**\"]\n\n### c38 | claim | unassessed [selected]\ntext: Record c38 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c37 | claim | unassessed [selected]\ntext: Record c37 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 2\nchoice: Choice 9\nscope: [\"lib/mod2/**\"]\n\n### c36 | claim | unassessed [selected]\ntext: Record c36 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d34 | decision | adopted [selected]\ntext: Record d34 about module 4\nchoice: Choice 102\nscope: [\"lib/mod4/**\"]\n\n### d32 | decision | adopted [selected]\ntext: Record d32 about module 5\nchoice: Choice 96\nscope: [\"lib/mod5/**\"]\n\n### d63 | decision | adopted [selected]\ntext: Record d63 about module 0\nchoice: Choice 189\nscope: [\"lib/mod0/**\"]\ndepends_on: [\"d32\"]\n\n### q63 | question | open [selected]\ntext: Record q63 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c63 | claim | unassessed [selected]\ntext: Record c63 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d61 | decision | adopted [selected]\ntext: Record d61 about module 1\nchoice: Choice 183\nscope: [\"lib/mod1/**\"]\n\n### d53 | decision | adopted [selected]\ntext: Record d53 about module 5\nchoice: Choice 159\nscope: [\"lib/mod5/**\"]\n\n### q53 | question | open [selected]\ntext: Record q53 about module 4\nscope: [\"lib/mod4/**\"]\n\n### d51 | decision | adopted [selected]\ntext: Record d51 about module 6\nchoice: Choice 153\nscope: [\"lib/mod6/**\"]\n\n### d46 | decision | adopted [selected]\ntext: Record d46 about module 5\nchoice: Choice 138\nscope: [\"lib/mod5/**\"]\n\n### d45 | decision | adopted [selected]\ntext: Record d45 about module 2\nchoice: Choice 135\napplicable: false\nblocked_by: [\"c29\"]\nblocked: c29 unassessed\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"c29\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### d44 | decision | adopted [selected]\ntext: Record d44 about module 6\nchoice: Choice 132\napplicable: false\nblocked_by: [\"c18\"]\nblocked: c18 unassessed\nscope: [\"lib/mod6/**\"]\ndepends_on: [\"c18\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q43 | question | open [selected]\ntext: Record q43 about module 2\nscope: [\"lib/mod2/**\"]\n\n### d41 | decision | adopted [selected]\ntext: Record d41 about module 4\nchoice: Choice 123\napplicable: false\nblocked_by: [\"c13\"]\nblocked: c13 unassessed\nscope: [\"lib/mod4/**\"]\ndepends_on: [\"c13\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q39 | question | open [selected]\ntext: Record q39 about module 4\nscope: [\"lib/mod4/**\"]\n\n### d38 | decision | adopted [selected]\ntext: Record d38 about module 2\nchoice: Choice 114\napplicable: false\nblocked_by: [\"c3\"]\nblocked: c3 unassessed\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"c3\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q38 | question | open [selected]\ntext: Record q38 about module 1\nscope: [\"lib/mod1/**\"]\n\n### d37 | decision | adopted [selected]\ntext: Record d37 about module 6\nchoice: Choice 111\nscope: [\"lib/mod6/**\"]\n\n### q37 | question | open [selected]\ntext: Record q37 about module 5\nscope: [\"lib/mod5/**\"]\n\n### q36 | question | open [selected]\ntext: Record q36 about module 2\nscope: [\"lib/mod2/**\"]\n\n### c3 | claim | unassessed [selected]\ntext: Record c3 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d35 | decision | adopted [selected]\ntext: Record d35 about module 0\nchoice: Choice 105\napplicable: false\nblocked_by: [\"c6\"]\nblocked: c6 unassessed\nscope: [\"lib/mod0/**\"]\ndepends_on: [\"c6\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q35 | question | open [selected]\ntext: Record q35 about module 6\nscope: [\"lib/mod6/**\"]\n\n# index: 40 more current records\nc35 claim unassessed Record c35 about module 5\nc34 claim unassessed Record c34 about module 2\nd33 decision adopted Record d33 about module 1\nq33 question open Record q33 about module 0\nc33 claim unassessed Record c33 about module 6\nq32 question open Record q32 about module 4\nd31 decision adopted Record d31 about module 2\nq31 question open Record q31 about module 1\nc31 claim unassessed Record c31 about module 0\nd30 decision adopted Record d30 about module 6\nq30 question open Record q30 about module 5\nc30 claim unassessed Record c30 about module 4\nd23 decision adopted Record d23 about module 6\nq23 question open Record q23 about module 5\nc23 claim unassessed Record c23 about module 4\nd21 decision adopted Record d21 about module 0\nd13 decision adopted Record d13 about module 4\nd12 decision adopted Record d12 about module 1\nq3 question open Record q3 about module 1\nd49 decision adopted Record d49 about module 0\nq129 question open Record q129 about module 1\nc129 claim unassessed Record c129 about module 0\nq128 question open Record q128 about module 5\nc128 claim unassessed Record c128 about module 4\nq127 question open Record q127 about module 2\nc127 claim unassessed Record c127 about module 1\nq126 question open Record q126 about module 6\nc126 claim unassessed Record c126 about module 5\nc125 claim unassessed Record c125 about module 2\nq124 question open Record q124 about module 0\nc124 claim unassessed Record c124 about module 6\nq122 question open Record q122 about module 1\nc122 claim unassessed Record c122 about module 0\nq121 question open Record q121 about module 5\nc121 claim unassessed Record c121 about module 4\nq120 question open Record q120 about module 2\nc120 claim unassessed Record c120 about module 1\nq119 question open Record q119 about module 6\nc119 claim unassessed Record c119 about module 5\nc118 claim unassessed Record c118 about module 2\n# and 217 more; docket list\n\n# full text: 143; index: 40; retired: 0.\n# Not listed: 217; reach them with docket list.\n# Related records in index only: 8; formulas remain complete.\n# Coverage: partial, 257 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n400_qnone_fyes_b900": "# docket: repo | revision: 4cc469337b96 | latest: c134@4cc469337b96\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n# index: c67, q132, c130, d127, q125, c123, d120, d85, q118, c116, d113, q111, c109, d106, q104, c102, d99, q97, c95, d92, d57, q90, c88, d50, q83, c81, d78, q76, c74, d71, q69, c32, d64, q62, c60, q55, c53, c18, q48, c46\n# and 360 more; docket list\n\n# full text: 0; index: 40; retired: 0.\n# Not listed: 360; reach them with docket list.\n# Coverage: partial, 57 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n400_qnone_fyes_b8000": "# docket: repo | revision: 4cc469337b96 | latest: c134@4cc469337b96\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n### c67 | claim | unassessed [selected]\ntext: Record c67 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q132 | question | open [selected]\ntext: Record q132 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c130 | claim | unassessed [selected]\ntext: Record c130 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d127 | decision | adopted [selected]\ntext: Record d127 about module 3\nchoice: Choice 381\nscope: [\"lib/mod3/**\"]\n\n### q125 | question | open [selected]\ntext: Record q125 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c123 | claim | unassessed [selected]\ntext: Record c123 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d120 | decision | adopted [selected]\ntext: Record d120 about module 3\nchoice: Choice 360\napplicable: false\nblocked_by: [\"d57\", \"c43\"]\nblocked: d57 -> c43 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d57\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### d85 | decision | adopted [selected]\ntext: Record d85 about module 3\nchoice: Choice 255\napplicable: false\nblocked_by: [\"c67\"]\nblocked: c67 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c67\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q118 | question | open [selected]\ntext: Record q118 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c116 | claim | unassessed [selected]\ntext: Record c116 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d113 | decision | adopted [selected]\ntext: Record d113 about module 3\nchoice: Choice 339\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d26\"]\n\n### q111 | question | open [selected]\ntext: Record q111 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c109 | claim | unassessed [selected]\ntext: Record c109 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d106 | decision | adopted [selected]\ntext: Record d106 about module 3\nchoice: Choice 318\napplicable: false\nblocked_by: [\"d85\", \"c67\"]\nblocked: d85 -> c67 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d85\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q104 | question | open [selected]\ntext: Record q104 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c102 | claim | unassessed [selected]\ntext: Record c102 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d99 | decision | adopted [selected]\ntext: Record d99 about module 3\nchoice: Choice 297\nscope: [\"lib/mod3/**\"]\n\n### q97 | question | open [selected]\ntext: Record q97 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c95 | claim | unassessed [selected]\ntext: Record c95 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d92 | decision | adopted [selected]\ntext: Record d92 about module 3\nchoice: Choice 276\nscope: [\"lib/mod3/**\"]\n\n### d57 | decision | adopted [selected]\ntext: Record d57 about module 3\nchoice: Choice 171\napplicable: false\nblocked_by: [\"c43\"]\nblocked: c43 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c43\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q90 | question | open [selected]\ntext: Record q90 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c88 | claim | unassessed [selected]\ntext: Record c88 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d50 | decision | adopted [selected]\ntext: Record d50 about module 3\nchoice: Choice 150\napplicable: false\nblocked_by: [\"d49\", \"c13\"]\nblocked: d49 -> c13 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d49\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q83 | question | open [selected]\ntext: Record q83 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c81 | claim | unassessed [selected]\ntext: Record c81 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d78 | decision | adopted [selected]\ntext: Record d78 about module 3\nchoice: Choice 234\napplicable: false\nblocked_by: [\"d49\", \"c13\"]\nblocked: d49 -> c13 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d49\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q76 | question | open [selected]\ntext: Record q76 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c74 | claim | unassessed [selected]\ntext: Record c74 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d71 | decision | adopted [selected]\ntext: Record d71 about module 3\nchoice: Choice 213\napplicable: false\nblocked_by: [\"c17\"]\nblocked: c17 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c17\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q69 | question | open [selected]\ntext: Record q69 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d64 | decision | adopted [selected]\ntext: Record d64 about module 3\nchoice: Choice 192\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d3\"]\n\n# index: 40 more current records\nc32 claim unassessed Record c32 about module 3\nq62 question open Record q62 about module 3\nc60 claim unassessed Record c60 about module 3\nq55 question open Record q55 about module 3\nc53 claim unassessed Record c53 about module 3\nc18 claim unassessed Record c18 about module 3\nq48 question open Record q48 about module 3\nc46 claim unassessed Record c46 about module 3\nd43 decision adopted Record d43 about module 3\nd8 decision adopted Record d8 about module 3\nq41 question open Record q41 about module 3\nc39 claim unassessed Record c39 about module 3\nd36 decision adopted Record d36 about module 3\nd1 decision adopted Record d1 about module 3\nq34 question open Record q34 about module 3\nd29 decision adopted Record d29 about module 3\nq27 question open Record q27 about module 3\nc25 claim unassessed Record c25 about module 3\nd22 decision adopted Record d22 about module 3\nq20 question open Record q20 about module 3\nd15 decision adopted Record d15 about module 3\nq13 question open Record q13 about module 3\nc11 claim unassessed Record c11 about module 3\nq6 question open Record q6 about module 3\nc4 claim unassessed Record c4 about module 3\nd49 decision adopted Record d49 about module 0\nc134 claim unassessed Record c134 about module 1\nd133 decision adopted Record d133 about module 0\nq133 question open Record q133 about module 6\nc133 claim unassessed Record c133 about module 5\nd132 decision adopted Record d132 about module 4\nc132 claim unassessed Record c132 about module 2\nd131 decision adopted Record d131 about module 1\nq131 question open Record q131 about module 0\nc131 claim unassessed Record c131 about module 6\nd130 decision adopted Record d130 about module 5\nq130 question open Record q130 about module 4\nd129 decision adopted Record d129 about module 2\nq129 question open Record q129 about module 1\nc129 claim unassessed Record c129 about module 0\n# and 328 more; docket list\n\n# full text: 32; index: 40; retired: 0.\n# Not listed: 328; reach them with docket list.\n# Related records in index only: 5; formulas remain complete.\n# Coverage: partial, 29 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n400_qnone_fyes_bdefault": "# docket: repo | revision: 4cc469337b96 | latest: c134@4cc469337b96\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n### c67 | claim | unassessed [selected]\ntext: Record c67 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q132 | question | open [selected]\ntext: Record q132 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c130 | claim | unassessed [selected]\ntext: Record c130 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d127 | decision | adopted [selected]\ntext: Record d127 about module 3\nchoice: Choice 381\nscope: [\"lib/mod3/**\"]\n\n### q125 | question | open [selected]\ntext: Record q125 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c123 | claim | unassessed [selected]\ntext: Record c123 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d120 | decision | adopted [selected]\ntext: Record d120 about module 3\nchoice: Choice 360\napplicable: false\nblocked_by: [\"d57\", \"c43\"]\nblocked: d57 -> c43 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d57\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### d85 | decision | adopted [selected]\ntext: Record d85 about module 3\nchoice: Choice 255\napplicable: false\nblocked_by: [\"c67\"]\nblocked: c67 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c67\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q118 | question | open [selected]\ntext: Record q118 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c116 | claim | unassessed [selected]\ntext: Record c116 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d113 | decision | adopted [selected]\ntext: Record d113 about module 3\nchoice: Choice 339\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d26\"]\n\n### q111 | question | open [selected]\ntext: Record q111 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c109 | claim | unassessed [selected]\ntext: Record c109 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d106 | decision | adopted [selected]\ntext: Record d106 about module 3\nchoice: Choice 318\napplicable: false\nblocked_by: [\"d85\", \"c67\"]\nblocked: d85 -> c67 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d85\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q104 | question | open [selected]\ntext: Record q104 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c102 | claim | unassessed [selected]\ntext: Record c102 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d99 | decision | adopted [selected]\ntext: Record d99 about module 3\nchoice: Choice 297\nscope: [\"lib/mod3/**\"]\n\n### q97 | question | open [selected]\ntext: Record q97 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c95 | claim | unassessed [selected]\ntext: Record c95 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d92 | decision | adopted [selected]\ntext: Record d92 about module 3\nchoice: Choice 276\nscope: [\"lib/mod3/**\"]\n\n### d57 | decision | adopted [selected]\ntext: Record d57 about module 3\nchoice: Choice 171\napplicable: false\nblocked_by: [\"c43\"]\nblocked: c43 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c43\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q90 | question | open [selected]\ntext: Record q90 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c88 | claim | unassessed [selected]\ntext: Record c88 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d50 | decision | adopted [selected]\ntext: Record d50 about module 3\nchoice: Choice 150\napplicable: false\nblocked_by: [\"d49\", \"c13\"]\nblocked: d49 -> c13 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d49\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q83 | question | open [selected]\ntext: Record q83 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c81 | claim | unassessed [selected]\ntext: Record c81 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d78 | decision | adopted [selected]\ntext: Record d78 about module 3\nchoice: Choice 234\napplicable: false\nblocked_by: [\"d49\", \"c13\"]\nblocked: d49 -> c13 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d49\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q76 | question | open [selected]\ntext: Record q76 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c74 | claim | unassessed [selected]\ntext: Record c74 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d71 | decision | adopted [selected]\ntext: Record d71 about module 3\nchoice: Choice 213\napplicable: false\nblocked_by: [\"c17\"]\nblocked: c17 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c17\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q69 | question | open [selected]\ntext: Record q69 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d64 | decision | adopted [selected]\ntext: Record d64 about module 3\nchoice: Choice 192\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d3\"]\n\n# index: 40 more current records\nc32 claim unassessed Record c32 about module 3\nq62 question open Record q62 about module 3\nc60 claim unassessed Record c60 about module 3\nq55 question open Record q55 about module 3\nc53 claim unassessed Record c53 about module 3\nc18 claim unassessed Record c18 about module 3\nq48 question open Record q48 about module 3\nc46 claim unassessed Record c46 about module 3\nd43 decision adopted Record d43 about module 3\nd8 decision adopted Record d8 about module 3\nq41 question open Record q41 about module 3\nc39 claim unassessed Record c39 about module 3\nd36 decision adopted Record d36 about module 3\nd1 decision adopted Record d1 about module 3\nq34 question open Record q34 about module 3\nd29 decision adopted Record d29 about module 3\nq27 question open Record q27 about module 3\nc25 claim unassessed Record c25 about module 3\nd22 decision adopted Record d22 about module 3\nq20 question open Record q20 about module 3\nd15 decision adopted Record d15 about module 3\nq13 question open Record q13 about module 3\nc11 claim unassessed Record c11 about module 3\nq6 question open Record q6 about module 3\nc4 claim unassessed Record c4 about module 3\nd49 decision adopted Record d49 about module 0\nc134 claim unassessed Record c134 about module 1\nd133 decision adopted Record d133 about module 0\nq133 question open Record q133 about module 6\nc133 claim unassessed Record c133 about module 5\nd132 decision adopted Record d132 about module 4\nc132 claim unassessed Record c132 about module 2\nd131 decision adopted Record d131 about module 1\nq131 question open Record q131 about module 0\nc131 claim unassessed Record c131 about module 6\nd130 decision adopted Record d130 about module 5\nq130 question open Record q130 about module 4\nd129 decision adopted Record d129 about module 2\nq129 question open Record q129 about module 1\nc129 claim unassessed Record c129 about module 0\n# and 328 more; docket list\n\n# full text: 32; index: 40; retired: 0.\n# Not listed: 328; reach them with docket list.\n# Related records in index only: 5; formulas remain complete.\n# Coverage: partial, 29 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n1500_qnone_fno_b900": "# docket: repo | revision: 782c58a0a496 | latest: d500@782c58a0a496\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n# index: c434, c479, c226, c467, c336, d445, c422, c396, c273, c266, d390, c386, d6, d3, d500, q500, c500, d499, q499, c499, d498, q498, d374, c250, c498, d497, q497, c497, d496, q496, c496, d495, q495, c495, d494, q494, c494, d493, q493, c120\n# and 1460 more; docket list\n\n# full text: 0; index: 40; retired: 0.\n# Not listed: 1460; reach them with docket list.\n# Coverage: task matches and their prerequisites covered. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n1500_qnone_fno_b8000": "# docket: repo | revision: 782c58a0a496 | latest: d500@782c58a0a496\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n### c434 | claim | unassessed [selected]\ntext: Record c434 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c479 | claim | unassessed [selected]\ntext: Record c479 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c226 | claim | unassessed [selected]\ntext: Record c226 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c467 | claim | unassessed [selected]\ntext: Record c467 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c336 | claim | unassessed [selected]\ntext: Record c336 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d445 | decision | adopted [selected]\ntext: Record d445 about module 5\nchoice: Choice 1335\nscope: [\"lib/mod5/**\"]\ndepends_on: [\"d140\"]\n\n### c422 | claim | unassessed [selected]\ntext: Record c422 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c396 | claim | unassessed [selected]\ntext: Record c396 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c273 | claim | unassessed [selected]\ntext: Record c273 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c266 | claim | unassessed [selected]\ntext: Record c266 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d390 | decision | adopted [selected]\ntext: Record d390 about module 1\nchoice: Choice 1170\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"d78\"]\n\n### c386 | claim | unassessed [selected]\ntext: Record c386 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d6 | decision | adopted [selected]\ntext: Record d6 about module 4\nchoice: Choice 18\nscope: [\"lib/mod4/**\"]\ndepends_on: [\"d3\"]\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 2\nchoice: Choice 9\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"d1\"]\n\n### d500 | decision | adopted [selected]\ntext: Record d500 about module 2\nchoice: Choice 1500\nscope: [\"lib/mod2/**\"]\n\n### q500 | question | open [selected]\ntext: Record q500 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c500 | claim | unassessed [selected]\ntext: Record c500 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d499 | decision | adopted [selected]\ntext: Record d499 about module 6\nchoice: Choice 1497\napplicable: false\nblocked_by: [\"c10\"]\nblocked: c10 unassessed\nscope: [\"lib/mod6/**\"]\ndepends_on: [\"c10\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q499 | question | open [selected]\ntext: Record q499 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c499 | claim | unassessed [selected]\ntext: Record c499 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d498 | decision | adopted [selected]\ntext: Record d498 about module 3\nchoice: Choice 1494\nscope: [\"lib/mod3/**\"]\n\n### q498 | question | open [selected]\ntext: Record q498 about module 2\nscope: [\"lib/mod2/**\"]\n\n### d374 | decision | adopted [selected]\ntext: Record d374 about module 2\nchoice: Choice 1122\napplicable: false\nblocked_by: [\"c299\"]\nblocked: c299 unassessed\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"c299\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c250 | claim | unassessed [selected]\ntext: Record c250 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c498 | claim | unassessed [selected]\ntext: Record c498 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d497 | decision | adopted [selected]\ntext: Record d497 about module 0\nchoice: Choice 1491\nscope: [\"lib/mod0/**\"]\n\n### q497 | question | open [selected]\ntext: Record q497 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c497 | claim | unassessed [selected]\ntext: Record c497 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d496 | decision | adopted [selected]\ntext: Record d496 about module 4\nchoice: Choice 1488\nscope: [\"lib/mod4/**\"]\n\n### q496 | question | open [selected]\ntext: Record q496 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c496 | claim | unassessed [selected]\ntext: Record c496 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d495 | decision | adopted [selected]\ntext: Record d495 about module 1\nchoice: Choice 1485\napplicable: false\nblocked_by: [\"c479\"]\nblocked: c479 unassessed\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"c479\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n# index: 40 more current records\nq495 question open Record q495 about module 0\nc495 claim unassessed Record c495 about module 6\nd494 decision adopted Record d494 about module 5\nq494 question open Record q494 about module 4\nc494 claim unassessed Record c494 about module 3\nd493 decision adopted Record d493 about module 2\nq493 question open Record q493 about module 1\nc120 claim unassessed Record c120 about module 1\nc493 claim unassessed Record c493 about module 0\nd492 decision adopted Record d492 about module 6\nq492 question open Record q492 about module 5\nc492 claim unassessed Record c492 about module 4\nd491 decision adopted Record d491 about module 3\nq491 question open Record q491 about module 2\nc491 claim unassessed Record c491 about module 1\nd490 decision adopted Record d490 about module 0\nq490 question open Record q490 about module 6\nc490 claim unassessed Record c490 about module 5\nd489 decision adopted Record d489 about module 4\nq489 question open Record q489 about module 3\nc489 claim unassessed Record c489 about module 2\nd488 decision adopted Record d488 about module 1\nq488 question open Record q488 about module 0\nc488 claim unassessed Record c488 about module 6\nd487 decision adopted Record d487 about module 5\nq487 question open Record q487 about module 4\nc487 claim unassessed Record c487 about module 3\nd486 decision adopted Record d486 about module 2\nq486 question open Record q486 about module 1\nc486 claim unassessed Record c486 about module 0\nd485 decision adopted Record d485 about module 6\nq485 question open Record q485 about module 5\nc485 claim unassessed Record c485 about module 4\nd484 decision adopted Record d484 about module 3\nq484 question open Record q484 about module 2\nc484 claim unassessed Record c484 about module 1\nd483 decision adopted Record d483 about module 0\nq483 question open Record q483 about module 6\nd235 decision adopted Record d235 about module 5\nc483 claim unassessed Record c483 about module 5\n# and 1428 more; docket list\n\n# full text: 32; index: 40; retired: 0.\n# Not listed: 1428; reach them with docket list.\n# Related records in index only: 5; formulas remain complete.\n# Coverage: partial, 2 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n1500_qnone_fno_bdefault": "# docket: repo | revision: 782c58a0a496 | latest: d500@782c58a0a496\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n\n### c434 | claim | unassessed [selected]\ntext: Record c434 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c479 | claim | unassessed [selected]\ntext: Record c479 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c226 | claim | unassessed [selected]\ntext: Record c226 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c467 | claim | unassessed [selected]\ntext: Record c467 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c336 | claim | unassessed [selected]\ntext: Record c336 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d445 | decision | adopted [selected]\ntext: Record d445 about module 5\nchoice: Choice 1335\nscope: [\"lib/mod5/**\"]\ndepends_on: [\"d140\"]\n\n### c422 | claim | unassessed [selected]\ntext: Record c422 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c396 | claim | unassessed [selected]\ntext: Record c396 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c273 | claim | unassessed [selected]\ntext: Record c273 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c266 | claim | unassessed [selected]\ntext: Record c266 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d390 | decision | adopted [selected]\ntext: Record d390 about module 1\nchoice: Choice 1170\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"d78\"]\n\n### c386 | claim | unassessed [selected]\ntext: Record c386 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d6 | decision | adopted [selected]\ntext: Record d6 about module 4\nchoice: Choice 18\nscope: [\"lib/mod4/**\"]\ndepends_on: [\"d3\"]\n\n### d3 | decision | adopted [selected]\ntext: Record d3 about module 2\nchoice: Choice 9\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"d1\"]\n\n### d500 | decision | adopted [selected]\ntext: Record d500 about module 2\nchoice: Choice 1500\nscope: [\"lib/mod2/**\"]\n\n### q500 | question | open [selected]\ntext: Record q500 about module 1\nscope: [\"lib/mod1/**\"]\n\n### c500 | claim | unassessed [selected]\ntext: Record c500 about module 0\nscope: [\"lib/mod0/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d499 | decision | adopted [selected]\ntext: Record d499 about module 6\nchoice: Choice 1497\napplicable: false\nblocked_by: [\"c10\"]\nblocked: c10 unassessed\nscope: [\"lib/mod6/**\"]\ndepends_on: [\"c10\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q499 | question | open [selected]\ntext: Record q499 about module 5\nscope: [\"lib/mod5/**\"]\n\n### c499 | claim | unassessed [selected]\ntext: Record c499 about module 4\nscope: [\"lib/mod4/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d498 | decision | adopted [selected]\ntext: Record d498 about module 3\nchoice: Choice 1494\nscope: [\"lib/mod3/**\"]\n\n### q498 | question | open [selected]\ntext: Record q498 about module 2\nscope: [\"lib/mod2/**\"]\n\n### d374 | decision | adopted [selected]\ntext: Record d374 about module 2\nchoice: Choice 1122\napplicable: false\nblocked_by: [\"c299\"]\nblocked: c299 unassessed\nscope: [\"lib/mod2/**\"]\ndepends_on: [\"c299\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c250 | claim | unassessed [selected]\ntext: Record c250 about module 6\nscope: [\"lib/mod6/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c498 | claim | unassessed [selected]\ntext: Record c498 about module 1\nscope: [\"lib/mod1/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d497 | decision | adopted [selected]\ntext: Record d497 about module 0\nchoice: Choice 1491\nscope: [\"lib/mod0/**\"]\n\n### q497 | question | open [selected]\ntext: Record q497 about module 6\nscope: [\"lib/mod6/**\"]\n\n### c497 | claim | unassessed [selected]\ntext: Record c497 about module 5\nscope: [\"lib/mod5/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d496 | decision | adopted [selected]\ntext: Record d496 about module 4\nchoice: Choice 1488\nscope: [\"lib/mod4/**\"]\n\n### q496 | question | open [selected]\ntext: Record q496 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c496 | claim | unassessed [selected]\ntext: Record c496 about module 2\nscope: [\"lib/mod2/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d495 | decision | adopted [selected]\ntext: Record d495 about module 1\nchoice: Choice 1485\napplicable: false\nblocked_by: [\"c479\"]\nblocked: c479 unassessed\nscope: [\"lib/mod1/**\"]\ndepends_on: [\"c479\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n# index: 40 more current records\nq495 question open Record q495 about module 0\nc495 claim unassessed Record c495 about module 6\nd494 decision adopted Record d494 about module 5\nq494 question open Record q494 about module 4\nc494 claim unassessed Record c494 about module 3\nd493 decision adopted Record d493 about module 2\nq493 question open Record q493 about module 1\nc120 claim unassessed Record c120 about module 1\nc493 claim unassessed Record c493 about module 0\nd492 decision adopted Record d492 about module 6\nq492 question open Record q492 about module 5\nc492 claim unassessed Record c492 about module 4\nd491 decision adopted Record d491 about module 3\nq491 question open Record q491 about module 2\nc491 claim unassessed Record c491 about module 1\nd490 decision adopted Record d490 about module 0\nq490 question open Record q490 about module 6\nc490 claim unassessed Record c490 about module 5\nd489 decision adopted Record d489 about module 4\nq489 question open Record q489 about module 3\nc489 claim unassessed Record c489 about module 2\nd488 decision adopted Record d488 about module 1\nq488 question open Record q488 about module 0\nc488 claim unassessed Record c488 about module 6\nd487 decision adopted Record d487 about module 5\nq487 question open Record q487 about module 4\nc487 claim unassessed Record c487 about module 3\nd486 decision adopted Record d486 about module 2\nq486 question open Record q486 about module 1\nc486 claim unassessed Record c486 about module 0\nd485 decision adopted Record d485 about module 6\nq485 question open Record q485 about module 5\nc485 claim unassessed Record c485 about module 4\nd484 decision adopted Record d484 about module 3\nq484 question open Record q484 about module 2\nc484 claim unassessed Record c484 about module 1\nd483 decision adopted Record d483 about module 0\nq483 question open Record q483 about module 6\nd235 decision adopted Record d235 about module 5\nc483 claim unassessed Record c483 about module 5\n# and 1428 more; docket list\n\n# full text: 32; index: 40; retired: 0.\n# Not listed: 1428; reach them with docket list.\n# Related records in index only: 5; formulas remain complete.\n# Coverage: partial, 2 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n1500_qmodule 3_fno_b900": "# docket: repo | revision: 782c58a0a496 | latest: d500@782c58a0a496\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n# index: c396, d498, q496, c494, d491, q489, c487, d484, q482, c480, d477, q475, c473, c347, d470, q468, c466, d463, q461, c459, d456, c207, q454, c452, d449, q447, c445, d442, q440, c438, d435, q433, c431, d428, q426, c424, d421, q419, c417, d414\n# and 1460 more; docket list\n\n# full text: 0; index: 40; retired: 0.\n# Not listed: 1460; reach them with docket list.\n# Coverage: partial, 757 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n1500_qmodule 3_fno_b8000": "# docket: repo | revision: 782c58a0a496 | latest: d500@782c58a0a496\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n### c396 | claim | unassessed [selected]\ntext: Record c396 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d498 | decision | adopted [selected]\ntext: Record d498 about module 3\nchoice: Choice 1494\nscope: [\"lib/mod3/**\"]\n\n### q496 | question | open [selected]\ntext: Record q496 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c494 | claim | unassessed [selected]\ntext: Record c494 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d491 | decision | adopted [selected]\ntext: Record d491 about module 3\nchoice: Choice 1473\nscope: [\"lib/mod3/**\"]\n\n### q489 | question | open [selected]\ntext: Record q489 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c487 | claim | unassessed [selected]\ntext: Record c487 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d484 | decision | adopted [selected]\ntext: Record d484 about module 3\nchoice: Choice 1452\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d390\"]\n\n### q482 | question | open [selected]\ntext: Record q482 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c480 | claim | unassessed [selected]\ntext: Record c480 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d477 | decision | adopted [selected]\ntext: Record d477 about module 3\nchoice: Choice 1431\nscope: [\"lib/mod3/**\"]\n\n### q475 | question | open [selected]\ntext: Record q475 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c473 | claim | unassessed [selected]\ntext: Record c473 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c347 | claim | unassessed [selected]\ntext: Record c347 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d470 | decision | adopted [selected]\ntext: Record d470 about module 3\nchoice: Choice 1410\nscope: [\"lib/mod3/**\"]\n\n### q468 | question | open [selected]\ntext: Record q468 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c466 | claim | unassessed [selected]\ntext: Record c466 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d463 | decision | adopted [selected]\ntext: Record d463 about module 3\nchoice: Choice 1389\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d151\"]\n\n### q461 | question | open [selected]\ntext: Record q461 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c459 | claim | unassessed [selected]\ntext: Record c459 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d456 | decision | adopted [selected]\ntext: Record d456 about module 3\nchoice: Choice 1368\napplicable: false\nblocked_by: [\"d374\", \"c299\"]\nblocked: d374 -> c299 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d374\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c207 | claim | unassessed [selected]\ntext: Record c207 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q454 | question | open [selected]\ntext: Record q454 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c452 | claim | unassessed [selected]\ntext: Record c452 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d449 | decision | adopted [selected]\ntext: Record d449 about module 3\nchoice: Choice 1347\nscope: [\"lib/mod3/**\"]\n\n### q447 | question | open [selected]\ntext: Record q447 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c445 | claim | unassessed [selected]\ntext: Record c445 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d442 | decision | adopted [selected]\ntext: Record d442 about module 3\nchoice: Choice 1326\napplicable: false\nblocked_by: [\"c148\"]\nblocked: c148 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c148\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q440 | question | open [selected]\ntext: Record q440 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c438 | claim | unassessed [selected]\ntext: Record c438 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d435 | decision | adopted [selected]\ntext: Record d435 about module 3\nchoice: Choice 1305\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d274\"]\n\n### q433 | question | open [selected]\ntext: Record q433 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c431 | claim | unassessed [selected]\ntext: Record c431 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d428 | decision | adopted [selected]\ntext: Record d428 about module 3\nchoice: Choice 1284\nscope: [\"lib/mod3/**\"]\n\n### q426 | question | open [selected]\ntext: Record q426 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c424 | claim | unassessed [selected]\ntext: Record c424 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# index: 40 more current records\nd421 decision adopted Record d421 about module 3\nq419 question open Record q419 about module 3\nc417 claim unassessed Record c417 about module 3\nd414 decision adopted Record d414 about module 3\nq412 question open Record q412 about module 3\nc410 claim unassessed Record c410 about module 3\nd407 decision adopted Record d407 about module 3\nq405 question open Record q405 about module 3\nc403 claim unassessed Record c403 about module 3\nd400 decision adopted Record d400 about module 3\nq398 question open Record q398 about module 3\nd274 decision adopted Record d274 about module 3\nd393 decision adopted Record d393 about module 3\nq391 question open Record q391 about module 3\nc389 claim unassessed Record c389 about module 3\nd386 decision adopted Record d386 about module 3\nq384 question open Record q384 about module 3\nc382 claim unassessed Record c382 about module 3\nd379 decision adopted Record d379 about module 3\nq377 question open Record q377 about module 3\nd1 decision adopted Record d1 about module 3\nc375 claim unassessed Record c375 about module 3\nd372 decision adopted Record d372 about module 3\nq370 question open Record q370 about module 3\nc368 claim unassessed Record c368 about module 3\nc242 claim unassessed Record c242 about module 3\nd365 decision adopted Record d365 about module 3\nq363 question open Record q363 about module 3\nd239 decision adopted Record d239 about module 3\nc361 claim unassessed Record c361 about module 3\nd358 decision adopted Record d358 about module 3\nq356 question open Record q356 about module 3\nd232 decision adopted Record d232 about module 3\nc354 claim unassessed Record c354 about module 3\nd351 decision adopted Record d351 about module 3\nq349 question open Record q349 about module 3\nd344 decision adopted Record d344 about module 3\nq342 question open Record q342 about module 3\nc340 claim unassessed Record c340 about module 3\nd337 decision adopted Record d337 about module 3\n# and 1424 more; docket list\n\n# full text: 36; index: 40; retired: 0.\n# Not listed: 1424; reach them with docket list.\n# Related records in index only: 5; formulas remain complete.\n# Coverage: partial, 723 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n1500_qmodule 3_fno_bdefault": "# docket: repo | revision: 782c58a0a496 | latest: d500@782c58a0a496\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# query: module 3\n\n### c396 | claim | unassessed [selected]\ntext: Record c396 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d498 | decision | adopted [selected]\ntext: Record d498 about module 3\nchoice: Choice 1494\nscope: [\"lib/mod3/**\"]\n\n### q496 | question | open [selected]\ntext: Record q496 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c494 | claim | unassessed [selected]\ntext: Record c494 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d491 | decision | adopted [selected]\ntext: Record d491 about module 3\nchoice: Choice 1473\nscope: [\"lib/mod3/**\"]\n\n### q489 | question | open [selected]\ntext: Record q489 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c487 | claim | unassessed [selected]\ntext: Record c487 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d484 | decision | adopted [selected]\ntext: Record d484 about module 3\nchoice: Choice 1452\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d390\"]\n\n### q482 | question | open [selected]\ntext: Record q482 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c480 | claim | unassessed [selected]\ntext: Record c480 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d477 | decision | adopted [selected]\ntext: Record d477 about module 3\nchoice: Choice 1431\nscope: [\"lib/mod3/**\"]\n\n### q475 | question | open [selected]\ntext: Record q475 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c473 | claim | unassessed [selected]\ntext: Record c473 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c347 | claim | unassessed [selected]\ntext: Record c347 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d470 | decision | adopted [selected]\ntext: Record d470 about module 3\nchoice: Choice 1410\nscope: [\"lib/mod3/**\"]\n\n### q468 | question | open [selected]\ntext: Record q468 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c466 | claim | unassessed [selected]\ntext: Record c466 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d463 | decision | adopted [selected]\ntext: Record d463 about module 3\nchoice: Choice 1389\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d151\"]\n\n### q461 | question | open [selected]\ntext: Record q461 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c459 | claim | unassessed [selected]\ntext: Record c459 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d456 | decision | adopted [selected]\ntext: Record d456 about module 3\nchoice: Choice 1368\napplicable: false\nblocked_by: [\"d374\", \"c299\"]\nblocked: d374 -> c299 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d374\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c207 | claim | unassessed [selected]\ntext: Record c207 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q454 | question | open [selected]\ntext: Record q454 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c452 | claim | unassessed [selected]\ntext: Record c452 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d449 | decision | adopted [selected]\ntext: Record d449 about module 3\nchoice: Choice 1347\nscope: [\"lib/mod3/**\"]\n\n### q447 | question | open [selected]\ntext: Record q447 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c445 | claim | unassessed [selected]\ntext: Record c445 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d442 | decision | adopted [selected]\ntext: Record d442 about module 3\nchoice: Choice 1326\napplicable: false\nblocked_by: [\"c148\"]\nblocked: c148 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c148\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q440 | question | open [selected]\ntext: Record q440 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c438 | claim | unassessed [selected]\ntext: Record c438 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d435 | decision | adopted [selected]\ntext: Record d435 about module 3\nchoice: Choice 1305\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d274\"]\n\n### q433 | question | open [selected]\ntext: Record q433 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c431 | claim | unassessed [selected]\ntext: Record c431 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d428 | decision | adopted [selected]\ntext: Record d428 about module 3\nchoice: Choice 1284\nscope: [\"lib/mod3/**\"]\n\n### q426 | question | open [selected]\ntext: Record q426 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c424 | claim | unassessed [selected]\ntext: Record c424 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d421 | decision | adopted [selected]\ntext: Record d421 about module 3\nchoice: Choice 1263\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d62\"]\n\n### q419 | question | open [selected]\ntext: Record q419 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c417 | claim | unassessed [selected]\ntext: Record c417 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d414 | decision | adopted [selected]\ntext: Record d414 about module 3\nchoice: Choice 1242\nscope: [\"lib/mod3/**\"]\n\n### q412 | question | open [selected]\ntext: Record q412 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c410 | claim | unassessed [selected]\ntext: Record c410 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d407 | decision | adopted [selected]\ntext: Record d407 about module 3\nchoice: Choice 1221\nscope: [\"lib/mod3/**\"]\n\n### q405 | question | open [selected]\ntext: Record q405 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c403 | claim | unassessed [selected]\ntext: Record c403 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d400 | decision | adopted [selected]\ntext: Record d400 about module 3\nchoice: Choice 1200\nscope: [\"lib/mod3/**\"]\n\n### q398 | question | open [selected]\ntext: Record q398 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d274 | decision | adopted [selected]\ntext: Record d274 about module 3\nchoice: Choice 822\nscope: [\"lib/mod3/**\"]\n\n### d393 | decision | adopted [selected]\ntext: Record d393 about module 3\nchoice: Choice 1179\napplicable: false\nblocked_by: [\"c338\"]\nblocked: c338 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c338\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q391 | question | open [selected]\ntext: Record q391 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c389 | claim | unassessed [selected]\ntext: Record c389 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d386 | decision | adopted [selected]\ntext: Record d386 about module 3\nchoice: Choice 1158\napplicable: false\nblocked_by: [\"c88\"]\nblocked: c88 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c88\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q384 | question | open [selected]\ntext: Record q384 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c382 | claim | unassessed [selected]\ntext: Record c382 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d379 | decision | adopted [selected]\ntext: Record d379 about module 3\nchoice: Choice 1137\napplicable: false\nblocked_by: [\"c191\"]\nblocked: c191 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c191\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q377 | question | open [selected]\ntext: Record q377 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d1 | decision | adopted [selected]\ntext: Record d1 about module 3\nchoice: Choice 3\nscope: [\"lib/mod3/**\"]\n\n### c375 | claim | unassessed [selected]\ntext: Record c375 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d372 | decision | adopted [selected]\ntext: Record d372 about module 3\nchoice: Choice 1116\nscope: [\"lib/mod3/**\"]\n\n### q370 | question | open [selected]\ntext: Record q370 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c368 | claim | unassessed [selected]\ntext: Record c368 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c242 | claim | unassessed [selected]\ntext: Record c242 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d365 | decision | adopted [selected]\ntext: Record d365 about module 3\nchoice: Choice 1095\nscope: [\"lib/mod3/**\"]\n\n### q363 | question | open [selected]\ntext: Record q363 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d239 | decision | adopted [selected]\ntext: Record d239 about module 3\nchoice: Choice 717\napplicable: false\nblocked_by: [\"d235\", \"c93\"]\nblocked: d235 -> c93 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d235\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c361 | claim | unassessed [selected]\ntext: Record c361 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d358 | decision | adopted [selected]\ntext: Record d358 about module 3\nchoice: Choice 1074\napplicable: false\nblocked_by: [\"c31\"]\nblocked: c31 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c31\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q356 | question | open [selected]\ntext: Record q356 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d232 | decision | adopted [selected]\ntext: Record d232 about module 3\nchoice: Choice 696\napplicable: false\nblocked_by: [\"c195\"]\nblocked: c195 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c195\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c354 | claim | unassessed [selected]\ntext: Record c354 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d351 | decision | adopted [selected]\ntext: Record d351 about module 3\nchoice: Choice 1053\napplicable: false\nblocked_by: [\"d232\", \"c195\"]\nblocked: d232 -> c195 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d232\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q349 | question | open [selected]\ntext: Record q349 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d344 | decision | adopted [selected]\ntext: Record d344 about module 3\nchoice: Choice 1032\napplicable: false\nblocked_by: [\"c140\"]\nblocked: c140 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c140\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q342 | question | open [selected]\ntext: Record q342 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c340 | claim | unassessed [selected]\ntext: Record c340 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d337 | decision | adopted [selected]\ntext: Record d337 about module 3\nchoice: Choice 1011\nscope: [\"lib/mod3/**\"]\n\n### q335 | question | open [selected]\ntext: Record q335 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c333 | claim | unassessed [selected]\ntext: Record c333 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d330 | decision | adopted [selected]\ntext: Record d330 about module 3\nchoice: Choice 990\nscope: [\"lib/mod3/**\"]\n\n### q328 | question | open [selected]\ntext: Record q328 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d78 | decision | adopted [selected]\ntext: Record d78 about module 3\nchoice: Choice 234\nscope: [\"lib/mod3/**\"]\n\n### c326 | claim | unassessed [selected]\ntext: Record c326 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d323 | decision | adopted [selected]\ntext: Record d323 about module 3\nchoice: Choice 969\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d51\"]\n\n### q321 | question | open [selected]\ntext: Record q321 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c319 | claim | unassessed [selected]\ntext: Record c319 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d316 | decision | adopted [selected]\ntext: Record d316 about module 3\nchoice: Choice 948\napplicable: false\nblocked_by: [\"c282\"]\nblocked: c282 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c282\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q314 | question | open [selected]\ntext: Record q314 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c312 | claim | unassessed [selected]\ntext: Record c312 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d309 | decision | adopted [selected]\ntext: Record d309 about module 3\nchoice: Choice 927\nscope: [\"lib/mod3/**\"]\n\n### q307 | question | open [selected]\ntext: Record q307 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c305 | claim | unassessed [selected]\ntext: Record c305 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d302 | decision | adopted [selected]\ntext: Record d302 about module 3\nchoice: Choice 906\napplicable: false\nblocked_by: [\"c33\"]\nblocked: c33 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c33\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q300 | question | open [selected]\ntext: Record q300 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c298 | claim | unassessed [selected]\ntext: Record c298 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d295 | decision | adopted [selected]\ntext: Record d295 about module 3\nchoice: Choice 885\nscope: [\"lib/mod3/**\"]\n\n### q293 | question | open [selected]\ntext: Record q293 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c291 | claim | unassessed [selected]\ntext: Record c291 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d288 | decision | adopted [selected]\ntext: Record d288 about module 3\nchoice: Choice 864\nscope: [\"lib/mod3/**\"]\n\n### q286 | question | open [selected]\ntext: Record q286 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d162 | decision | adopted [selected]\ntext: Record d162 about module 3\nchoice: Choice 486\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d132\"]\n\n### c284 | claim | unassessed [selected]\ntext: Record c284 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d281 | decision | adopted [selected]\ntext: Record d281 about module 3\nchoice: Choice 843\nscope: [\"lib/mod3/**\"]\n\n### q279 | question | open [selected]\ntext: Record q279 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d155 | decision | adopted [selected]\ntext: Record d155 about module 3\nchoice: Choice 465\nscope: [\"lib/mod3/**\"]\n\n### c277 | claim | unassessed [selected]\ntext: Record c277 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q272 | question | open [selected]\ntext: Record q272 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c270 | claim | unassessed [selected]\ntext: Record c270 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d267 | decision | adopted [selected]\ntext: Record d267 about module 3\nchoice: Choice 801\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d6\"]\n\n### q265 | question | open [selected]\ntext: Record q265 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c263 | claim | unassessed [selected]\ntext: Record c263 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c11 | claim | unassessed [selected]\ntext: Record c11 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d260 | decision | adopted [selected]\ntext: Record d260 about module 3\nchoice: Choice 780\nscope: [\"lib/mod3/**\"]\n\n### q258 | question | open [selected]\ntext: Record q258 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c256 | claim | unassessed [selected]\ntext: Record c256 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d253 | decision | adopted [selected]\ntext: Record d253 about module 3\nchoice: Choice 759\nscope: [\"lib/mod3/**\"]\n\n### q251 | question | open [selected]\ntext: Record q251 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c249 | claim | unassessed [selected]\ntext: Record c249 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d246 | decision | adopted [selected]\ntext: Record d246 about module 3\nchoice: Choice 738\nscope: [\"lib/mod3/**\"]\n\n### q244 | question | open [selected]\ntext: Record q244 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c116 | claim | unassessed [selected]\ntext: Record c116 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q237 | question | open [selected]\ntext: Record q237 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c235 | claim | unassessed [selected]\ntext: Record c235 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d106 | decision | adopted [selected]\ntext: Record d106 about module 3\nchoice: Choice 318\napplicable: false\nblocked_by: [\"c24\"]\nblocked: c24 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c24\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q230 | question | open [selected]\ntext: Record q230 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c228 | claim | unassessed [selected]\ntext: Record c228 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c102 | claim | unassessed [selected]\ntext: Record c102 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d225 | decision | adopted [selected]\ntext: Record d225 about module 3\nchoice: Choice 675\nscope: [\"lib/mod3/**\"]\n\n### q223 | question | open [selected]\ntext: Record q223 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c221 | claim | unassessed [selected]\ntext: Record c221 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d218 | decision | adopted [selected]\ntext: Record d218 about module 3\nchoice: Choice 654\napplicable: false\nblocked_by: [\"c76\"]\nblocked: c76 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c76\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q216 | question | open [selected]\ntext: Record q216 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c214 | claim | unassessed [selected]\ntext: Record c214 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d211 | decision | adopted [selected]\ntext: Record d211 about module 3\nchoice: Choice 633\nscope: [\"lib/mod3/**\"]\n\n### c88 | claim | unassessed [selected]\ntext: Record c88 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q209 | question | open [selected]\ntext: Record q209 about module 3\nscope: [\"lib/mod3/**\"]\n\n### d204 | decision | adopted [selected]\ntext: Record d204 about module 3\nchoice: Choice 612\nscope: [\"lib/mod3/**\"]\n\n### q202 | question | open [selected]\ntext: Record q202 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c200 | claim | unassessed [selected]\ntext: Record c200 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c74 | claim | unassessed [selected]\ntext: Record c74 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d197 | decision | adopted [selected]\ntext: Record d197 about module 3\nchoice: Choice 591\nscope: [\"lib/mod3/**\"]\n\n### q195 | question | open [selected]\ntext: Record q195 about module 3\nscope: [\"lib/mod3/**\"]\n\n# index: 40 more current records\nc193 claim unassessed Record c193 about module 3\nd190 decision adopted Record d190 about module 3\nq188 question open Record q188 about module 3\nc186 claim unassessed Record c186 about module 3\nd183 decision adopted Record d183 about module 3\nq181 question open Record q181 about module 3\nc179 claim unassessed Record c179 about module 3\nd176 decision adopted Record d176 about module 3\nq174 question open Record q174 about module 3\nd50 decision adopted Record d50 about module 3\nc172 claim unassessed Record c172 about module 3\nd169 decision adopted Record d169 about module 3\nd43 decision adopted Record d43 about module 3\nq167 question open Record q167 about module 3\nc165 claim unassessed Record c165 about module 3\nc39 claim unassessed Record c39 about module 3\nq160 question open Record q160 about module 3\nc158 claim unassessed Record c158 about module 3\nd29 decision adopted Record d29 about module 3\nq153 question open Record q153 about module 3\nc151 claim unassessed Record c151 about module 3\nd148 decision adopted Record d148 about module 3\nq146 question open Record q146 about module 3\nd22 decision adopted Record d22 about module 3\nc144 claim unassessed Record c144 about module 3\nd141 decision adopted Record d141 about module 3\nq139 question open Record q139 about module 3\nc137 claim unassessed Record c137 about module 3\nd134 decision adopted Record d134 about module 3\nd8 decision adopted Record d8 about module 3\nq132 question open Record q132 about module 3\nc130 claim unassessed Record c130 about module 3\nc4 claim unassessed Record c4 about module 3\nd127 decision adopted Record d127 about module 3\nq125 question open Record q125 about module 3\nc123 claim unassessed Record c123 about module 3\nd120 decision adopted Record d120 about module 3\nq118 question open Record q118 about module 3\nd113 decision adopted Record d113 about module 3\nq111 question open Record q111 about module 3\n# and 1319 more; docket list\n\n# full text: 141; index: 40; retired: 0.\n# Not listed: 1319; reach them with docket list.\n# Related records in index only: 18; formulas remain complete.\n# Coverage: partial, 624 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n1500_qnone_fyes_b900": "# docket: repo | revision: 782c58a0a496 | latest: d500@782c58a0a496\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n# index: c396, d498, q496, c494, d491, q489, c487, d484, q482, c480, d477, q475, c473, c347, d470, q468, c466, d463, q461, c459, d456, c207, q454, c452, d449, q447, c445, d442, q440, c438, d435, q433, c431, d428, q426, c424, d421, q419, c417, d414\n# and 1460 more; docket list\n\n# full text: 0; index: 40; retired: 0.\n# Not listed: 1460; reach them with docket list.\n# Coverage: partial, 214 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n1500_qnone_fyes_b8000": "# docket: repo | revision: 782c58a0a496 | latest: d500@782c58a0a496\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n### c396 | claim | unassessed [selected]\ntext: Record c396 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d498 | decision | adopted [selected]\ntext: Record d498 about module 3\nchoice: Choice 1494\nscope: [\"lib/mod3/**\"]\n\n### q496 | question | open [selected]\ntext: Record q496 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c494 | claim | unassessed [selected]\ntext: Record c494 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d491 | decision | adopted [selected]\ntext: Record d491 about module 3\nchoice: Choice 1473\nscope: [\"lib/mod3/**\"]\n\n### q489 | question | open [selected]\ntext: Record q489 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c487 | claim | unassessed [selected]\ntext: Record c487 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d484 | decision | adopted [selected]\ntext: Record d484 about module 3\nchoice: Choice 1452\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d390\"]\n\n### q482 | question | open [selected]\ntext: Record q482 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c480 | claim | unassessed [selected]\ntext: Record c480 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d477 | decision | adopted [selected]\ntext: Record d477 about module 3\nchoice: Choice 1431\nscope: [\"lib/mod3/**\"]\n\n### q475 | question | open [selected]\ntext: Record q475 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c473 | claim | unassessed [selected]\ntext: Record c473 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c347 | claim | unassessed [selected]\ntext: Record c347 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d470 | decision | adopted [selected]\ntext: Record d470 about module 3\nchoice: Choice 1410\nscope: [\"lib/mod3/**\"]\n\n### q468 | question | open [selected]\ntext: Record q468 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c466 | claim | unassessed [selected]\ntext: Record c466 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d463 | decision | adopted [selected]\ntext: Record d463 about module 3\nchoice: Choice 1389\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d151\"]\n\n### q461 | question | open [selected]\ntext: Record q461 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c459 | claim | unassessed [selected]\ntext: Record c459 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d456 | decision | adopted [selected]\ntext: Record d456 about module 3\nchoice: Choice 1368\napplicable: false\nblocked_by: [\"d374\", \"c299\"]\nblocked: d374 -> c299 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d374\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c207 | claim | unassessed [selected]\ntext: Record c207 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q454 | question | open [selected]\ntext: Record q454 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c452 | claim | unassessed [selected]\ntext: Record c452 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d449 | decision | adopted [selected]\ntext: Record d449 about module 3\nchoice: Choice 1347\nscope: [\"lib/mod3/**\"]\n\n### q447 | question | open [selected]\ntext: Record q447 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c445 | claim | unassessed [selected]\ntext: Record c445 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d442 | decision | adopted [selected]\ntext: Record d442 about module 3\nchoice: Choice 1326\napplicable: false\nblocked_by: [\"c148\"]\nblocked: c148 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c148\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q440 | question | open [selected]\ntext: Record q440 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c438 | claim | unassessed [selected]\ntext: Record c438 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d435 | decision | adopted [selected]\ntext: Record d435 about module 3\nchoice: Choice 1305\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d274\"]\n\n### q433 | question | open [selected]\ntext: Record q433 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c431 | claim | unassessed [selected]\ntext: Record c431 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d428 | decision | adopted [selected]\ntext: Record d428 about module 3\nchoice: Choice 1284\nscope: [\"lib/mod3/**\"]\n\n### q426 | question | open [selected]\ntext: Record q426 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c424 | claim | unassessed [selected]\ntext: Record c424 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# index: 40 more current records\nd421 decision adopted Record d421 about module 3\nq419 question open Record q419 about module 3\nc417 claim unassessed Record c417 about module 3\nd414 decision adopted Record d414 about module 3\nq412 question open Record q412 about module 3\nc410 claim unassessed Record c410 about module 3\nd407 decision adopted Record d407 about module 3\nq405 question open Record q405 about module 3\nc403 claim unassessed Record c403 about module 3\nd400 decision adopted Record d400 about module 3\nq398 question open Record q398 about module 3\nd274 decision adopted Record d274 about module 3\nd393 decision adopted Record d393 about module 3\nq391 question open Record q391 about module 3\nc389 claim unassessed Record c389 about module 3\nd386 decision adopted Record d386 about module 3\nq384 question open Record q384 about module 3\nc382 claim unassessed Record c382 about module 3\nd379 decision adopted Record d379 about module 3\nq377 question open Record q377 about module 3\nd1 decision adopted Record d1 about module 3\nc375 claim unassessed Record c375 about module 3\nd372 decision adopted Record d372 about module 3\nq370 question open Record q370 about module 3\nc368 claim unassessed Record c368 about module 3\nc242 claim unassessed Record c242 about module 3\nd365 decision adopted Record d365 about module 3\nq363 question open Record q363 about module 3\nd239 decision adopted Record d239 about module 3\nc361 claim unassessed Record c361 about module 3\nd358 decision adopted Record d358 about module 3\nq356 question open Record q356 about module 3\nd232 decision adopted Record d232 about module 3\nc354 claim unassessed Record c354 about module 3\nd351 decision adopted Record d351 about module 3\nq349 question open Record q349 about module 3\nd344 decision adopted Record d344 about module 3\nq342 question open Record q342 about module 3\nc340 claim unassessed Record c340 about module 3\nd337 decision adopted Record d337 about module 3\n# and 1424 more; docket list\n\n# full text: 36; index: 40; retired: 0.\n# Not listed: 1424; reach them with docket list.\n# Related records in index only: 5; formulas remain complete.\n# Coverage: partial, 181 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n", +"n1500_qnone_fyes_bdefault": "# docket: repo | revision: 782c58a0a496 | latest: d500@782c58a0a496\n# Context: decisions are commitments, claims are premises, questions are inquiries; states are not truth and authors are recorders.\n# files: lib/mod3/cache.py\n\n### c396 | claim | unassessed [selected]\ntext: Record c396 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d498 | decision | adopted [selected]\ntext: Record d498 about module 3\nchoice: Choice 1494\nscope: [\"lib/mod3/**\"]\n\n### q496 | question | open [selected]\ntext: Record q496 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c494 | claim | unassessed [selected]\ntext: Record c494 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d491 | decision | adopted [selected]\ntext: Record d491 about module 3\nchoice: Choice 1473\nscope: [\"lib/mod3/**\"]\n\n### q489 | question | open [selected]\ntext: Record q489 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c487 | claim | unassessed [selected]\ntext: Record c487 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d484 | decision | adopted [selected]\ntext: Record d484 about module 3\nchoice: Choice 1452\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d390\"]\n\n### q482 | question | open [selected]\ntext: Record q482 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c480 | claim | unassessed [selected]\ntext: Record c480 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d477 | decision | adopted [selected]\ntext: Record d477 about module 3\nchoice: Choice 1431\nscope: [\"lib/mod3/**\"]\n\n### q475 | question | open [selected]\ntext: Record q475 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c473 | claim | unassessed [selected]\ntext: Record c473 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### c347 | claim | unassessed [selected]\ntext: Record c347 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d470 | decision | adopted [selected]\ntext: Record d470 about module 3\nchoice: Choice 1410\nscope: [\"lib/mod3/**\"]\n\n### q468 | question | open [selected]\ntext: Record q468 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c466 | claim | unassessed [selected]\ntext: Record c466 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d463 | decision | adopted [selected]\ntext: Record d463 about module 3\nchoice: Choice 1389\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d151\"]\n\n### q461 | question | open [selected]\ntext: Record q461 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c459 | claim | unassessed [selected]\ntext: Record c459 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d456 | decision | adopted [selected]\ntext: Record d456 about module 3\nchoice: Choice 1368\napplicable: false\nblocked_by: [\"d374\", \"c299\"]\nblocked: d374 -> c299 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d374\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### c207 | claim | unassessed [selected]\ntext: Record c207 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### q454 | question | open [selected]\ntext: Record q454 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c452 | claim | unassessed [selected]\ntext: Record c452 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d449 | decision | adopted [selected]\ntext: Record d449 about module 3\nchoice: Choice 1347\nscope: [\"lib/mod3/**\"]\n\n### q447 | question | open [selected]\ntext: Record q447 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c445 | claim | unassessed [selected]\ntext: Record c445 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d442 | decision | adopted [selected]\ntext: Record d442 about module 3\nchoice: Choice 1326\napplicable: false\nblocked_by: [\"c148\"]\nblocked: c148 unassessed\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"c148\"]\nwarning: decision is not applicable; treat it as unavailable current support.\n\n### q440 | question | open [selected]\ntext: Record q440 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c438 | claim | unassessed [selected]\ntext: Record c438 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d435 | decision | adopted [selected]\ntext: Record d435 about module 3\nchoice: Choice 1305\nscope: [\"lib/mod3/**\"]\ndepends_on: [\"d274\"]\n\n### q433 | question | open [selected]\ntext: Record q433 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c431 | claim | unassessed [selected]\ntext: Record c431 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n### d428 | decision | adopted [selected]\ntext: Record d428 about module 3\nchoice: Choice 1284\nscope: [\"lib/mod3/**\"]\n\n### q426 | question | open [selected]\ntext: Record q426 about module 3\nscope: [\"lib/mod3/**\"]\n\n### c424 | claim | unassessed [selected]\ntext: Record c424 about module 3\nscope: [\"lib/mod3/**\"]\nwarning: effective state is unassessed; treat this record as unavailable current support.\n\n# index: 40 more current records\nd421 decision adopted Record d421 about module 3\nq419 question open Record q419 about module 3\nc417 claim unassessed Record c417 about module 3\nd414 decision adopted Record d414 about module 3\nq412 question open Record q412 about module 3\nc410 claim unassessed Record c410 about module 3\nd407 decision adopted Record d407 about module 3\nq405 question open Record q405 about module 3\nc403 claim unassessed Record c403 about module 3\nd400 decision adopted Record d400 about module 3\nq398 question open Record q398 about module 3\nd274 decision adopted Record d274 about module 3\nd393 decision adopted Record d393 about module 3\nq391 question open Record q391 about module 3\nc389 claim unassessed Record c389 about module 3\nd386 decision adopted Record d386 about module 3\nq384 question open Record q384 about module 3\nc382 claim unassessed Record c382 about module 3\nd379 decision adopted Record d379 about module 3\nq377 question open Record q377 about module 3\nd1 decision adopted Record d1 about module 3\nc375 claim unassessed Record c375 about module 3\nd372 decision adopted Record d372 about module 3\nq370 question open Record q370 about module 3\nc368 claim unassessed Record c368 about module 3\nc242 claim unassessed Record c242 about module 3\nd365 decision adopted Record d365 about module 3\nq363 question open Record q363 about module 3\nd239 decision adopted Record d239 about module 3\nc361 claim unassessed Record c361 about module 3\nd358 decision adopted Record d358 about module 3\nq356 question open Record q356 about module 3\nd232 decision adopted Record d232 about module 3\nc354 claim unassessed Record c354 about module 3\nd351 decision adopted Record d351 about module 3\nq349 question open Record q349 about module 3\nd344 decision adopted Record d344 about module 3\nq342 question open Record q342 about module 3\nc340 claim unassessed Record c340 about module 3\nd337 decision adopted Record d337 about module 3\n# and 1424 more; docket list\n\n# full text: 36; index: 40; retired: 0.\n# Not listed: 1424; reach them with docket list.\n# Related records in index only: 5; formulas remain complete.\n# Coverage: partial, 181 in the index only. Selected ledger data only.\n# Declared grounds; evidence references are supplied provenance, not freshly verified.\n# Retrieve full record: docket show RECORD_ID --json\n" } \ No newline at end of file diff --git a/tests/golden/regenerate.py b/tests/golden/regenerate.py index 71a1211..33d3443 100644 --- a/tests/golden/regenerate.py +++ b/tests/golden/regenerate.py @@ -20,14 +20,16 @@ def ledger(count): random.seed(SEED + count) records = [] + numbers = dict.fromkeys(("decision", "claim", "question"), 0) for number in range(1, count + 1): kind = ("decision", "claim", "question")[number % 3] + numbers[kind] += 1 fields = {"choice": f"Choice {number}"} if kind == "decision" else {} if kind == "decision" and number > 3 and random.random() < 0.6: target, target_kind = records[random.randrange(len(records))] if target_kind in ("claim", "decision"): fields["depends_on"] = (target,) - ident = f"{kind[0]}{number}" + ident = f"{kind[0]}{numbers[kind]}" records.append((ident, kind)) yield entry( ident, diff --git a/tests/test_check_order.py b/tests/test_check_order.py new file mode 100644 index 0000000..bd432e8 --- /dev/null +++ b/tests/test_check_order.py @@ -0,0 +1,60 @@ +import json +import os +import subprocess +import sys +import tempfile +import unittest +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) +from docket import ledger + +DOCKET = str(Path(__file__).resolve().parent.parent / "bin" / "docket") + + +def record(kind, ident, **kwargs): + if kind == "decision": + kwargs.setdefault("choice", "yes") + return ledger.make_record(kind, f"{kind} {ident}", author="t", record_id=ident, **kwargs) + + +def check(records): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + (root / ".git").mkdir() + path = root / ".docket" / "ledger.jsonl" + path.parent.mkdir() + path.write_text("".join(json.dumps(r) + "\n" for r in records)) + env = dict(os.environ, DOCKET_HOME=str(root / "global"), DOCKET_NO_UPDATE_CHECK="1") + return subprocess.run( + [sys.executable, DOCKET, "check"], cwd=root, env=env, capture_output=True, text=True + ) + + +class CheckOrderTests(unittest.TestCase): + def test_a_kind_may_restart_its_numbering_below_another_kinds_maximum(self): + result = check([record("claim", "c5"), record("decision", "d1"), record("question", "q2")]) + self.assertEqual(result.returncode, 0, result.stdout) + self.assertIn("3 records", result.stdout) + + def test_a_number_that_does_not_increase_within_its_kind_is_a_fault(self): + result = check([record("claim", "c5"), record("decision", "d9"), record("claim", "c3")]) + self.assertEqual(result.returncode, 1) + self.assertIn("line 3: id c3 does not increase past c5", result.stdout) + + def test_a_duplicate_id_is_still_reported(self): + result = check([record("claim", "c1"), record("claim", "c1")]) + self.assertEqual(result.returncode, 1) + self.assertIn("duplicate id c1, first seen on line 1", result.stdout) + + def test_an_old_ledger_prints_the_migrate_instruction_once(self): + old = [dict(record("claim", f"c{n}"), schema=2) for n in (1, 2, 3)] + result = check(old) + self.assertEqual(result.returncode, 1) + self.assertEqual(result.stdout.count("docket migrate"), 1, result.stdout) + self.assertIn("schema 2", result.stdout) + self.assertNotIn("docket rebase", result.stdout) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_correct_cli.py b/tests/test_correct_cli.py index d367186..3a128f4 100644 --- a/tests/test_correct_cli.py +++ b/tests/test_correct_cli.py @@ -111,7 +111,7 @@ def test_supersedes_is_refused_with_a_pointer_to_supersession(self): def test_decision_only_field_is_refused_on_a_claim(self): run(self.cwd, "claim", "Writes are durable.") - out = run(self.cwd, "correct", "c2", "--alternative", "x") + out = run(self.cwd, "correct", "c1", "--alternative", "x") self.assertEqual(out.returncode, 1) self.assertIn("decision-only field", out.stderr) @@ -154,7 +154,7 @@ def test_show_at_a_point_before_the_correction(self): run(self.cwd, "claim", "Writes are durable.") run(self.cwd, "correct", "d1", "--scope", "a.py") self.assertEqual(self.show("d1")["scope"], ["a.py"]) - out = run(self.cwd, "show", "d1", "--json", "--at", "c2") + out = run(self.cwd, "show", "d1", "--json", "--at", "c1") self.assertEqual(json.loads(out.stdout)["scope"], ["lib/cache.py"]) out = run(self.cwd, "show", "d1", "--json", "--at", "d1.1") self.assertEqual(json.loads(out.stdout)["scope"], ["a.py"]) @@ -224,7 +224,7 @@ def test_check_reports_a_malformed_correction(self): stream.write( json.dumps( { - "schema": 2, + "schema": ledger.SCHEMA, "kind": "correction", "id": "d1.2", "corrects": "d1", diff --git a/tests/test_corrections.py b/tests/test_corrections.py index 588f4a2..875372b 100644 --- a/tests/test_corrections.py +++ b/tests/test_corrections.py @@ -12,7 +12,7 @@ def line(ident, target, fields, **extra): record = { - "schema": 2, + "schema": ledger.SCHEMA, "kind": "correction", "id": ident, "corrects": target, @@ -133,7 +133,7 @@ def test_nothing_may_point_at_a_correction(self): def test_record_numbering_ignores_corrections(self): entries = ledger.validate_entries([decision("d1"), line("d1.1", "d1", {"scope": []})]) - self.assertEqual(ledger.allocate_id(entries, "claim"), "c2") + self.assertEqual(ledger.allocate_id(entries, "claim"), "c1") class ReadTests(unittest.TestCase): @@ -222,9 +222,9 @@ def test_append_numbers_corrections_per_record(self): self.add("decision", "The cache lives in Redis.", choice="Redis") self.add("claim", "Writes are durable.") self.assertEqual(self.correct("d1", {"scope": ["a"]})["id"], "d1.1") - self.assertEqual(self.correct("c2", {"scope": ["a"]})["id"], "c2.1") + self.assertEqual(self.correct("c1", {"scope": ["a"]})["id"], "c1.1") self.assertEqual(self.correct("d1", {"scope": ["b"]})["id"], "d1.2") - self.assertEqual(self.add("claim", "Another.")["id"], "c3") + self.assertEqual(self.add("claim", "Another.")["id"], "c2") def test_concurrent_corrections_never_share_a_number(self): self.add("claim", "Writes are durable.") diff --git a/tests/test_docket.py b/tests/test_docket.py index a9699ed..9009244 100644 --- a/tests/test_docket.py +++ b/tests/test_docket.py @@ -81,7 +81,7 @@ def test_typed_commands_and_filters(self): result = run(root, "question", "Which database?") self.assertEqual(result.returncode, 0, result.stderr) result = run(root, "claim", "Postgres is supported", "--state", "accepted") - self.assertIn("c2", result.stdout) + self.assertIn("c1", result.stdout) result = run( root, "decision", @@ -91,12 +91,12 @@ def test_typed_commands_and_filters(self): "--alternative", "SQLite", "--depends-on", - "c2", + "c1", "--decided-by", "human", "--pin", ) - self.assertIn("d3", result.stdout) + self.assertIn("d1", result.stdout) result = run(root, "list", "--kind", "decision", "--json") data = json.loads(result.stdout) self.assertEqual(len(data), 1) @@ -120,6 +120,25 @@ def test_list_and_show_json_drop_legacy_unless_asked(self): kept = kept[0] if isinstance(kept, list) else kept self.assertEqual(kept["legacy"], {"source_id": "d1"}) + def test_list_and_show_json_drop_migrated_from_unless_asked(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + (root / ".git").mkdir() + run(root, "claim", "Premise", "--state", "accepted") + path = Path(run(root, "where").stdout.split()[0]) + lines = [json.loads(line) for line in path.read_text().splitlines()] + lines[-1]["migrated_from"] = "d17" + path.write_text("".join(json.dumps(line) + "\n" for line in lines)) + for cmd in (("list", "--json"), ("show", "c1", "--json")): + plain = json.loads(run(root, *cmd).stdout) + plain = plain[0] if isinstance(plain, list) else plain + self.assertNotIn("migrated_from", plain) + kept = json.loads(run(root, *cmd, "--legacy").stdout) + kept = kept[0] if isinstance(kept, list) else kept + self.assertEqual(kept["migrated_from"], "d17") + result = run(root, "list", "--json", "--fields", "id,migrated_from") + self.assertEqual(result.returncode, 2) + def test_list_json_fields_keeps_only_named_fields(self): with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) @@ -212,7 +231,7 @@ def test_a_batch_is_all_or_nothing_and_resolves_batch_references(self): self.assertEqual(result.returncode, 0, result.stderr) records = json.loads(run(root, "list", "--json").stdout) decision = next(r for r in records if r["kind"] == "decision") - self.assertEqual(decision["supports"], [["c2"]]) + self.assertEqual(decision["supports"], [["c1"]]) self.assertEqual(decision["answers"], ["q1"]) def test_symlinked_cli_resolves_lib_from_real_executable(self): @@ -436,9 +455,9 @@ def test_graph_payload_is_version_two_and_preserves_metadata(self): payload = docket_cli._graph_payload(entries, docket_cli.retired_by(entries)) self.assertEqual(payload["version"], 2) by_id = {entry["id"]: entry for entry in payload["entries"]} - self.assertEqual(by_id["d2"]["kind"], "decision") - self.assertTrue(by_id["d2"]["applicable"]) - self.assertEqual(by_id["d2"]["depends_on"], ["c1"]) + self.assertEqual(by_id["d1"]["kind"], "decision") + self.assertTrue(by_id["d1"]["applicable"]) + self.assertEqual(by_id["d1"]["depends_on"], ["c1"]) def test_static_graph_shows_blocked_decision_prerequisites(self): with tempfile.TemporaryDirectory() as tmp: @@ -728,7 +747,7 @@ def test_a_record_that_changed_and_newly_owes_review_prints_once(self): self.assertEqual(run(home, *args).returncode, 0) result = run(home, "context", "--since", token) self.assertEqual(result.returncode, 0, result.stderr) - self.assertEqual(result.stdout.count("### d3 "), 1) + self.assertEqual(result.stdout.count("### d1 "), 1) self.assertIn("3 no longer available, 0 newly owe review", result.stdout) diff --git a/tests/test_feature_cli.py b/tests/test_feature_cli.py index 28abf99..c8d28dd 100644 --- a/tests/test_feature_cli.py +++ b/tests/test_feature_cli.py @@ -170,6 +170,37 @@ def test_check_passes_on_a_healthy_store(self): code, _ = self.run_cli("check") self.assertEqual(code, 0) + def cited_store(self, key=None): + self.run_cli( + "claim", "Premise one", "--state", "accepted", "--scope", "a/**", "--cost", "none" + ) + self.run_cli("feature", "start", "one", "--text", "t", "--path", "a/**") + self.run_cli("feature", "amend", "one", "--include", "c1") + store = self.root / ".docket" / "features.jsonl" + if key is not None: + lines = [json.loads(line) for line in store.read_text(encoding="utf-8").splitlines()] + lines[-1]["keys"] = {"c1": key} + store.write_text("".join(json.dumps(line) + "\n" for line in lines), encoding="utf-8") + + def test_check_passes_when_a_stored_key_matches_its_record(self): + self.cited_store() + code, _ = self.run_cli("check") + self.assertEqual(code, 0) + + def test_check_reports_an_event_whose_stored_key_matches_no_record(self): + self.cited_store(key="0" * 12) + code, out = self.run_cli("check") + self.assertEqual(code, 1) + self.assertIn("c1", out) + self.assertIn("stored key", out) + + def test_check_ignores_a_stale_key_on_a_closed_feature(self): + # remap skips closed features, so reporting one would fail check forever. + self.cited_store(key="0" * 12) + self.run_cli("feature", "abandon", "one", "--text", "no") + code, _ = self.run_cli("check") + self.assertEqual(code, 0) + def test_check_reports_a_corrupt_feature_store(self): self.run_cli("feature", "start", "one", "--text", "t", "--path", "a/**") store = self.root / ".docket" / "features.jsonl" @@ -262,7 +293,7 @@ def test_an_id_on_an_invalid_record_still_counts_as_known(self): self.ledger_record( json.dumps( { - "schema": 2, + "schema": 3, "id": "d9", "kind": "decision", "text": "t", diff --git a/tests/test_features.py b/tests/test_features.py index 4de4187..5ae624b 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -1,3 +1,5 @@ +import hashlib +import json import sys import tempfile import unittest @@ -6,6 +8,7 @@ sys.path.insert(0, str(Path(__file__).parent.parent)) import docket.feature_project as feature_project import docket.features as features +from docket import ledger class EventSchemaTests(unittest.TestCase): @@ -62,6 +65,12 @@ def test_a_field_the_schema_gained_later_is_filled_on_read(self): del event["cleared"] self.assertEqual(features.validate_event(event)["cleared"], []) + def test_a_schema_one_event_is_refused_with_the_migrate_instruction(self): + event = dict(features.make_event("note", "slug-one", text="t"), schema=1) + with self.assertRaisesRegex(features.FeatureSchemaTooOld, "docket migrate"): + features.validate_event(event) + self.assertTrue(issubclass(features.FeatureSchemaTooOld, features.FeatureError)) + def test_a_line_that_declares_no_schema_is_still_refused(self): event = features.make_event("note", "slug-one", text="t") del event["schema"] @@ -102,10 +111,32 @@ def test_appended_events_read_back_in_order(self): self.assertEqual([e["event"] for e in features.read(self.path)], ["start", "note"]) def test_a_corrupt_line_names_its_line_number(self): - self.path.write_text('{"schema":1,"event":"nope"}\n', encoding="utf-8") + self.path.write_text('{"schema":2,"event":"nope"}\n', encoding="utf-8") with self.assertRaisesRegex(features.FeatureError, "line 1"): features.read(self.path) + def schema_one_line(self, ident="f1"): + event = dict( + features.make_event("start", "one", text="t", paths=["a/**"]), id=ident, schema=1 + ) + return json.dumps(event) + "\n" + + def test_read_refuses_a_schema_one_store_naming_the_line(self): + self.path.write_text(self.schema_one_line(), encoding="utf-8") + with self.assertRaisesRegex(features.FeatureSchemaTooOld, "line 1.*docket migrate"): + features.read(self.path) + + def test_an_archive_at_schema_one_still_sets_the_id_floor(self): + from docket.feature_archive import highest_archived_id + + archive = self.path.parent / "archive" + archive.mkdir() + (archive / "features-abc.jsonl").write_text(self.schema_one_line("f7"), encoding="utf-8") + self.assertEqual(highest_archived_id(self.path), 7) + self.path.write_text("", encoding="utf-8") + started = features.make_event("start", "one", text="t", paths=["a/**"]) + self.assertEqual(features.append(self.path, started)["id"], "f8") + def test_qualified_id_appends_eight_characters_of_base(self): event = self.add("start", "one", text="t", paths=["a/**"], base="6f0898e2c1f4a9") self.assertEqual(features.qualified(event), "f1@6f0898e2") @@ -211,5 +242,108 @@ def test_resolve_names_closed_ids_when_only_those_match(self): feature_project.resolve(self.current(), "one") +TS = "2026-01-01T00:00:00+00:00" + + +def stored_key(kind, text): + """The key recipe as it stood before id masking, for events written then.""" + raw = "\0".join((kind, TS, "t", "s", text)) + return hashlib.sha1(raw.encode("utf-8")).hexdigest()[:12] + + +def claim(ident, text): + return ledger.make_record( + "claim", text, state="accepted", author="t", session="s", ts=TS, record_id=ident + ) + + +class RecordKeyTests(unittest.TestCase): + def test_a_headline_with_no_id_token_keeps_its_key(self): + self.assertEqual( + ledger.record_key(claim("c1", "No ids in this headline")), + stored_key("claim", "No ids in this headline"), + ) + + def test_a_headline_id_token_does_not_move_the_key(self): + before = claim("c3", "Contradicts d2 outright") + after = claim("c2", "Contradicts d1 outright") + self.assertEqual(ledger.record_key(before), ledger.record_key(after)) + self.assertNotEqual(ledger.record_key(before), stored_key("claim", before["text"])) + + def test_a_key_stored_before_the_change_still_rebinds(self): + entries = [claim("c1", "Alpha"), claim("c2", "Beta")] + keys = {"c9": stored_key("claim", "Beta")} + self.assertEqual(ledger.rebind(["c9"], keys, entries), ["c2"]) + + def test_stale_keys_names_an_id_whose_key_matches_no_record(self): + entries = [claim("c1", "Alpha"), claim("c2", "Beta")] + keys = {"c1": stored_key("claim", "Alpha"), "c2": "0" * 12, "c3": "1" * 12} + self.assertEqual(ledger.stale_keys(["c1", "c2", "c3", "c4"], keys, entries), ["c2"]) + + def test_an_id_whose_key_names_another_record_is_rebound_not_stale(self): + entries = [claim("c1", "Alpha"), claim("c2", "Beta")] + keys = {"c1": stored_key("claim", "Beta")} + self.assertEqual(ledger.stale_keys(["c1"], keys, entries), []) + + +class RemapEventsTests(unittest.TestCase): + def setUp(self): + self.by_id = { + "c3": claim("c3", "Third premise"), + "d1": ledger.make_record( + "decision", + "Cache layer sits behind reads", + state="adopted", + choice="Cache", + alternatives=["No cache"], + rationale="Reads dominate", + author="t", + session="s", + ts=TS, + record_id="d1", + ), + "q1": ledger.make_record( + "question", "Which store?", author="t", session="s", ts=TS, record_id="q1" + ), + } + self.mapping = {"c4": "c3", "d2": "d1", "q5": "q1"} + + def event(self, **fields): + return dict( + features.make_event("start", "one", text="t", paths=["a/**"], ts=TS, **fields), + id="f1", + schema=1, + ) + + def test_every_ledger_ref_field_is_rewritten_and_keys_recomputed(self): + old = self.event( + include=["c4"], + exclude=["d2"], + held=["q5"], + failed=["c4", "d9"], + unanswered=["q5"], + keys={"c4": "a" * 12, "d2": "b" * 12, "q5": "c" * 12}, + ) + [new] = features.remap_events([old], self.mapping, self.by_id) + self.assertEqual(new["schema"], 2) + self.assertEqual(new["include"], ["c3"]) + self.assertEqual(new["exclude"], ["d1"]) + self.assertEqual(new["held"], ["q1"]) + self.assertEqual(new["failed"], ["c3", "d9"]) + self.assertEqual(new["unanswered"], ["q1"]) + self.assertEqual( + new["keys"], {i: ledger.record_key(self.by_id[i]) for i in ("c3", "d1", "q1")} + ) + + def test_a_key_whose_record_is_missing_is_kept_under_the_new_id(self): + old = self.event(include=["c4"], keys={"c4": "a" * 12}) + [new] = features.remap_events([old], self.mapping, {}) + self.assertEqual(new["keys"], {"c3": "a" * 12}) + + def test_a_schema_two_event_passes_through_untouched(self): + done = dict(self.event(include=["c3"]), schema=2) + self.assertEqual(features.remap_events([done], {"c3": "c2"}, self.by_id), [done]) + + if __name__ == "__main__": unittest.main() diff --git a/tests/test_graph_cli.py b/tests/test_graph_cli.py index 5ea45b1..1192248 100644 --- a/tests/test_graph_cli.py +++ b/tests/test_graph_cli.py @@ -86,7 +86,7 @@ def seed(self): "--supports", "c1", "--answers", - "q2", + "q1", "--cost", "a nested path is never seen", ) @@ -96,15 +96,15 @@ def test_mermaid_prints_a_flowchart(self): code, out, _ = self.run_cli("export", "--format", "mermaid") self.assertEqual(code, 0) self.assertTrue(out.startswith("flowchart LR")) - self.assertIn("c1 --> d3", out) - self.assertIn("d3 ==> q2", out) + self.assertIn("c1 --> d1", out) + self.assertIn("d1 ==> q1", out) def test_dot_prints_a_digraph(self): self.seed() code, out, _ = self.run_cli("export", "--format", "dot") self.assertEqual(code, 0) self.assertTrue(out.startswith("digraph docket {")) - self.assertIn('"c1" -> "d3"', out) + self.assertIn('"c1" -> "d1"', out) def test_group_scope_clusters_the_dot_output(self): self.seed() @@ -120,9 +120,9 @@ def test_an_unknown_focus_exits_1(self): def test_focus_outside_the_filtered_selection_exits_1(self): self.seed() - code, _, err = self.run_cli("export", "--kind", "claim", "--focus", "d3") + code, _, err = self.run_cli("export", "--kind", "claim", "--focus", "d1") self.assertEqual(code, 1) - self.assertIn("d3 is not in this selection", err) + self.assertIn("d1 is not in this selection", err) def test_hops_without_focus_exits_2(self): self.seed() @@ -141,16 +141,16 @@ def test_focus_reaches_the_renderer(self): self.seed() code, out, _ = self.run_cli("export", "--focus", "c1", "--hops", "1") self.assertEqual(code, 0) - self.assertIn("c1 --> d3", out) - self.assertNotIn("q2", out) + self.assertIn("c1 --> d1", out) + self.assertNotIn("q1", out) def test_focus_on_a_record_with_no_relation_exits_0(self): self.seed() self.run_cli("claim", "a lone fact", "--state", "accepted", "--scope", "z/**") - code, out, _ = self.run_cli("export", "--focus", "c4") + code, out, _ = self.run_cli("export", "--focus", "c2") self.assertEqual(code, 0) - self.assertIn("c4", out) - self.assertNotIn("d3", out) + self.assertIn("c2", out) + self.assertNotIn("d1", out) def test_an_empty_ledger_says_nothing_is_recorded(self): code, out, _ = self.run_cli("export", "--format", "mermaid") @@ -188,7 +188,7 @@ def test_find_narrows_the_export(self): "plugin", ) self.assertLessEqual(len(narrow), len(wide)) - self.assertIn("d3", narrow) + self.assertIn("d1", narrow) def test_detail_zero_prints_bare_ids(self): self.seed() @@ -222,9 +222,9 @@ def test_superseded_reaches_the_renderer(self): "--scope", "a/**", "--supersedes", - "d3", + "d1", "--answers", - "q2", + "q1", "--cost", "none", ) @@ -269,7 +269,7 @@ def test_a_supersede_chain_draws_every_link(self): "--scope", "a/**", "--supersedes", - "d3", + "d1", "--cost", "none", ) @@ -281,13 +281,13 @@ def test_a_supersede_chain_draws_every_link(self): "--scope", "a/**", "--supersedes", - "d4", + "d2", "--cost", "none", ) _, out, _ = self.run_cli("export", "--format", "mermaid", "--superseded") - self.assertIn("d4 -- retires --> d3", out) - self.assertIn("d5 -- retires --> d4", out) + self.assertIn("d2 -- retires --> d1", out) + self.assertIn("d3 -- retires --> d2", out) def test_a_kind_filter_drops_the_edges_it_orphans(self): # --kind hands over a subset. An edge whose other end is filtered out @@ -301,7 +301,7 @@ def test_a_kind_filter_drops_the_edges_it_orphans(self): "decision", ) self.assertNotIn("c1", out) - self.assertNotIn("q2", out) + self.assertNotIn("q1", out) def test_a_state_filter_reaches_the_export(self): self.seed() @@ -401,7 +401,7 @@ def test_a_filter_reaches_the_csv_tables(self): "decision", ) if (target / "nodes.csv").is_file(): - self.assertNotIn("q2", (target / "nodes.csv").read_text(encoding="utf-8")) + self.assertNotIn("q1", (target / "nodes.csv").read_text(encoding="utf-8")) if __name__ == "__main__": diff --git a/tests/test_graph_export.py b/tests/test_graph_export.py index a7529b9..32e166e 100644 --- a/tests/test_graph_export.py +++ b/tests/test_graph_export.py @@ -492,7 +492,10 @@ def test_this_project_s_own_ledger_renders(self): path = Path(__file__).parent.parent / ".docket" / "ledger.jsonl" if not path.is_file(): self.skipTest("no project ledger") - entries = ledger.project(ledger.read(path), validated=True) + try: + entries = ledger.project(ledger.read(path), validated=True) + except ledger.SchemaTooOld: + self.skipTest("this checkout's ledger is not migrated yet") svg = self.render(to_dot(entries, superseded=True)) self.assertGreater(len(svg), 10_000) @@ -539,7 +542,10 @@ def test_this_project_s_own_ledger_parses(self): path = Path(__file__).parent.parent / ".docket" / "ledger.jsonl" if not path.is_file(): self.skipTest("no project ledger") - entries = ledger.project(ledger.read(path), validated=True) + try: + entries = ledger.project(ledger.read(path), validated=True) + except ledger.SchemaTooOld: + self.skipTest("this checkout's ledger is not migrated yet") self.render(to_mermaid(entries, superseded=True)) diff --git a/tests/test_guard_ledger.py b/tests/test_guard_ledger.py index 9383ce4..0d89c2b 100644 --- a/tests/test_guard_ledger.py +++ b/tests/test_guard_ledger.py @@ -33,11 +33,27 @@ def test_edit_and_write_on_a_ledger_ask(self): ".docket/ledger.jsonl", "/home/user/project/.docket/ledger.jsonl", ".docket/ledger.jsonl.schema1", + ".docket/ledger.jsonl.schema2", ".docket/migration-v0.8-map.json", ): with self.subTest(tool=tool, path=path): self.assertEqual(decide(tool, {"file_path": path}), "ask") + def test_every_schema_backup_asks(self): + for path in ( + ".docket/ledger.jsonl.schema1", + ".docket/ledger.jsonl.schema2", + ".docket/ledger.jsonl.schema12", + ".docket/features.jsonl.schema1", + ): + with self.subTest(path=path): + self.assertEqual(decide("Edit", {"file_path": path}), "ask") + + def test_a_name_that_only_looks_like_a_backup_is_untouched(self): + for path in (".docket/ledger.jsonl.schema", ".docket/ledger.jsonl.schemax"): + with self.subTest(path=path): + self.assertEqual(decide("Edit", {"file_path": path}), "allow") + def test_an_ordinary_file_is_untouched(self): for path in ("docket/ledger.py", "README.md", "docket/notes.jsonl", ".docket/notes.txt"): with self.subTest(path=path): diff --git a/tests/test_ledger.py b/tests/test_ledger.py index 680299f..df1b869 100644 --- a/tests/test_ledger.py +++ b/tests/test_ledger.py @@ -20,10 +20,11 @@ def tearDown(self): def add(self, kind, text, **kwargs): return ledger.append(self.path, ledger.make_record(kind, text, author="test", **kwargs)) - def test_ids_share_one_sequence_across_kinds(self): + def test_each_kind_counts_from_one(self): self.assertEqual(self.add("claim", "one")["id"], "c1") - self.assertEqual(self.add("question", "two")["id"], "q2") - self.assertEqual(self.add("decision", "three", choice="yes")["id"], "d3") + self.assertEqual(self.add("question", "two")["id"], "q1") + self.assertEqual(self.add("decision", "three", choice="yes")["id"], "d1") + self.assertEqual(self.add("claim", "four")["id"], "c2") def test_invalid_state_kind_and_references_are_rejected(self): with self.assertRaises(ledger.LedgerError): @@ -34,13 +35,18 @@ def test_invalid_state_kind_and_references_are_rejected(self): with self.assertRaisesRegex(ledger.LedgerError, "not a question"): self.add("claim", "answer", answers=["c1"]) - def test_global_numeric_sequence_is_unique_and_increasing(self): + def test_sequence_increases_within_a_kind_and_ignores_other_kinds(self): first = ledger.make_record("claim", "first", author="test", record_id="c2") - second = ledger.make_record( + other_kind = ledger.make_record( "decision", "second", choice="yes", author="test", record_id="d1" ) - with self.assertRaisesRegex(ledger.LedgerError, "monotonically"): - ledger.validate_entries([first, second]) + ledger.validate_entries([first, other_kind]) + same_kind = ledger.make_record("claim", "third", author="test", record_id="c1") + with self.assertRaisesRegex(ledger.LedgerError, "per-kind sequence must increase"): + ledger.validate_entries([first, other_kind, same_kind]) + again = ledger.make_record("claim", "again", author="test", record_id="c2") + with self.assertRaisesRegex(ledger.LedgerError, "duplicate ID"): + ledger.validate_entries([first, again]) def test_unknown_fields_and_invalid_falsy_shapes_are_rejected(self): for field, value in ( @@ -68,6 +74,29 @@ def test_legacy_audit_metadata_is_an_opaque_object(self): with self.assertRaisesRegex(ledger.LedgerError, "legacy must be an object"): ledger.validate_record(claim) + def test_migrated_from_names_a_record_id(self): + claim = ledger.make_record("claim", "claim", author="test", record_id="c1") + claim["migrated_from"] = "c184" + self.assertEqual(ledger.validate_record(claim)["migrated_from"], "c184") + for bad in ("184", "x1", "", 7, ["c1"], "c01"): + claim["migrated_from"] = bad + with self.assertRaisesRegex(ledger.LedgerError, "migrated_from", msg=repr(bad)): + ledger.validate_record(claim) + + def test_migrated_from_is_an_audit_field(self): + self.assertEqual(ledger.AUDIT_FIELDS, frozenset({"legacy", "migrated_from"})) + self.assertLessEqual(ledger.AUDIT_FIELDS, ledger.ALLOWED_FIELDS) + + def test_next_id_counts_within_one_kind(self): + records = [ + ledger.make_record("claim", "a", author="t", record_id="c4"), + ledger.make_record("decision", "b", choice="x", author="t", record_id="d9"), + ] + self.assertEqual(ledger.next_id(records, "claim"), "5") + self.assertEqual(ledger.next_id(records, "decision"), "10") + self.assertEqual(ledger.next_id(records, "question"), "1") + self.assertEqual(ledger.allocate_id(records, "question"), "q1") + def test_supersession_and_resolution_are_derived(self): question = self.add("question", "which?") claim = self.add("claim", "yes", state="accepted", answers=[question["id"]]) @@ -99,13 +128,64 @@ def test_corrupt_and_schema_one_files_fail_loudly(self): with self.assertRaisesRegex(ledger.LedgerError, "migrate"): ledger.read(self.path) + def test_an_older_schema_raises_schema_too_old_with_its_version(self): + claim = ledger.make_record("claim", "one", author="test", record_id="c1") + correction = { + "schema": 2, + "kind": "correction", + "id": "c1.1", + "corrects": "c1", + "fields": {"scope": []}, + "reason": "", + "ts": "", + "author": "", + "session": "", + "branch": "", + } + cases = { + "schema one": ([{"schema": 1}], 1), + "no schema": ([{"id": "d1", "question": "Q"}], 1), + "schema two record": ([dict(claim, schema=2)], 2), + "schema two correction": ([claim, correction], 2), + } + for name, (lines, version) in cases.items(): + with self.subTest(name): + self.path.write_text("".join(json.dumps(line) + "\n" for line in lines)) + with self.assertRaises(ledger.SchemaTooOld) as caught: + ledger.read(self.path) + self.assertEqual(caught.exception.version, version) + self.assertIn("docket migrate", str(caught.exception)) + with self.assertRaises(ledger.SchemaTooOld): + ledger.validate_entries(lines) + + def test_the_line_validators_of_corrections_and_reviews_refuse_old_schemas(self): + from docket import corrections, reviews + + old_fix = {"schema": 2, "id": "c1.1", "corrects": "c1", "fields": {"scope": []}} + with self.assertRaises(ledger.SchemaTooOld): + corrections.validate(old_fix, None) + old_review = {"schema": 2, "id": "c1.r1", "reviews": "c1", "grounds": {"c1": "c1"}} + with self.assertRaises(ledger.SchemaTooOld): + reviews.validate(old_review, None) + + def test_corruption_is_not_schema_too_old(self): + self.path.write_text("not json\n") + with self.assertRaises(ledger.LedgerError) as caught: + ledger.read(self.path) + self.assertNotIsInstance(caught.exception, ledger.SchemaTooOld) + claim = ledger.make_record("claim", "one", author="test", record_id="c1") + self.path.write_text(json.dumps(dict(claim, schema=9)) + "\n") + with self.assertRaises(ledger.LedgerError) as caught: + ledger.read(self.path) + self.assertNotIsInstance(caught.exception, ledger.SchemaTooOld) + def test_append_repairs_missing_final_newline_without_merging_records(self): first = ledger.make_record("claim", "one", author="test") first["id"] = "c1" self.path.write_text(json.dumps(first)) second = ledger.append(self.path, ledger.make_record("question", "two", author="test")) - self.assertEqual(second["id"], "q2") - self.assertEqual([entry["id"] for entry in ledger.read(self.path)], ["c1", "q2"]) + self.assertEqual(second["id"], "q1") + self.assertEqual([entry["id"] for entry in ledger.read(self.path)], ["c1", "q1"]) def test_torn_final_line_is_skipped_on_read_and_dropped_on_append(self): first = ledger.make_record("claim", "one", author="test") @@ -121,9 +201,9 @@ def test_torn_final_line_is_skipped_on_read_and_dropped_on_append(self): self.assertIn("torn", err.getvalue()) with redirect_stderr(StringIO()): second = ledger.append(self.path, ledger.make_record("question", "two", author="t")) - self.assertEqual(second["id"], "q2") + self.assertEqual(second["id"], "q1") self.assertEqual(self.path.read_text().count("\n"), 2) - self.assertEqual([e["id"] for e in ledger.read(self.path)], ["c1", "q2"]) + self.assertEqual([e["id"] for e in ledger.read(self.path)], ["c1", "q1"]) def test_bad_line_with_a_newline_is_not_treated_as_torn(self): self.path.write_text('{"id":"c1"\n') @@ -136,7 +216,7 @@ def test_a_newer_writers_fields_and_kinds_read_leniently_but_block_writes(self): claim = ledger.make_record("claim", "one", author="test", record_id="c1") claim["confidence"] = 0.9 - future = {"schema": 2, "kind": "assumption", "id": "a2", "text": "later kind"} + future = {"schema": ledger.SCHEMA, "kind": "assumption", "id": "a2", "text": "later kind"} self.path.write_text(json.dumps(claim) + "\n" + json.dumps(future) + "\n") err = StringIO() with redirect_stderr(err): @@ -226,7 +306,7 @@ def test_read_without_the_lock_does_not_wait(self): # locking read here would deadlock the writer. self.assertEqual(len(ledger.read(path, lock=False)), 1) - def test_concurrent_appends_keep_global_ids_unique(self): + def test_concurrent_appends_keep_ids_unique_within_each_kind(self): def write(index): kind = ("claim", "question", "decision")[index % 3] kwargs = {"choice": "yes"} if kind == "decision" else {} @@ -235,7 +315,9 @@ def write(index): with ThreadPoolExecutor(max_workers=8) as workers: ids = list(workers.map(write, range(18))) self.assertEqual(len(set(ids)), 18) - self.assertEqual({int(item[1:]) for item in ids}, set(range(1, 19))) + for letter in "cqd": + numbers = {int(item[1:]) for item in ids if item[0] == letter} + self.assertEqual(numbers, set(range(1, 7)), letter) class ValidationScalingTests(unittest.TestCase): diff --git a/tests/test_merge_driver.py b/tests/test_merge_driver.py index b4adeff..5427654 100644 --- a/tests/test_merge_driver.py +++ b/tests/test_merge_driver.py @@ -1,3 +1,5 @@ +import contextlib +import io import json import os import shutil @@ -10,7 +12,7 @@ ROOT = Path(__file__).parent.parent sys.path.insert(0, str(ROOT)) -from docket import corrections, features, merge_driver # noqa: E402 +from docket import corrections, features, merge_driver, migrate, reviews # noqa: E402 from docket.ledger import make_record, read # noqa: E402 @@ -22,6 +24,34 @@ def write(path, records): path.write_text("".join(json.dumps(r) + "\n" for r in records), encoding="utf-8") +def decision(ident, text, **kwargs): + return make_record( + "decision", + text, + state="adopted", + choice="Cache", + alternatives=["No cache"], + rationale="Reads dominate", + author="t", + record_id=ident, + **kwargs, + ) + + +def v2(records): + return [dict(r, schema=2) for r in records] + + +def upgraded(records): + """What a schema-2 ledger holds after `docket migrate`.""" + return migrate.renumber_step(v2(records))[0] + + +def features_event(ident, slug, schema, **fields): + made = features.make_event("start", slug, text=slug, paths=["src/**"], ts="t", **fields) + return dict(made, id=ident, schema=schema) + + class DriverTests(unittest.TestCase): def setUp(self): self.tmp = Path(tempfile.mkdtemp()) @@ -130,6 +160,201 @@ def test_an_empty_base_merges_two_new_ledgers(self): self.assertEqual([r["text"] for r in read(self.ours)], ["Ours", "Theirs"]) +class CrossMigrationTests(unittest.TestCase): + """Two branches that each ran `docket migrate`, from a schema-2 BASE. + + Schema-2 ids are one global sequence: c1 d2 c3. After the migration they + are per kind: c1 d1 c2. + """ + + def setUp(self): + self.tmp = Path(tempfile.mkdtemp()) + self.addCleanup(shutil.rmtree, self.tmp) + self.base, self.ours, self.theirs = (self.tmp / n for n in ("O", "A", "B")) + self.shared = [ + claim("c1", "Shared premise"), + decision("d2", "Cache layer sits behind reads", supports=[["c1"]]), + ] + + def run_driver(self): + err = io.StringIO() + with contextlib.redirect_stderr(err): + code = merge_driver.run(self.base, self.ours, self.theirs) + return code, err.getvalue() + + def ids(self): + return [r["id"] for r in read(self.ours)] + + def test_both_sides_migrated_separately_merge_without_duplicates(self): + write(self.base, v2(self.shared)) + write(self.ours, upgraded(self.shared + [claim("c3", "Ours only")])) + write(self.theirs, upgraded(self.shared + [claim("c3", "Theirs only")])) + before = self.ours.read_text(encoding="utf-8") + self.assertEqual(self.run_driver()[0], 0) + self.assertTrue(self.ours.read_text(encoding="utf-8").startswith(before)) + merged = read(self.ours) + self.assertEqual(self.ids(), ["c1", "d1", "c2", "c3"]) + # One old id on two records, one per branch. + self.assertEqual([merged[2]["migrated_from"], merged[3]["migrated_from"]], ["c3", "c3"]) + self.assertEqual([merged[2]["text"], merged[3]["text"]], ["Ours only", "Theirs only"]) + once = self.ours.read_text(encoding="utf-8") + self.assertEqual(self.run_driver()[0], 0) + self.assertEqual(self.ours.read_text(encoding="utf-8"), once) + + def test_a_correction_and_a_review_of_a_shared_record_merge_once(self): + fix = corrections.make("d2", {"scope": ["a.py"]}, author="t") + fix["id"] = "d2.1" + look = reviews.make("d2", author="t") + look["id"] = "d2.r1" + look["grounds"] = {"c1": "c1"} + write(self.base, v2(self.shared)) + write(self.ours, upgraded(self.shared + [claim("c3", "Ours only")])) + write(self.theirs, upgraded(self.shared + [fix, look])) + self.assertEqual(self.run_driver()[0], 0) + merged = read(self.ours) + self.assertEqual(self.ids(), ["c1", "d1", "c2", "d1.1", "d1.r1"]) + self.assertEqual(merged[3]["corrects"], "d1") + self.assertEqual((merged[4]["reviews"], merged[4]["grounds"]), ("d1", {"c1": "c1"})) + once = self.ours.read_text(encoding="utf-8") + self.assertEqual(self.run_driver()[0], 0) + self.assertEqual(self.ours.read_text(encoding="utf-8"), once) + + def test_a_branch_that_merged_main_before_the_migration_merges_back_without_duplicates(self): + base = [claim("c1", "Shared premise")] + main = base + [decision("d2", "Cache layer sits behind reads", supports=[["c1"]])] + branch = base + [claim("c2", "Branch only")] + # A schema-2 `docket rebase` appended main's decision to the branch + # under the next global id, d3. + branch = branch + [dict(main[1], id="d3")] + branch = branch + [claim("c4", "Cites the cache", supports=[["d3"]])] + write(self.base, v2(base)) + write(self.ours, upgraded(main)) + write(self.theirs, upgraded(branch)) + self.assertEqual(self.run_driver()[0], 0) + merged = read(self.ours) + self.assertEqual(self.ids(), ["c1", "d1", "c2", "c3"]) + self.assertEqual([r["text"] for r in merged][2:], ["Branch only", "Cites the cache"]) + self.assertEqual(merged[3]["supports"], [["d1"]]) + once = self.ours.read_text(encoding="utf-8") + self.assertEqual(self.run_driver()[0], 0) + self.assertEqual(self.ours.read_text(encoding="utf-8"), once) + + def test_ours_migrated_and_theirs_not_is_refused_with_markers(self): + write(self.base, v2(self.shared)) + write(self.ours, upgraded(self.shared) + [claim("c2", "Ours only")]) + write(self.theirs, v2(self.shared + [claim("c3", "Theirs only")])) + code, err = self.run_driver() + self.assertEqual(code, 1) + self.assertIn("<<<<<<<", self.ours.read_text(encoding="utf-8")) + self.assertIn("the other branch's ledger is schema 2", err) + self.assertIn("docket migrate", err) + + def test_theirs_migrated_and_ours_not_is_refused_with_markers(self): + write(self.base, v2(self.shared)) + write(self.ours, v2(self.shared + [claim("c3", "Ours only")])) + write(self.theirs, upgraded(self.shared) + [claim("c2", "Theirs only")]) + code, err = self.run_driver() + self.assertEqual(code, 1) + self.assertIn("<<<<<<<", self.ours.read_text(encoding="utf-8")) + self.assertIn("this branch's ledger is schema 2", err) + + def test_an_unreadable_base_is_refused_with_markers(self): + for label, content in ( + ("non-UTF-8", b'{"id":"c1"}\n\xff\xfe\n'), + ("non-object", b"[1, 2]\n"), + ("non-object after a record", json.dumps(claim("c1", "x")).encode() + b"\n7\n"), + ): + with self.subTest(label): + self.base.write_bytes(content) + write(self.ours, [claim("c1", "Ours")]) + write(self.theirs, [claim("c1", "Theirs")]) + code, _ = self.run_driver() + self.assertEqual(code, 1) + self.assertIn("<<<<<<<", self.ours.read_text(encoding="utf-8")) + + def test_an_unreadable_base_beside_feature_stores_is_refused_with_markers(self): + good = json.dumps(features_event("f1", "shared", 2)).encode() + for label, content in ( + ("non-UTF-8", good + b"\n\xff\xfe\n"), + ("non-object", good + b"\n[1]\n"), + ): + with self.subTest(label): + self.base.write_bytes(content) + write(self.ours, [features_event("f1", "ours", 2)]) + write(self.theirs, [features_event("f1", "theirs", 2)]) + code, _ = self.run_driver() + self.assertEqual(code, 1) + self.assertIn("<<<<<<<", self.ours.read_text(encoding="utf-8")) + + def test_a_schema_2_base_with_a_non_object_line_is_refused_with_markers(self): + self.base.write_bytes(json.dumps(v2(self.shared)[0]).encode() + b"\n[1]\n") + write(self.ours, upgraded(self.shared)) + write(self.theirs, upgraded(self.shared)) + code, _ = self.run_driver() + self.assertEqual(code, 1) + self.assertIn("<<<<<<<", self.ours.read_text(encoding="utf-8")) + + def test_an_empty_base_still_merges_two_migrated_ledgers(self): + self.base.write_text("", encoding="utf-8") + write(self.ours, [claim("c1", "Ours")]) + write(self.theirs, [claim("c1", "Theirs")]) + self.assertEqual(self.run_driver()[0], 0) + self.assertEqual(self.ids(), ["c1", "c2"]) + + def test_features_base_at_schema_1_matches_its_migrated_copy(self): + # ours archived the old feature; theirs still carries it, migrated. + # A strict key would see a new event and resurrect it. + old = features_event("f1", "old", 1, include=["d2"], keys={"d2": "a" * 12}) + migrated = dict(old, schema=2, include=["d1"], keys={"d1": "b" * 12}) + write(self.base, [old]) + write(self.ours, [features_event("f1", "ours", 2)]) + write(self.theirs, [migrated, features_event("f2", "theirs", 2)]) + self.assertEqual(self.run_driver()[0], 0) + merged = features.read(self.ours) + self.assertEqual([(e["id"], e["slug"]) for e in merged], [("f1", "ours"), ("f2", "theirs")]) + + def test_one_feature_event_carried_by_both_sides_under_different_ids_merges_once(self): + # A pre-migration features merge copied the event across verbatim; each + # branch's migration then mapped its include through its own ledger. + ours_copy = features_event("f1", "shared", 2, include=["d1"], keys={"d1": "a" * 12}) + theirs_copy = dict(ours_copy, include=["d2"], keys={"d2": "a" * 12}) + write(self.base, [features_event("f1", "shared", 1, include=["d3"])]) + write(self.ours, [ours_copy]) + write(self.theirs, [theirs_copy, features_event("f2", "theirs", 2)]) + self.assertEqual(self.run_driver()[0], 0) + merged = features.read(self.ours) + self.assertEqual( + [(e["id"], e["slug"]) for e in merged], [("f1", "shared"), ("f2", "theirs")] + ) + self.assertEqual(merged[0]["include"], ["d1"]) + + def test_features_sides_at_different_schemas_are_refused_with_markers(self): + for ours_schema, theirs_schema in ((1, 2), (2, 1), (1, 1)): + write(self.base, [features_event("f1", "shared", 1)]) + write(self.ours, [features_event("f1", "shared", ours_schema)]) + write( + self.theirs, + [ + features_event("f1", "shared", theirs_schema), + features_event("f2", "t", theirs_schema), + ], + ) + code, err = self.run_driver() + self.assertEqual(code, 1, (ours_schema, theirs_schema)) + self.assertIn("<<<<<<<", self.ours.read_text(encoding="utf-8")) + self.assertIn("features file is schema 1", err) + self.assertIn("docket migrate", err) + + def test_a_schema_1_ledger_side_is_refused_too(self): + write(self.base, v2(self.shared)) + write(self.ours, upgraded(self.shared)) + write(self.theirs, [dict(r, schema=1) for r in self.shared]) + code, err = self.run_driver() + self.assertEqual(code, 1) + self.assertIn("<<<<<<<", self.ours.read_text(encoding="utf-8")) + self.assertIn("schema 1", err) + + DOCKET = str(ROOT / "bin" / "docket") diff --git a/tests/test_migrate_cli.py b/tests/test_migrate_cli.py index 1b711f0..b23e2a1 100644 --- a/tests/test_migrate_cli.py +++ b/tests/test_migrate_cli.py @@ -11,6 +11,9 @@ from pathlib import Path ROOT = Path(__file__).resolve().parent.parent +sys.path.insert(0, str(ROOT)) +from docket.ledger import make_record # noqa: E402 + DOCKET = ROOT / "bin" / "docket" @@ -54,12 +57,315 @@ def project(work: Path, records: list[dict]) -> Path: def run(work: Path, *argv: str) -> subprocess.CompletedProcess: - env = dict(os.environ, DOCKET_HOME=str(work / "global")) + env = dict(os.environ, DOCKET_HOME=str(work / "global"), DOCKET_NO_UPDATE_CHECK="1") return subprocess.run( [sys.executable, str(DOCKET), *argv], cwd=work, capture_output=True, text=True, env=env ) +def commit(work: Path) -> None: + """Commit everything, so `--rewrite` sees tracked, clean files.""" + git = ["git", "-c", "user.name=t", "-c", "user.email=t@example.com"] + subprocess.run([*git, "add", "-A"], cwd=work, check=True) + subprocess.run([*git, "commit", "-q", "-m", "fixture"], cwd=work, check=True) + + +def rec(kind: str, ident: str, text: str, *, schema: int = 3, extra=None, **fields) -> dict: + if kind == "decision": + fields.setdefault("choice", "chosen") + # make_record builds a new record, which never carries an audit field. + audit = {key: fields.pop(key) for key in ("migrated_from",) if key in fields} + record = make_record( + kind, text, record_id=ident, ts="2026-09-12T00:00:00+00:00", author="tester", **fields + ) + return {**record, "schema": schema, **audit, **(extra or {})} + + +class MigrateSchema3CliTests(unittest.TestCase): + def schema2(self, work: Path) -> Path: + return project( + work, + [ + rec("claim", "c1", "First claim", schema=2), + rec("decision", "d2", "Use the first claim", schema=2, supports=[["c1"]]), + rec("claim", "c3", "Second claim", schema=2), + rec("decision", "d4", "Follows d2 and c3 and c9", schema=2, supports=[["c3"]]), + rec("question", "q5", "What next", schema=2), + ], + ) + + def test_the_default_output_is_a_summary_without_the_per_record_report(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + ledger = self.schema2(work) + result = run(work, "migrate") + self.assertEqual(result.returncode, 0, result.stderr) + lines = result.stdout.splitlines() + self.assertEqual( + lines[0], + "docket: migrated 5 records from schema 2 to schema 3 " + "(2 claims, 2 decisions, 1 question)", + ) + self.assertIn("rewrote 1 prose field", result.stdout) + self.assertIn("left 1 unmapped id as written", result.stdout) + self.assertIn(f"original kept at {ledger}.schema2", result.stdout) + self.assertNotIn("d4 -> d2", result.stdout) + self.assertNotIn("Follows", result.stdout) + self.assertTrue(Path(str(ledger) + ".schema2").exists()) + + def test_dry_run_prints_the_report_then_every_prose_change_and_unmapped_token(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + ledger = self.schema2(work) + before = ledger.read_bytes() + result = run(work, "migrate", "--dry-run") + self.assertEqual(result.returncode, 0, result.stderr) + out = result.stdout + self.assertIn("d4 -> d2", out) + self.assertIn("q5 -> q1", out) + self.assertIn("d4 text: Follows d2 and c3 and c9 -> Follows d1 and c2 and c9", out) + self.assertIn("d4 text: unmapped c9", out) + self.assertLess(out.index("q5 -> q1"), out.index("d4 text:")) + self.assertIn("docket: would migrate 5 records from schema 2 to schema 3", out) + self.assertEqual(ledger.read_bytes(), before) + self.assertFalse(Path(str(ledger) + ".schema2").exists()) + + def test_rewrite_rewrites_the_named_files(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + self.schema2(work) + doc = work / "notes.md" + doc.write_text("d4 then d2, see c3. Keep c9.\n") + untouched = work / "plain.md" + untouched.write_text("nothing\n") + commit(work) + result = run(work, "migrate", "--rewrite", str(doc), str(untouched)) + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual(doc.read_text(), "d2 then d1, see c2. Keep c9.\n") + self.assertIn("rewrote 3 id mentions in 1 file", result.stdout) + self.assertIn(str(doc), result.stdout) + self.assertNotIn(str(untouched), result.stdout) + + def test_rewrite_with_dry_run_reports_files_and_counts_and_writes_nothing(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + self.schema2(work) + doc = work / "notes.md" + doc.write_text("d4 then d2, see c3.\n") + commit(work) + result = run(work, "migrate", "--dry-run", "--rewrite", str(doc)) + self.assertEqual(result.returncode, 0, result.stderr) + self.assertIn(f"{doc}: 3 ids", result.stdout) + self.assertIn("would rewrite 3 id mentions in 1 file", result.stdout) + self.assertEqual(doc.read_text(), "d4 then d2, see c3.\n") + + def test_rewrite_refuses_an_untracked_or_modified_file(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + ledger = self.schema2(work) + doc = work / "notes.md" + doc.write_text("d4\n") + commit(work) + fresh = work / "fresh.md" + fresh.write_text("d4\n") + before = ledger.read_bytes() + result = run(work, "migrate", "--rewrite", str(doc), str(fresh)) + self.assertEqual(result.returncode, 2) + self.assertIn("not tracked", result.stderr) + self.assertNotIn("--emit-map", result.stderr) + doc.write_text("d4 edited\n") + result = run(work, "migrate", "--rewrite", str(doc)) + self.assertEqual(result.returncode, 2) + self.assertIn("uncommitted", result.stderr) + self.assertEqual(ledger.read_bytes(), before) + + def test_rewrite_is_refused_once_the_ledger_is_at_schema_3(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + self.schema2(work) + doc = work / "notes.md" + doc.write_text("d4\n") + commit(work) + self.assertEqual(run(work, "migrate").returncode, 0) + result = run(work, "migrate", "--rewrite", str(doc)) + self.assertEqual(result.returncode, 2) + self.assertIn("already at schema 3", result.stderr) + self.assertNotIn("--emit-map", result.stderr) + self.assertEqual(doc.read_text(), "d4\n") + + def test_map_and_emit_map_are_refused_on_a_schema_2_ledger(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + ledger = self.schema2(work) + before = ledger.read_bytes() + mapping = work / "map.json" + mapping.write_text("{}") + for argv in (("--map", str(mapping)), ("--emit-map", str(work / "out.json"))): + result = run(work, "migrate", *argv) + self.assertEqual(result.returncode, 2, argv) + self.assertIn("schema 1", result.stderr) + self.assertNotIn("then 'docket migrate --map", result.stderr) + self.assertFalse((work / "out.json").exists()) + self.assertEqual(ledger.read_bytes(), before) + + def test_a_schema_1_ledger_still_gets_the_classification_hint_on_failure(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + project(work, [dict(LEGACY[0], state="parked")]) + result = run(work, "migrate") + self.assertEqual(result.returncode, 2) + self.assertIn("--emit-map", result.stderr) + + +class OldLedgerMessageTests(unittest.TestCase): + def old_ledger(self, work: Path) -> None: + project( + work, + [ + rec("claim", "c1", "First claim", schema=2), + rec("claim", "c2", "Second claim", schema=2), + ], + ) + + def test_context_prints_the_migrate_instruction_on_stdout_and_exits_0(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + self.old_ledger(work) + result = run(work, "context") + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual(result.stderr, "") + self.assertIn("schema 2", result.stdout) + self.assertIn(f"{DOCKET} migrate", result.stdout) + self.assertIn("--rewrite FILE...", result.stdout) + self.assertIn("commit ledger.jsonl and the features files", result.stdout) + self.assertIn("not the ledger.jsonl.schema* backup", result.stdout) + + def test_the_instruction_follows_the_harness_envelope(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + self.old_ledger(work) + result = run(work, "context", "--for", "gemini") + self.assertEqual(result.returncode, 0, result.stderr) + body = json.loads(result.stdout)["hookSpecificOutput"]["additionalContext"] + self.assertIn("migrate", body) + + def test_a_since_briefing_gets_the_same_instruction(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + self.old_ledger(work) + result = run(work, "context", "--since", "c1") + self.assertEqual(result.returncode, 0, result.stderr) + self.assertIn("migrate", result.stdout) + + def test_another_ledger_error_keeps_stderr_and_exit_1(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + ledger = project(work, [rec("claim", "c1", "First claim")]) + ledger.write_text(ledger.read_text() + "{not json\n") + result = run(work, "context") + self.assertEqual(result.returncode, 1) + self.assertEqual(result.stdout, "") + self.assertNotEqual(result.stderr, "") + + def test_a_current_ledger_still_briefs(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + project(work, [rec("claim", "c1", "First claim")]) + result = run(work, "context") + self.assertEqual(result.returncode, 0, result.stderr) + self.assertIn("First claim", result.stdout) + + def test_check_prints_the_instruction_once_and_no_per_line_faults(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + self.old_ledger(work) + result = run(work, "check") + self.assertEqual(result.returncode, 1) + combined = result.stdout + result.stderr + self.assertEqual(combined.count(f"{DOCKET} migrate"), 1) + self.assertNotIn("fault", combined) + self.assertNotIn("docket rebase", combined) + + +class OldIdTests(unittest.TestCase): + def ledger(self, work: Path) -> None: + # c1 and c3 both came from c4 on different branches. c2 came from c1, + # and c1 is also a current id: the old id resolves to the new record. + # c4 came from schema 1 as d9. + project( + work, + [ + rec("claim", "c1", "First", branch="a", migrated_from="c4"), + rec("claim", "c2", "Second", branch="a", migrated_from="c1"), + rec("claim", "c3", "Third", branch="b", migrated_from="c4"), + rec("claim", "c4", "Fourth", extra={"legacy": {"source_id": "d9"}}), + ], + ) + + def test_show_names_the_command_that_finds_a_vanished_old_id(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + self.ledger(work) + result = run(work, "show", "d9") + self.assertEqual(result.returncode, 1) + self.assertEqual(result.stdout, "") + self.assertIn("no entry d9", result.stderr) + self.assertIn("docket list --where was:d9", result.stderr) + + def test_show_is_silent_about_an_old_id_that_is_also_a_current_id(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + self.ledger(work) + result = run(work, "show", "c1") + self.assertEqual(result.returncode, 0, result.stderr) + self.assertIn("First", result.stdout) + self.assertEqual(result.stderr, "") + + def test_show_gives_no_hint_for_an_id_nobody_carried(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + self.ledger(work) + result = run(work, "show", "c9") + self.assertEqual(result.returncode, 1) + self.assertNotIn("was:", result.stderr) + + def test_list_finds_both_records_that_share_an_old_id(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + self.ledger(work) + result = run(work, "list", "--where", "was:c4", "--json", "--legacy") + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual([r["id"] for r in json.loads(result.stdout)], ["c1", "c3"]) + narrowed = run(work, "list", "--where", "was:c4 branch:b", "--json") + self.assertEqual([r["id"] for r in json.loads(narrowed.stdout)], ["c3"]) + + def test_list_finds_a_record_by_its_schema_1_id(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + self.ledger(work) + result = run(work, "list", "--where", "was:d9", "--json") + self.assertEqual([r["id"] for r in json.loads(result.stdout)], ["c4"]) + + +class WasFindsRetiredTests(unittest.TestCase): + def test_was_includes_a_retired_record_without_superseded(self): + with tempfile.TemporaryDirectory() as work: + work = Path(work) + project( + work, + [ + rec("decision", "d1", "Old", migrated_from="d98"), + rec("decision", "d2", "New", supersedes=["d1"]), + ], + ) + found = run(work, "list", "--where", "was:d98", "--json") + self.assertEqual([r["id"] for r in json.loads(found.stdout)], ["d1"]) + plain = run(work, "list", "--json") + self.assertEqual([r["id"] for r in json.loads(plain.stdout)], ["d2"]) + negated = run(work, "list", "--where=-was:d97", "--json") + self.assertEqual([r["id"] for r in json.loads(negated.stdout)], ["d2"]) + + class MigrateCliTests(unittest.TestCase): def test_migration_converts_the_project_ledger(self): with tempfile.TemporaryDirectory() as work: @@ -68,7 +374,7 @@ def test_migration_converts_the_project_ledger(self): result = run(work, "migrate") self.assertEqual(result.returncode, 0, result.stderr) records = [json.loads(line) for line in ledger.read_text().splitlines() if line.strip()] - self.assertEqual([r["id"] for r in records], ["d1", "q2"]) + self.assertEqual([r["id"] for r in records], ["d1", "q1"]) self.assertTrue(Path(str(ledger) + ".schema1").exists()) def test_a_converted_ledger_lists(self): @@ -80,7 +386,7 @@ def test_a_converted_ledger_lists(self): self.assertEqual(result.returncode, 0, result.stderr) self.assertIn("d1", result.stdout) - def test_a_schema_two_ledger_exits_clean_and_changes_nothing(self): + def test_a_schema_three_ledger_exits_clean_and_changes_nothing(self): with tempfile.TemporaryDirectory() as work: work = Path(work) ledger = project(work, LEGACY) @@ -88,9 +394,37 @@ def test_a_schema_two_ledger_exits_clean_and_changes_nothing(self): after = ledger.read_bytes() result = run(work, "migrate") self.assertEqual(result.returncode, 0, result.stderr) - self.assertIn("already schema 2", result.stdout) + self.assertIn("already schema 3", result.stdout) self.assertEqual(ledger.read_bytes(), after) + def test_a_schema_two_ledger_migrates_and_a_map_is_refused(self): + records = [ + dict( + json.loads( + json.dumps( + { + "schema": 2, "kind": "claim", "id": "c5", "text": "Premise", + "state": "accepted", "ts": "", "author": "", "session": "", + "branch": "", "scope": [], "rationale": "", "supports": [], + "depends_on": [], "answers": [], "supersedes": [], "evidence": [], + "revisit": "", "cost_if_wrong": "", "pinned": False, + } + ) + ) + ) + ] # fmt: skip + with tempfile.TemporaryDirectory() as work: + work = Path(work) + ledger = project(work, records) + refused = run(work, "migrate", "--emit-map", str(work / "map.json")) + self.assertEqual(refused.returncode, 2) + self.assertIn("applies to a schema 1 ledger", refused.stderr) + result = run(work, "migrate") + self.assertEqual(result.returncode, 0, result.stderr) + self.assertIn("original kept at", result.stdout) + self.assertTrue(Path(str(ledger) + ".schema2").exists()) + self.assertEqual(json.loads(ledger.read_text())["id"], "c1") + def test_a_dry_run_reports_and_writes_nothing(self): with tempfile.TemporaryDirectory() as work: work = Path(work) @@ -99,7 +433,7 @@ def test_a_dry_run_reports_and_writes_nothing(self): result = run(work, "migrate", "--dry-run") self.assertEqual(result.returncode, 0, result.stderr) self.assertIn("d1 -> d1 decision/adopted", result.stdout) - self.assertIn("d2 -> q2 question/open", result.stdout) + self.assertIn("d2 -> q1 question/open", result.stdout) self.assertEqual(ledger.read_bytes(), before) self.assertFalse(Path(str(ledger) + ".schema1").exists()) diff --git a/tests/test_migration.py b/tests/test_migration.py index 428e000..4dc7657 100644 --- a/tests/test_migration.py +++ b/tests/test_migration.py @@ -2,15 +2,23 @@ from __future__ import annotations +import hashlib import json +import os +import subprocess import sys import tempfile +import time import unittest from pathlib import Path +from unittest import mock sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) +from docket import features, ledger from docket import migrate as docket_migrate +from docket.ledger import SCHEMA, LedgerError, make_record +from docket.ledger import read as ledger_read def load_migrator(): @@ -316,6 +324,7 @@ def test_version_detection(self): self.assertEqual(docket_migrate.detect_version([{"id": "d1"}]), 1) self.assertEqual(docket_migrate.detect_version([{"schema": 1}]), 1) self.assertEqual(docket_migrate.detect_version([{"schema": 2}]), 2) + self.assertEqual(docket_migrate.detect_version([{"schema": 3}]), 3) with self.assertRaises(docket_migrate.MigrationError): docket_migrate.detect_version([{"schema": 1}, {"schema": 2}]) @@ -349,7 +358,7 @@ def test_a_settled_record_superseding_an_open_record_becomes_an_answer(self): entries = ledger_read(path) projected = {r["id"]: r for r in project(entries)} - self.assertEqual(projected["q19"]["state"], "resolved") + self.assertEqual(projected["q1"]["state"], "resolved") def test_an_open_record_superseding_an_open_record_keeps_supersedes(self): source = [ @@ -392,8 +401,9 @@ def test_a_support_edge_into_a_question_is_dropped(self): docket_migrate.migrate_in_place(path) converted = [json.loads(line) for line in path.read_text().splitlines() if line.strip()] by_id = {r["id"]: r for r in converted} - self.assertEqual(by_id["d6"]["supports"], []) - self.assertEqual(by_id["d6"]["legacy"]["relation_map"]["source_because"], [["d1"]]) + self.assertEqual(by_id["d1"]["supports"], []) + self.assertEqual(by_id["d1"]["migrated_from"], "d6") + self.assertEqual(by_id["d1"]["legacy"]["relation_map"]["source_because"], [["d1"]]) def test_a_justification_set_keeps_its_non_question_member(self): source = [ @@ -447,63 +457,64 @@ def test_both_rules_emit_a_note_naming_both_records(self): ) -class InPlaceTests(unittest.TestCase): - def legacy(self) -> list[dict]: - return [ - { - "id": "d1", - "ts": "2026-01-01T00:00:00+00:00", - "state": "settled", - "question": "Ship it?", - "answer": "Yes.", - "because": [], - "supersedes": [], - "cost_if_wrong": "", - "session": "", - "author": "", - "branch": "", - }, - { - "id": "d2", - "ts": "2026-01-02T00:00:00+00:00", - "state": "ruled-out", - "question": "Delete the key?", - "answer": "No.", - "because": ["d1"], - "supersedes": [], - "cost_if_wrong": "", - "session": "", - "author": "", - "branch": "", - }, - ] +def legacy_ledger() -> list[dict]: + return [ + { + "id": "d1", + "ts": "2026-01-01T00:00:00+00:00", + "state": "settled", + "question": "Ship it?", + "answer": "Yes.", + "because": [], + "supersedes": [], + "cost_if_wrong": "", + "session": "", + "author": "", + "branch": "", + }, + { + "id": "d2", + "ts": "2026-01-02T00:00:00+00:00", + "state": "ruled-out", + "question": "Delete the key?", + "answer": "No.", + "because": ["d1"], + "supersedes": [], + "cost_if_wrong": "", + "session": "", + "author": "", + "branch": "", + }, + ] + +class InPlaceTests(unittest.TestCase): def test_conversion_replaces_the_file_and_keeps_the_original(self): with tempfile.TemporaryDirectory() as work: path = Path(work) / "ledger.jsonl" - write_jsonl(path, self.legacy()) + write_jsonl(path, legacy_ledger()) original = path.read_bytes() - count, _, _ = docket_migrate.migrate_in_place(path) - self.assertEqual(count, 2) + result = docket_migrate.migrate_in_place(path) + self.assertEqual(result.count, 2) backup = Path(str(path) + ".schema1") self.assertEqual(backup.read_bytes(), original) converted = [json.loads(line) for line in path.read_text().splitlines() if line.strip()] self.assertEqual([r["id"] for r in converted], ["d1", "d2"]) - self.assertTrue(all(r["schema"] == 2 for r in converted)) + self.assertTrue(all(r["schema"] == 3 for r in converted)) def test_the_result_reads_back_through_the_ledger_reader(self): from docket.ledger import read as ledger_read with tempfile.TemporaryDirectory() as work: path = Path(work) / "ledger.jsonl" - write_jsonl(path, self.legacy()) + write_jsonl(path, legacy_ledger()) docket_migrate.migrate_in_place(path) self.assertEqual(len(ledger_read(path)), 2) def test_an_existing_backup_stops_the_command(self): with tempfile.TemporaryDirectory() as work: path = Path(work) / "ledger.jsonl" - write_jsonl(path, self.legacy()) + write_jsonl(path, legacy_ledger()) Path(str(path) + ".schema1").write_text("earlier\n") before = path.read_bytes() with self.assertRaises(docket_migrate.MigrationError): @@ -513,17 +524,17 @@ def test_an_existing_backup_stops_the_command(self): def test_a_dry_run_writes_nothing(self): with tempfile.TemporaryDirectory() as work: path = Path(work) / "ledger.jsonl" - write_jsonl(path, self.legacy()) + write_jsonl(path, legacy_ledger()) before = path.read_bytes() - count, report, _ = docket_migrate.migrate_in_place(path, dry_run=True) - self.assertEqual(count, 2) - self.assertEqual(len(report), 2) - self.assertIn("d1", report[0]) + result = docket_migrate.migrate_in_place(path, dry_run=True) + self.assertEqual(result.count, 2) + self.assertEqual(len(result.report), 2) + self.assertIn("d1", result.report[0]) self.assertEqual(path.read_bytes(), before) self.assertFalse(Path(str(path) + ".schema1").exists()) def test_a_failure_leaves_the_ledger_untouched(self): - records = self.legacy() + records = legacy_ledger() records[0]["state"] = "parked" with tempfile.TemporaryDirectory() as work: path = Path(work) / "ledger.jsonl" @@ -539,8 +550,8 @@ def test_an_explicit_map_overrides_the_derived_one(self): with tempfile.TemporaryDirectory() as work: work = Path(work) path = work / "ledger.jsonl" - write_jsonl(path, self.legacy()) - override = docket_migrate.derive_mapping(self.legacy()) + write_jsonl(path, legacy_ledger()) + override = docket_migrate.derive_mapping(legacy_ledger()) override["d1"]["kind"] = "claim" override["d1"]["state"] = "accepted" override["d1"]["id"] = "c1" @@ -554,5 +565,582 @@ def test_an_explicit_map_overrides_the_derived_one(self): self.assertEqual(converted[0]["id"], "c1") +def schema_two_ledger() -> list[dict]: + """Seven schema-2 lines: every kind, a correction, a review, and a prose mention chain.""" + + def make(kind, ident, text, **kwargs): + record = make_record(kind, text, author="t", ts="2026-10-01T00:00:00+00:00", **kwargs) + return {**record, "id": ident, "schema": 2} + + chosen = make("decision", "d2", "Cache in Redis", choice="Redis", supports=[["c1"]]) + chosen["legacy"] = {"source_id": "d1", "relation_map": {"mapped_answers": ["q99"]}} + retiring = make("decision", "d4", "Cache for sixty seconds", choice="Redis, 60s") + retiring.update( + answers=["q3"], + supersedes=["d2"], + supports=[["c1"]], + rationale="Replaces d2 after q3; c1 still holds", + ) + fix = { + "schema": 2, + "kind": "correction", + "id": "d4.1", + "corrects": "d4", + "fields": {"rationale": "Replaces d2 after q3."}, + "reason": "", + "ts": "2026-10-01T00:00:01+00:00", + "author": "t", + "session": "", + "branch": "", + } + review = { + "schema": 2, + "kind": "review", + "id": "d4.r1", + "reviews": "d4", + "grounds": {"c1": "c1"}, + "note": "", + "ts": "2026-10-01T00:00:02+00:00", + "author": "t", + "session": "", + "branch": "", + } + return [ + make("claim", "c1", "Reads are cached", state="accepted"), + chosen, + make("question", "q3", "Which TTL?"), + retiring, + fix, + review, + make("claim", "c5", "d4 settles the TTL, d2 is retired", supports=[["c1"]]), + ] + + +class MigrationEdgeTests(unittest.TestCase): + def test_a_ledger_that_cannot_be_renumbered_is_refused_untouched(self): + # A hand-resolved merge can leave one id twice; renumbering it would + # point every later citation of that id at one of the two by chance. + first = {**make_record("claim", "One", author="t", record_id="c1"), "schema": 2} + twin = {**make_record("claim", "Two", author="t", record_id="c1"), "schema": 2} + with tempfile.TemporaryDirectory() as work: + path = Path(work) / "ledger.jsonl" + write_jsonl(path, [first, twin]) + before = path.read_bytes() + with self.assertRaisesRegex(docket_migrate.MigrationError, "docket check"): + docket_migrate.migrate_in_place(path) + self.assertEqual(path.read_bytes(), before) + self.assertFalse(Path(str(path) + ".schema2").exists()) + + def test_an_empty_ledger_has_nothing_to_migrate(self): + with tempfile.TemporaryDirectory() as work: + path = Path(work) / "ledger.jsonl" + path.write_text("") + result = docket_migrate.migrate_in_place(path) + self.assertEqual(result.count, 0) + self.assertEqual(path.read_text(), "") + self.assertFalse(Path(str(path) + ".schema2").exists()) + + def test_two_thousand_records_migrate_in_linear_time(self): + rows: list[dict] = [] + for n in range(1, 2001): + kind = ("claim", "decision", "question")[n % 3] + fields: dict = {"choice": "Chosen"} if kind == "decision" else {} + if kind == "decision" and n > 3: + # n % 3 == 1 here, so the line before is a claim. + fields["supports"] = [[rows[-1]["id"]]] + cites = rows[-1]["id"] if rows else "nothing" + made = make_record( + kind, f"Record {n} follows {cites}", author="t", record_id=f"{kind[0]}{n}", **fields + ) + rows.append({**made, "schema": 2}) + with tempfile.TemporaryDirectory() as work: + path = Path(work) / "ledger.jsonl" + write_jsonl(path, rows) + start = time.monotonic() + result = docket_migrate.migrate_in_place(path, dry_run=True) + # Generous: a quadratic pass over 2000 lines takes far longer. + self.assertLess(time.monotonic() - start, 5.0) + self.assertEqual(result.count, 2000) + self.assertEqual(result.per_kind, {"claim": 666, "decision": 667, "question": 667}) + + +class SchemaThreeTests(unittest.TestCase): + def test_the_latest_schema_is_the_ledgers(self): + self.assertEqual(docket_migrate.SCHEMA_LATEST, SCHEMA) + + def test_schema_two_becomes_three_with_per_kind_ids(self): + with tempfile.TemporaryDirectory() as work: + path = Path(work) / "ledger.jsonl" + write_jsonl(path, schema_two_ledger()) + original = path.read_bytes() + result = docket_migrate.migrate_in_place(path) + self.assertEqual(Path(str(path) + ".schema2").read_bytes(), original) + self.assertFalse(Path(str(path) + ".schema1").exists()) + lines = [json.loads(line) for line in path.read_text().splitlines()] + self.assertEqual( + [line["id"] for line in lines], + ["c1", "d1", "q1", "d2", "d2.1", "d2.r1", "c2"], + ) + self.assertTrue(all(line["schema"] == 3 for line in lines)) + self.assertEqual( + [line.get("migrated_from") for line in lines], + ["c1", "d2", "q3", "d4", None, None, "c5"], + ) + by_id = {line["id"]: line for line in lines} + self.assertEqual(by_id["d2"]["supersedes"], ["d1"]) + self.assertEqual(by_id["d2"]["answers"], ["q1"]) + self.assertEqual(by_id["d2.1"]["corrects"], "d2") + self.assertEqual(by_id["d2.r1"]["reviews"], "d2") + self.assertEqual(by_id["d1"]["legacy"], schema_two_ledger()[1]["legacy"]) + # d4 -> d2 and d2 -> d1 in one line: a chained rewrite would give d1 twice. + self.assertEqual(by_id["c2"]["text"], "d2 settles the TTL, d1 is retired") + self.assertEqual(by_id["d2"]["rationale"], "Replaces d1 after q1; c1 still holds") + self.assertEqual(by_id["d2.1"]["fields"], {"rationale": "Replaces d1 after q1."}) + self.assertEqual( + result.mapping, {"c1": "c1", "d2": "d1", "q3": "q1", "d4": "d2", "c5": "c2"} + ) + self.assertEqual(result.per_kind, {"claim": 2, "decision": 2, "question": 1}) + self.assertEqual( + sorted(change.field for change in result.prose_changes), + ["rationale", "rationale", "text"], + ) + self.assertTrue(all(change.after is not None for change in result.prose_changes)) + self.assertEqual(result.count, 7) + self.assertEqual(result.backup, str(path) + ".schema2") + self.assertEqual(len(ledger_read(path)), 7) + + def test_schema_one_reaches_three_in_one_run(self): + third = dict(legacy_ledger()[1], id="d3", ts="2026-01-03T00:00:00+00:00") + with tempfile.TemporaryDirectory() as work: + path = Path(work) / "ledger.jsonl" + write_jsonl(path, [*legacy_ledger(), third]) + original = path.read_bytes() + result = docket_migrate.migrate_in_place(path) + self.assertEqual(Path(str(path) + ".schema1").read_bytes(), original) + self.assertFalse(Path(str(path) + ".schema2").exists()) + lines = [json.loads(line) for line in path.read_text().splitlines()] + self.assertEqual([line["id"] for line in lines], ["d1", "d2", "d3"]) + self.assertEqual([line["migrated_from"] for line in lines], ["d1", "d2", "d3"]) + self.assertEqual([line["legacy"]["source_id"] for line in lines], ["d1", "d2", "d3"]) + self.assertTrue(all(line["schema"] == 3 for line in lines)) + self.assertEqual(result.report[0], "d1 -> d1 decision/adopted") + + def test_a_schema_one_question_keeps_its_schema_two_id_as_migrated_from(self): + source = legacy_ledger() + source[1]["state"] = "open" + with tempfile.TemporaryDirectory() as work: + path = Path(work) / "ledger.jsonl" + write_jsonl(path, source) + result = docket_migrate.migrate_in_place(path) + lines = [json.loads(line) for line in path.read_text().splitlines()] + self.assertEqual([line["id"] for line in lines], ["d1", "q1"]) + self.assertEqual(lines[1]["migrated_from"], "q2") + self.assertEqual(lines[1]["legacy"]["source_id"], "d2") + self.assertEqual(result.report, ["d1 -> d1 decision/adopted", "d2 -> q1 question/open"]) + + def test_a_map_applies_only_to_schema_one(self): + with tempfile.TemporaryDirectory() as work: + path = Path(work) / "ledger.jsonl" + write_jsonl(path, schema_two_ledger()) + before = path.read_bytes() + with self.assertRaisesRegex(docket_migrate.MigrationError, "applies only to schema 1"): + docket_migrate.migrate_in_place(path, mapping_path=Path(work) / "map.json") + self.assertEqual(path.read_bytes(), before) + + def test_a_schema_three_ledger_is_left_alone(self): + with tempfile.TemporaryDirectory() as work: + path = Path(work) / "ledger.jsonl" + write_jsonl(path, [make_record("claim", "one", author="t", record_id="c1")]) + before = path.read_bytes() + result = docket_migrate.migrate_in_place(path) + self.assertEqual(result.count, 0) + self.assertEqual(path.read_bytes(), before) + self.assertFalse(Path(str(path) + ".schema3").exists()) + + def test_an_existing_backup_of_the_starting_schema_stops_the_run(self): + with tempfile.TemporaryDirectory() as work: + path = Path(work) / "ledger.jsonl" + write_jsonl(path, schema_two_ledger()) + Path(str(path) + ".schema2").write_text("earlier\n") + before = path.read_bytes() + with self.assertRaisesRegex(docket_migrate.MigrationError, "already exists"): + docket_migrate.migrate_in_place(path) + self.assertEqual(path.read_bytes(), before) + + def test_a_dry_run_reports_every_line_and_writes_nothing(self): + with tempfile.TemporaryDirectory() as work: + path = Path(work) / "ledger.jsonl" + write_jsonl(path, schema_two_ledger()) + before = path.read_bytes() + result = docket_migrate.migrate_in_place(path, dry_run=True) + self.assertEqual(path.read_bytes(), before) + self.assertEqual( + result.report, + [ + "c1 -> c1 claim/accepted", + "d2 -> d1 decision/adopted", + "q3 -> q1 question/open", + "d4 -> d2 decision/adopted", + "d4.1 -> d2.1 correction", + "d4.r1 -> d2.r1 review", + "c5 -> c2 claim/unassessed", + ], + ) + self.assertFalse(Path(str(path) + ".schema2").exists()) + + def test_a_failing_step_leaves_the_ledger_untouched(self): + records = schema_two_ledger() + records[3]["supersedes"] = ["q3"] + with tempfile.TemporaryDirectory() as work: + path = Path(work) / "ledger.jsonl" + write_jsonl(path, records) + before = path.read_bytes() + with self.assertRaises(LedgerError): + docket_migrate.migrate_in_place(path) + self.assertEqual(path.read_bytes(), before) + self.assertFalse(Path(str(path) + ".migrating").exists()) + + +class FeaturesMoveTests(unittest.TestCase): + TS = "2026-01-01T00:00:00+00:00" + + def setUp(self): + tmp = tempfile.TemporaryDirectory() + self.addCleanup(tmp.cleanup) + self.dir = Path(tmp.name) / ".docket" + (self.dir / "archive").mkdir(parents=True) + self.path = self.dir / "ledger.jsonl" + self.store = self.dir / "features.jsonl" + self.archive = self.dir / "archive" / "features-abc123.jsonl" + # Old ids c1 d2 c3 c4 become c1 d1 c2 c3. c3 cites d2 in its headline. + self.c1 = self.rec("claim", "c1", "First premise", state="accepted") + self.d2 = self.rec( + "decision", + "d2", + "Cache layer sits behind reads", + state="adopted", + choice="Cache", + alternatives=["No cache"], + rationale="Reads dominate", + supports=[["c1"]], + ) + self.c3 = self.rec("claim", "c3", "Contradicts d2 outright", state="accepted") + self.c4 = self.rec("claim", "c4", "Fourth premise", state="accepted") + write_jsonl(self.path, [self.c1, self.d2, self.c3, self.c4]) + + def rec(self, kind, ident, text, **fields): + made = ledger.make_record( + kind, text, author="t", session="s", ts=self.TS, record_id=ident, **fields + ) + return dict(made, schema=2) + + def old_key(self, entry): + parts = (entry["kind"], entry["ts"], entry["author"], entry["session"], entry["text"]) + return hashlib.sha1("\0".join(parts).encode("utf-8")).hexdigest()[:12] + + def event(self, ident, slug, **fields): + made = features.make_event("start", slug, text=slug, paths=["src/**"], ts=self.TS, **fields) + return dict(made, id=ident, schema=1) + + def ledger_schema(self): + return json.loads(self.path.read_text().splitlines()[0])["schema"] + + def test_features_and_archive_follow_the_ledger(self): + keys = { + "c4": self.old_key(self.c4), + "c3": self.old_key(self.c3), + "d2": self.old_key(self.d2), + } + write_jsonl( + self.store, + [self.event("f2", "live", include=["c4", "c3"], exclude=["d2"], keys=keys)], + ) + write_jsonl( + self.archive, + [self.event("f1", "old", include=["c4"], keys={"c4": self.old_key(self.c4)})], + ) + result = docket_migrate.migrate_in_place(self.path) + self.assertEqual(result.features_events, 2) + + by_id = {e["id"]: e for e in ledger.project(ledger.read(self.path))} + [live] = features.read(self.store) + self.assertEqual(live["schema"], 2) + self.assertEqual(live["include"], ["c3", "c2"]) + self.assertEqual(live["exclude"], ["d1"]) + self.assertEqual(live["keys"], {i: ledger.record_key(by_id[i]) for i in ("c3", "c2", "d1")}) + # c4 has no token in its headline, so its key is the one stored before. + self.assertEqual(live["keys"]["c3"], self.old_key(self.c4)) + # c3 mentions d2 in its headline. The rewrite to d1 must not move the key. + self.assertNotEqual(live["keys"]["c2"], self.old_key(self.c3)) + [archived] = features.read(self.archive) + self.assertEqual(archived["include"], ["c3"]) + self.assertEqual(archived["keys"], {"c3": self.old_key(self.c4)}) + + def test_a_crash_before_the_ledger_swap_is_repaired_by_a_rerun(self): + write_jsonl( + self.store, + [self.event("f1", "live", include=["c4"], keys={"c4": self.old_key(self.c4)})], + ) + original = self.path.read_bytes() + real = os.replace + ledger_path = self.path + + def fail(source, target): + if Path(target) == ledger_path: + raise OSError("disk full") + return real(source, target) + + with mock.patch.object(os, "replace", fail), self.assertRaises(OSError): + docket_migrate.migrate_in_place(self.path) + # Never a moment with no ledger: still the schema-2 file, backup beside it. + self.assertEqual(self.path.read_bytes(), original) + backup = Path(str(self.path) + ".schema2") + self.assertEqual(backup.read_bytes(), original) + [after_crash] = features.read(self.store) + self.assertEqual(after_crash["include"], ["c3"]) + + docket_migrate.migrate_in_place(self.path) + self.assertEqual(self.ledger_schema(), 3) + self.assertEqual(backup.read_bytes(), original) + # c4 -> c3 once. A second mapping would have sent it on to c2. + self.assertEqual(features.read(self.store), [after_crash]) + self.assertFalse(Path(str(self.path) + ".migrating").exists()) + + def test_a_features_line_that_is_not_an_object_is_a_migration_error(self): + self.store.write_text(json.dumps(self.event("f1", "live")) + "\n[1]\n", encoding="utf-8") + before = self.path.read_bytes() + with self.assertRaises(docket_migrate.MigrationError) as caught: + docket_migrate.migrate_in_place(self.path) + self.assertIn(str(self.store), str(caught.exception)) + self.assertIn("line 2", str(caught.exception)) + self.assertEqual(self.path.read_bytes(), before) + + def test_a_line_appended_after_the_read_stops_the_commit(self): + real = docket_migrate._commit + + def late_append(*args, **kwargs): + with self.path.open("a", encoding="utf-8") as handle: + handle.write(json.dumps(self.rec("claim", "c5", "Late", state="accepted")) + "\n") + return real(*args, **kwargs) + + with mock.patch.object(docket_migrate, "_commit", late_append): + with self.assertRaises(docket_migrate.MigrationError) as caught: + docket_migrate.migrate_in_place(self.path) + self.assertEqual( + str(caught.exception), "the ledger changed while migrating; run docket migrate again" + ) + self.assertEqual(self.ledger_schema(), 2) + self.assertFalse(Path(str(self.path) + ".schema2").exists()) + docket_migrate.migrate_in_place(self.path) + self.assertEqual(self.ledger_schema(), 3) + + def test_a_backup_that_differs_from_the_ledger_stops_the_command(self): + Path(str(self.path) + ".schema2").write_text("earlier\n") + before = self.path.read_bytes() + with self.assertRaises(docket_migrate.MigrationError): + docket_migrate.migrate_in_place(self.path) + self.assertEqual(self.path.read_bytes(), before) + + def test_the_backup_refusal_names_the_remedy(self): + Path(str(self.path) + ".schema2").write_text("earlier\n") + with self.assertRaises(docket_migrate.MigrationError) as caught: + docket_migrate.migrate_in_place(self.path) + self.assertIn("another branch's migration", str(caught.exception)) + self.assertIn("delete or move it and run docket migrate again", str(caught.exception)) + + def test_a_stale_temp_from_a_crashed_run_is_overwritten(self): + write_jsonl(self.store, [self.event("f1", "live", include=["c4"])]) + Path(str(self.path) + ".migrating").write_text("junk\n") + Path(str(self.store) + ".migrating").write_text("junk\n") + docket_migrate.migrate_in_place(self.path) + self.assertEqual(features.read(self.store)[0]["include"], ["c3"]) + self.assertEqual(self.ledger_schema(), 3) + + def test_a_features_file_already_at_schema_two_is_left_alone(self): + write_jsonl(self.store, [dict(self.event("f1", "live", include=["c4"]), schema=2)]) + before = self.store.read_bytes() + result = docket_migrate.migrate_in_place(self.path) + self.assertEqual(result.features_events, 0) + self.assertEqual(self.store.read_bytes(), before) + + def test_a_dry_run_counts_features_events_and_writes_nothing(self): + write_jsonl(self.store, [self.event("f1", "live", include=["c4"])]) + before = self.store.read_bytes() + result = docket_migrate.migrate_in_place(self.path, dry_run=True) + self.assertEqual(result.features_events, 1) + self.assertEqual(self.store.read_bytes(), before) + self.assertEqual(self.ledger_schema(), 2) + + def test_a_ledger_with_no_features_files_migrates(self): + result = docket_migrate.migrate_in_place(self.path) + self.assertEqual(result.features_events, 0) + self.assertFalse(self.store.exists()) + + def test_a_migrated_ledger_remaps_features_still_at_schema_one(self): + docket_migrate.migrate_in_place(self.path) + ledger_bytes = self.path.read_bytes() + write_jsonl( + self.store, + [self.event("f1", "late", include=["c4"], keys={"c4": self.old_key(self.c4)})], + ) + result = docket_migrate.migrate_in_place(self.path) + self.assertEqual(result.features_events, 1) + self.assertEqual(features.read(self.store)[0]["include"], ["c3"]) + self.assertEqual(self.path.read_bytes(), ledger_bytes) + + def test_an_old_id_held_by_two_records_is_not_mapped(self): + records = [ + {"id": "c2", "migrated_from": "c3"}, + {"id": "c3", "migrated_from": "c3"}, + {"id": "d1", "migrated_from": "d2"}, + {"id": "c1"}, + ] + self.assertEqual(docket_migrate._migrated_map(records), {"d2": "d1"}) + + +def s2(kind: str, ident: str, text: str, **fields) -> dict: + if kind == "decision": + fields.setdefault("choice", "chosen") + record = make_record( + kind, text, record_id=ident, ts="2026-09-12T00:00:00+00:00", author="t", **fields + ) + return {**record, "schema": 2} + + +def schema2_ledger() -> list[dict]: + # One global counter with gaps. Per kind: c1->c1, d2->d1, c3->c2, d4->d2, q5->q1. + return [ + s2("claim", "c1", "First claim"), + s2("decision", "d2", "Use the first claim", supports=[["c1"]]), + s2("claim", "c3", "Second claim"), + s2("decision", "d4", "Follows d2 and c3", supports=[["c3"]]), + s2("question", "q5", "What next"), + ] + + +def git(work: Path, *args: str) -> None: + base = ["git", "-c", "user.name=t", "-c", "user.email=t@example.com"] + subprocess.run([*base, *args], cwd=work, check=True, capture_output=True) + + +class ReadSourceTests(unittest.TestCase): + def test_typed_schema_2_lines_skip_the_old_id_check(self): + with tempfile.TemporaryDirectory() as work: + path = Path(work) / "ledger.jsonl" + write_jsonl(path, schema2_ledger()) + records = docket_migrate.read_source(path) + self.assertEqual([r["id"] for r in records], ["c1", "d2", "c3", "d4", "q5"]) + self.assertEqual(docket_migrate.detect_version(records), 2) + + +class RewriteTests(unittest.TestCase): + def setUp(self): + self._tmp = tempfile.TemporaryDirectory() + self.addCleanup(self._tmp.cleanup) + self.work = Path(self._tmp.name) + self.path = self.work / "ledger.jsonl" + write_jsonl(self.path, schema2_ledger()) + self.doc = self.work / "notes.md" + self.doc.write_text("d4 then d2, see c3 and q5. Keep c9 and d2.1.\n") + git(self.work, "init", "-q") + git(self.work, "add", "-A") + git(self.work, "commit", "-q", "-m", "fixture") + + def test_rewrite_text_is_one_lookup_per_token(self): + mapping = {"d4": "d2", "d2": "d1"} + self.assertEqual( + docket_migrate.rewrite_text("d4 then d2; d4x, d2.1, d20", mapping), + ("d2 then d1; d4x, d1.1, d20", 3), + ) + + def test_an_identity_mapping_counts_nothing(self): + self.assertEqual(docket_migrate.rewrite_text("c1 and c1", {"c1": "c1"}), ("c1 and c1", 0)) + + def test_rewrite_rewrites_named_files_in_the_migration_run(self): + other = self.work / "plain.md" + other.write_text("no ids here\n") + git(self.work, "add", "-A") + git(self.work, "commit", "-q", "-m", "plain") + result = docket_migrate.migrate_in_place(self.path, rewrite=[self.doc, other]) + self.assertEqual(self.doc.read_text(), "d2 then d1, see c2 and q1. Keep c9 and d1.1.\n") + self.assertEqual(other.read_text(), "no ids here\n") + self.assertEqual(result.rewritten, [str(self.doc)]) + self.assertEqual(result.rewrite_counts, {str(self.doc): 5}) + self.assertTrue(Path(str(self.path) + ".schema2").exists()) + + def test_dry_run_plans_the_rewrite_and_writes_nothing(self): + before = (self.path.read_bytes(), self.doc.read_bytes()) + result = docket_migrate.migrate_in_place(self.path, dry_run=True, rewrite=[self.doc]) + self.assertEqual(result.rewritten, [str(self.doc)]) + self.assertEqual(result.rewrite_counts, {str(self.doc): 5}) + self.assertEqual((self.path.read_bytes(), self.doc.read_bytes()), before) + + def test_rewrite_is_refused_on_a_ledger_already_at_schema_3(self): + docket_migrate.migrate_in_place(self.path) + migrated = self.path.read_bytes() + with self.assertRaisesRegex(docket_migrate.MigrationError, "already at schema 3"): + docket_migrate.migrate_in_place(self.path, rewrite=[self.doc]) + with self.assertRaisesRegex(docket_migrate.MigrationError, "already at schema 3"): + docket_migrate.migrate_in_place(self.path, dry_run=True, rewrite=[self.doc]) + self.assertEqual(self.path.read_bytes(), migrated) + self.assertEqual(self.doc.read_text(), "d4 then d2, see c3 and q5. Keep c9 and d2.1.\n") + + def test_an_untracked_file_is_refused_before_anything_is_written(self): + fresh = self.work / "fresh.md" + fresh.write_text("d4\n") + before = self.path.read_bytes() + with self.assertRaisesRegex(docket_migrate.MigrationError, "not tracked"): + docket_migrate.migrate_in_place(self.path, rewrite=[self.doc, fresh]) + self.assertEqual(self.path.read_bytes(), before) + self.assertFalse(Path(str(self.path) + ".schema2").exists()) + self.assertEqual(fresh.read_text(), "d4\n") + + def test_a_file_with_uncommitted_changes_is_refused(self): + self.doc.write_text("d4 edited\n") + before = self.path.read_bytes() + with self.assertRaisesRegex(docket_migrate.MigrationError, "uncommitted"): + docket_migrate.migrate_in_place(self.path, rewrite=[self.doc]) + self.assertEqual(self.path.read_bytes(), before) + self.assertEqual(self.doc.read_text(), "d4 edited\n") + + def test_a_file_outside_a_git_repository_is_refused(self): + with tempfile.TemporaryDirectory() as elsewhere: + loose = Path(elsewhere) / "loose.md" + loose.write_text("d4\n") + with self.assertRaisesRegex(docket_migrate.MigrationError, "not tracked"): + docket_migrate.migrate_in_place(self.path, rewrite=[loose]) + + def test_a_missing_directory_or_ledger_target_is_refused(self): + before = self.path.read_bytes() + for bad in (self.work / "missing.md", self.work, self.path): + with self.assertRaises(docket_migrate.MigrationError, msg=str(bad)): + docket_migrate.migrate_in_place(self.path, rewrite=[self.doc, bad]) + self.assertEqual(self.path.read_bytes(), before) + self.assertFalse(Path(str(self.path) + ".schema2").exists()) + + def test_a_schema_1_ledger_rewrites_files_through_schema_1_ids(self): + # d3 is an open question: schema 1 d3 becomes schema 2 q3, then q1. + legacy = legacy_ledger() + [dict(legacy_ledger()[0], id="d3", state="open")] + write_jsonl(self.path, legacy) + self.doc.write_text("see d3 and d2, not q3\n") + git(self.work, "add", "-A") + git(self.work, "commit", "-q", "-m", "legacy") + result = docket_migrate.migrate_in_place(self.path, rewrite=[self.doc]) + self.assertEqual(self.doc.read_text(), "see q1 and d2, not q3\n") + self.assertEqual(result.rewrite_counts, {str(self.doc): 1}) + + def test_naming_a_file_twice_is_refused(self): + with self.assertRaisesRegex(docket_migrate.MigrationError, "twice"): + docket_migrate.migrate_in_place(self.path, rewrite=[self.doc, self.doc]) + + def test_map_is_refused_on_a_schema_2_ledger(self): + mapping = self.work / "map.json" + mapping.write_text("{}") + before = self.path.read_bytes() + with self.assertRaisesRegex(docket_migrate.MigrationError, "schema 1"): + docket_migrate.migrate_in_place(self.path, mapping_path=mapping) + self.assertEqual(self.path.read_bytes(), before) + + if __name__ == "__main__": unittest.main() diff --git a/tests/test_rebase.py b/tests/test_rebase.py index 9bdd7b2..f0f945c 100644 --- a/tests/test_rebase.py +++ b/tests/test_rebase.py @@ -1,10 +1,27 @@ +import copy +import io import json +import os +import subprocess import tempfile import unittest +from contextlib import redirect_stderr, redirect_stdout from pathlib import Path +from docket import corrections, migrate, reviews +from docket.cli import main from docket.ledger import make_record, read -from docket.rebase import RebaseError, common_prefix, merge, renumber +from docket.rebase import ( + PROSE_FIELDS, + ProseChange, + RebaseError, + _key, + common_prefix, + merge, + renumber, + renumber_per_kind, + rewrite_prose, +) def claim(ident, text, **kwargs): @@ -12,7 +29,8 @@ def claim(ident, text, **kwargs): def decision(ident, text, **kwargs): - return make_record("decision", text, choice="yes", author="t", record_id=ident, **kwargs) + kwargs.setdefault("choice", "yes") + return make_record("decision", text, author="t", record_id=ident, **kwargs) class RebaseTests(unittest.TestCase): @@ -30,8 +48,8 @@ def test_renumber_continues_the_sequence_and_rewrites_inner_references(self): decision("d3", "Their decision", supports=[["c2"], ["c1"]], depends_on=["c2"]), ] tail, mapping = renumber(mine, theirs) - self.assertEqual(mapping, {"c2": "c3", "d3": "d4"}) - self.assertEqual([row["id"] for row in tail], ["c3", "d4"]) + self.assertEqual(mapping, {"c2": "c3", "d3": "d1"}) + self.assertEqual([row["id"] for row in tail], ["c3", "d1"]) # The inner reference follows the rename; the prefix reference does not. self.assertEqual(tail[1]["supports"], [["c3"], ["c1"]]) self.assertEqual(tail[1]["depends_on"], ["c3"]) @@ -114,7 +132,7 @@ def test_a_record_matched_under_a_new_id_carries_that_id_into_later_references(s merged_main = main + renumber(main, branch)[0] branch_later = branch + [decision("d3", "Uses it", supports=[["c2"]])] tail, mapping = renumber(merged_main, branch_later) - self.assertEqual(mapping, {"d3": "d4"}) + self.assertEqual(mapping, {"d3": "d1"}) self.assertEqual(tail[0]["supports"], [["c3"]]) def test_two_identical_looking_reviews_of_different_records_stay_distinct(self): @@ -174,5 +192,467 @@ def test_a_matched_supersession_is_not_refused(self): self.assertEqual((tail, mapping), ([], {})) +PINNED = "2026-10-03T00:00:00+00:00" + + +def question(ident, text, **kwargs): + return make_record("question", text, author="t", record_id=ident, **kwargs) + + +def mixed_ledger(): + """Schema-2 ids from one global counter, one line of every kind, ts pinned.""" + + rows = [ + claim("c1", "Base premise"), + decision("d2", "Use the log", supports=[["c1"]]), + claim("c3", "Log holds d2 and c1"), + question("q4", "Where does it live"), + decision( + "d5", + "Move it", + supports=[["c3", "c1"], ["d2"]], + depends_on=["d2"], + answers=["q4"], + supersedes=["d2"], + ), + claim("c6", "Later premise"), + ] + fix = corrections.make("c3", {"text": "Log holds d5."}, reason="d5 changed", author="t") + fix["id"] = "c3.1" + rows.append(fix) + review = reviews.make("d5", note="Rechecked d5 against c3", author="t") + review["id"] = "d5.r1" + review["grounds"] = {"c3": "c3", "d2": "d5"} + rows.append(review) + for row in rows: + row["ts"] = PINNED + return rows + + +class RewriteProseTests(unittest.TestCase): + def test_one_lookup_per_token_so_shifted_ids_do_not_chain(self): + mapping = {"c3": "c2", "c2": "c1"} + self.assertEqual( + rewrite_prose("c3 then c2, not c3 again", mapping), "c2 then c1, not c2 again" + ) + + def test_a_token_naming_no_mapped_id_is_left_alone(self): + mapping = {"c2": "c1"} + self.assertEqual( + rewrite_prose("c99, q7, c2 and abc2 and c02", mapping), "c99, q7, c1 and abc2 and c02" + ) + + def test_lists_are_rewritten_element_wise_and_other_values_pass_through(self): + mapping = {"d3": "d1"} + self.assertEqual(rewrite_prose(["keep d3", "drop it"], mapping), ["keep d1", "drop it"]) + self.assertEqual(rewrite_prose(["d3", 7, None], mapping), ["d1", 7, None]) + self.assertEqual(rewrite_prose(5, mapping), 5) + self.assertIsNone(rewrite_prose(None, mapping)) + + def test_via_resolves_a_token_before_the_mapping_does(self): + # A schema-1 id in a legacy line's prose names the record whose + # legacy.source_id it is, not the schema-2 record that shares its number. + mapping = {"c4": "c2", "d4": "d1"} + via = {"d4": "c4"} + self.assertEqual(rewrite_prose("was d4, near c4", mapping, via), "was c2, near c2") + self.assertEqual(rewrite_prose("was d4, near c4", mapping), "was d1, near c2") + + def test_prose_fields_are_the_six_wording_keys(self): + self.assertEqual( + PROSE_FIELDS, + ("text", "choice", "alternatives", "rationale", "cost_if_wrong", "revisit"), + ) + + +class RenumberPerKindTests(unittest.TestCase): + def test_each_kind_counts_from_one_in_file_order(self): + rows = mixed_ledger() + untouched = copy.deepcopy(rows) + out, mapping, _ = renumber_per_kind(rows) + self.assertEqual(rows, untouched) + self.assertEqual( + [row["id"] for row in out], + ["c1", "d1", "c2", "q1", "d2", "c3", "c2.1", "d2.r1"], + ) + self.assertEqual( + mapping, + {"c1": "c1", "d2": "d1", "c3": "c2", "q4": "q1", "d5": "d2", "c6": "c3"}, + ) + + def test_corrections_and_reviews_keep_their_suffix_and_follow_their_target(self): + out, _, _ = renumber_per_kind(mixed_ledger()) + fix, review = out[6], out[7] + self.assertEqual((fix["id"], fix["corrects"]), ("c2.1", "c2")) + self.assertEqual((review["id"], review["reviews"]), ("d2.r1", "d2")) + self.assertEqual(review["grounds"], {"c2": "c2", "d1": "d2"}) + + def test_relations_are_rewritten(self): + out, _, _ = renumber_per_kind(mixed_ledger()) + self.assertEqual(out[1]["supports"], [["c1"]]) + moved = out[4] + self.assertEqual(moved["supports"], [["c2", "c1"], ["d1"]]) + self.assertEqual(moved["depends_on"], ["d1"]) + self.assertEqual(moved["answers"], ["q1"]) + self.assertEqual(moved["supersedes"], ["d1"]) + + def test_prose_mentions_follow_the_mapping_without_chaining(self): + out, _, _ = renumber_per_kind(mixed_ledger()) + self.assertEqual(out[2]["text"], "Log holds d1 and c1") + # Old d5 is now d2, and old d2 is now d1: a chained rewrite would say d1. + self.assertEqual(out[6]["fields"]["text"], "Log holds d2.") + self.assertEqual(out[6]["reason"], "d2 changed") + self.assertEqual(out[7]["note"], "Rechecked d2 against c2") + + def test_every_prose_field_is_rewritten_and_an_unmapped_token_stays(self): + rows = [ + decision("d1", "Base"), + claim("c2", "Premise"), + decision( + "d3", + "Rests on c2 and d1", + choice="Use c2, not c99", + alternatives=["keep d1", "drop c2"], + rationale="Because c2.", + cost_if_wrong="Redo d1 and c2.", + revisit="When c2 changes.", + ), + ] + fix = corrections.make( + "d3", + { + "text": "Now rests on c2.", + "alternatives": ["keep d1", "drop c2"], + "rationale": "c2 again.", + "scope": ["c2"], + }, + author="t", + ) + fix["id"] = "d3.1" + out, _, _ = renumber_per_kind(rows + [fix]) + row = out[2] + self.assertEqual(row["id"], "d2") + self.assertEqual(row["text"], "Rests on c1 and d1") + self.assertEqual(row["choice"], "Use c1, not c99") + self.assertEqual(row["alternatives"], ["keep d1", "drop c1"]) + self.assertEqual(row["rationale"], "Because c1.") + self.assertEqual(row["cost_if_wrong"], "Redo d1 and c1.") + self.assertEqual(row["revisit"], "When c1 changes.") + fields = out[3]["fields"] + self.assertEqual(fields["text"], "Now rests on c1.") + self.assertEqual(fields["alternatives"], ["keep d1", "drop c1"]) + self.assertEqual(fields["rationale"], "c1 again.") + self.assertEqual(fields["scope"], ["c2"]) + + def test_a_line_that_mentions_its_own_id_gets_the_new_one(self): + out, _, _ = renumber_per_kind([decision("d1", "Base"), claim("c2", "Calls itself c2")]) + self.assertEqual(out[1]["text"], "Calls itself c1") + + def test_legacy_scope_evidence_and_schema_are_not_touched(self): + rows = [decision("d1", "Base"), claim("c2", "Premise", scope=["c2"])] + rows[1]["legacy"] = {"mapped_supports": ["c2", "d1"]} + rows[1]["evidence"] = [{"kind": "note", "ref": "see c2"}] + out, _, _ = renumber_per_kind(rows) + row = out[1] + self.assertEqual(row["id"], "c1") + self.assertEqual(row["scope"], ["c2"]) + self.assertEqual(row["legacy"], {"mapped_supports": ["c2", "d1"]}) + self.assertEqual(row["evidence"], [{"kind": "note", "ref": "see c2"}]) + self.assertEqual(row["schema"], rows[1]["schema"]) + + def test_a_legacy_line_resolves_prose_through_its_source_id_first(self): + # Schema-1 c4 became schema-2 d4; its prose still says "c4" for itself. + # Without source_id, "c4" would map to the schema-2 claim c4. + first = claim("c1", "Root") + second = claim("c2", "Other") + third = decision("d3", "Legacy decision") + third["legacy"] = {"source_id": "c3"} + fourth = claim("c4", "A claim") + fourth["text"] = "Not the legacy c3, only c4" + fourth["legacy"] = {"source_id": "d4"} + fifth = decision("d5", "Mentions c3 as written") + out, _, _ = renumber_per_kind([first, second, third, fourth, fifth]) + # c3 in c4's prose is the legacy source of d3 -> d1; c4 is the schema-2 claim -> c3. + self.assertEqual(out[3]["text"], "Not the legacy d1, only c3") + # A line without legacy resolves through the mapping alone, and c3 is unmapped. + self.assertEqual(out[4]["text"], "Mentions c3 as written") + + def test_migrated_from_is_set_on_claims_decisions_and_questions_only(self): + rows = mixed_ledger() + out, _, _ = renumber_per_kind(rows) + for old, new in zip(rows, out): + if old["kind"] in ("claim", "decision", "question"): + self.assertEqual(new["migrated_from"], old["id"]) + else: + self.assertNotIn("migrated_from", new) + + def test_renumbering_a_prefix_equals_the_prefix_of_renumbering_the_whole(self): + rows = mixed_ledger() + whole = renumber_per_kind(rows)[0] + for k in range(len(rows) + 1): + with self.subTest(k=k): + self.assertEqual(renumber_per_kind(rows[:k])[0], whole[:k]) + + def test_a_duplicate_old_id_is_refused(self): + with self.assertRaises(RebaseError) as caught: + renumber_per_kind([claim("c1", "One"), claim("c1", "Two")]) + self.assertIn("c1", str(caught.exception)) + + def test_a_citation_of_an_id_not_yet_defined_is_refused(self): + for rows in ( + [decision("d1", "Early", depends_on=["c2"]), claim("c2", "Late")], + [claim("c1", "Only"), decision("d2", "Cites", supports=[["c9"]])], + ): + with self.subTest(rows=[r["id"] for r in rows]): + with self.assertRaises(RebaseError): + renumber_per_kind(rows) + + def test_a_correction_or_review_of_a_missing_target_is_refused(self): + fix = corrections.make("c9", {"text": "x"}, author="t") + fix["id"] = "c9.1" + with self.assertRaises(RebaseError): + renumber_per_kind([claim("c1", "Only"), fix]) + review = reviews.make("c9", author="t") + review["id"] = "c9.r1" + review["grounds"] = {"c1": "c1"} + with self.assertRaises(RebaseError): + renumber_per_kind([claim("c1", "Only"), review]) + + +def raw(kind, ident, text, **extra): + return {"schema": 2, "kind": kind, "id": ident, "text": text, **extra} + + +class RenumberGoldenTests(unittest.TestCase): + """Pins renumber_per_kind byte for byte. + + Two branches migrated by docket versions whose rules differ share no + prefix, so changing this output is a format change that needs a new schema. + """ + + OLD = [ + raw("claim", "c1", "Root premise"), + raw("decision", "d2", "Adopt the log", supports=[["c1"]]), + raw("claim", "c3", "Was d3; see c1 and d2", legacy={"source_id": "d3"}), + raw("question", "q4", "Which of c1 or d2"), + raw( + "decision", + "d5", + "Settles q4", + alternatives=["keep d2", "drop c3"], + rationale="Unlike c9", + depends_on=["d2"], + answers=["q4"], + ), + { + "schema": 2, + "kind": "correction", + "id": "d5.1", + "corrects": "d5", + "fields": {"text": "Settles q4 for d2", "scope": ["c3"]}, + "reason": "see c3", + }, + { + "schema": 2, + "kind": "review", + "id": "d5.r1", + "reviews": "d5", + "grounds": {"c3": "c3"}, + "note": "ok per q4", + }, + ] + + NEW = [ + raw("claim", "c1", "Root premise", migrated_from="c1"), + raw("decision", "d1", "Adopt the log", supports=[["c1"]], migrated_from="d2"), + raw( + "claim", + "c2", + "Was c2; see c1 and d1", + legacy={"source_id": "d3"}, + migrated_from="c3", + ), + raw("question", "q1", "Which of c1 or d1", migrated_from="q4"), + raw( + "decision", + "d2", + "Settles q1", + alternatives=["keep d1", "drop c2"], + rationale="Unlike c9", + depends_on=["d1"], + answers=["q1"], + migrated_from="d5", + ), + { + "schema": 2, + "kind": "correction", + "id": "d2.1", + "corrects": "d2", + "fields": {"text": "Settles q1 for d1", "scope": ["c3"]}, + "reason": "see c2", + }, + { + "schema": 2, + "kind": "review", + "id": "d2.r1", + "reviews": "d2", + "grounds": {"c2": "c2"}, + "note": "ok per q1", + }, + ] + + def test_output_mapping_and_report_are_fixed(self): + out, mapping, changes = renumber_per_kind(copy.deepcopy(self.OLD)) + self.assertEqual(out, self.NEW) + self.assertEqual(mapping, {"c1": "c1", "d2": "d1", "c3": "c2", "q4": "q1", "d5": "d2"}) + self.assertEqual( + changes, + [ + ProseChange("c3", "text", "Was d3; see c1 and d2", "Was c2; see c1 and d1"), + ProseChange("q4", "text", "Which of c1 or d2", "Which of c1 or d1"), + ProseChange("d5", "text", "Settles q4", "Settles q1"), + ProseChange("d5", "alternatives", "keep d2", "keep d1"), + ProseChange("d5", "alternatives", "drop c3", "drop c2"), + ProseChange("d5", "rationale", "c9", None), + ProseChange("d5.1", "text", "Settles q4 for d2", "Settles q1 for d1"), + ProseChange("d5.1", "reason", "see c3", "see c2"), + ProseChange("d5.r1", "note", "ok per q4", "ok per q1"), + ], + ) + + +class MatchKeyTests(unittest.TestCase): + def test_the_key_ignores_id_migrated_from_and_id_tokens_in_prose(self): + left = decision("d3", "Uses c2", supports=[["c2"]], rationale="see d1") + right = dict(left, id="d1", migrated_from="d3", text="Uses c1", rationale="see d9") + self.assertEqual(_key(left), _key(right)) + + def test_the_key_still_tells_apart_relations_and_other_wording(self): + left = decision("d3", "Uses c2", supports=[["c2"]]) + self.assertNotEqual(_key(left), _key(dict(left, supports=[["c1"]]))) + self.assertNotEqual(_key(left), _key(dict(left, text="Uses c2 now"))) + + def test_correction_fields_and_reason_and_review_note_are_masked(self): + one = corrections.make("c1", {"text": "see c2"}, reason="d3 was wrong", ts=PINNED) + two = corrections.make("c1", {"text": "see c7"}, reason="d9 was wrong", ts=PINNED) + self.assertEqual(_key(one), _key(two)) + three = reviews.make("c1", note="c2 holds", ts=PINNED) + four = reviews.make("c1", note="c8 holds", ts=PINNED) + self.assertEqual(_key(three), _key(four)) + five = corrections.make("c1", {"text": "other"}, reason="d3 was wrong", ts=PINNED) + self.assertNotEqual(_key(one), _key(five)) + + +class MergeProseTests(unittest.TestCase): + def branch_pair(self): + shared = [claim("c1", "Shared premise")] + branch = shared + [ + claim("c2", "Branch claim"), + decision("d3", "Uses c2", supports=[["c2"]]), + ] + main = shared + [claim("c2", "Main claim")] + for row in branch[1:] + main[1:]: + row["ts"] = PINNED + return shared, branch, main + + def test_a_merge_rewrites_prose_in_the_appended_tail(self): + _, branch, main = self.branch_pair() + tail, mapping = renumber(main, branch) + self.assertEqual(mapping["c2"], "c3") + self.assertEqual(tail[1]["text"], "Uses c3") + self.assertEqual(tail[1]["supports"], [["c3"]]) + + def test_a_second_merge_of_the_same_branch_appends_nothing(self): + _, branch, main = self.branch_pair() + merged = main + renumber(main, branch)[0] + self.assertEqual(renumber(merged, branch), ([], {})) + + def test_each_side_migrating_after_a_pre_migration_merge_still_merges_cleanly(self): + base = [claim("c1", "Shared")] + main = base + [decision("d2", "Main decision", supports=[["c1"]])] + # The branch merged main under the old code: main's d2 landed as d3. + branch = base + [ + claim("c2", "Branch claim"), + dict(main[1], id="d3"), + decision("d4", "Builds on d3", depends_on=["d3"]), + ] + for row in main[1:] + branch[1:]: + row["ts"] = PINNED + base_m = renumber_per_kind(base)[0] + main_m = renumber_per_kind(main)[0] + branch_m = renumber_per_kind(branch)[0] + # Same decision, migrated_from d2 on main and d3 on the branch. + self.assertNotEqual(main_m[1]["migrated_from"], branch_m[2]["migrated_from"]) + tail, _ = merge(base_m, main_m, branch_m) + self.assertEqual([r["text"] for r in tail], ["Branch claim", "Builds on d1"]) + self.assertEqual(tail[1]["depends_on"], ["d1"]) + self.assertEqual(merge(base_m, main_m + tail, branch_m), ([], {})) + + +def v2(records): + return [dict(r, schema=2) for r in records] + + +def upgraded(records): + return migrate.renumber_step(v2(records))[0] + + +def write_lines(path, records): + path.write_text("".join(json.dumps(r) + "\n" for r in records), encoding="utf-8") + + +class RebaseAcrossMigrationTests(unittest.TestCase): + def setUp(self): + tmp = tempfile.TemporaryDirectory() + self.addCleanup(tmp.cleanup) + self.root = Path(tmp.name) + subprocess.run( + ["git", "-C", str(self.root), "init", "-b", "main"], check=True, capture_output=True + ) + (self.root / ".docket").mkdir() + self.ledger = self.root / ".docket" / "ledger.jsonl" + self.other = self.root / "other.jsonl" + cwd = Path.cwd() + os.chdir(self.root) + self.addCleanup(os.chdir, cwd) + self.shared = [ + claim("c1", "Shared premise"), + decision("d2", "Cache layer sits behind reads", supports=[["c1"]]), + ] + + def run_cli(self, *argv): + out, err = io.StringIO(), io.StringIO() + with redirect_stdout(out), redirect_stderr(err): + code = main(list(argv)) + return code, out.getvalue(), err.getvalue() + + def test_two_ledgers_migrated_separately_rebase_cleanly(self): + write_lines(self.ledger, upgraded(self.shared + [claim("c3", "Ours only")])) + write_lines(self.other, upgraded(self.shared + [claim("c3", "Their premise")])) + code, _, _ = self.run_cli("rebase", str(self.other)) + self.assertEqual(code, 0) + merged = read(self.ledger) + self.assertEqual([r["id"] for r in merged], ["c1", "d1", "c2", "c3"]) + self.assertEqual(merged[3]["text"], "Their premise") + + def test_a_schema_2_other_is_refused_and_the_ledger_left_alone(self): + write_lines(self.ledger, upgraded(self.shared)) + write_lines(self.other, v2(self.shared + [claim("c3", "Their premise")])) + before = self.ledger.read_bytes() + code, _, err = self.run_cli("rebase", str(self.other)) + self.assertEqual(code, 1) + self.assertIn("docket migrate", err) + self.assertEqual(self.ledger.read_bytes(), before) + + def test_a_schema_2_working_ledger_is_refused_and_left_alone(self): + write_lines(self.ledger, v2(self.shared)) + write_lines(self.other, upgraded(self.shared)) + before = self.ledger.read_bytes() + code, _, err = self.run_cli("rebase", str(self.other)) + self.assertEqual(code, 1) + self.assertIn("docket migrate", err) + self.assertNotIn("docket: docket:", err) + self.assertEqual(self.ledger.read_bytes(), before) + + if __name__ == "__main__": unittest.main() diff --git a/tests/test_review_cli.py b/tests/test_review_cli.py index ec47792..38bb7b1 100644 --- a/tests/test_review_cli.py +++ b/tests/test_review_cli.py @@ -65,7 +65,7 @@ def test_a_missing_reason_hints_and_flags(self): def test_a_superseding_question_gets_no_hint(self): self.assertEqual(run(self.cwd, "question", "Is it durable?").returncode, 0) - out = run(self.cwd, "question", "Is it durable on ext4?", "--supersedes", "q3") + out = run(self.cwd, "question", "Is it durable on ext4?", "--supersedes", "q1") self.assertEqual(out.returncode, 0, out.stderr) self.assertNotIn("recorded as revise", out.stderr) diff --git a/tests/test_reviews.py b/tests/test_reviews.py index 8c34e5c..a1bde9e 100644 --- a/tests/test_reviews.py +++ b/tests/test_reviews.py @@ -17,7 +17,7 @@ def claim(ident, **kwargs): def review(ident, target, grounds, note=""): return { - "schema": 2, + "schema": ledger.SCHEMA, "kind": "review", "id": ident, "reviews": target, @@ -66,7 +66,7 @@ def test_unknown_fields_are_refused(self): def test_a_review_does_not_consume_a_record_number(self): entries = ledger.validate_entries([*BASE, review("c2.r1", "c2", {"c1": "c3"})]) - self.assertEqual(ledger.next_id(entries), "4") + self.assertEqual(ledger.next_id(entries, "claim"), "4") class ReviewFoldTests(unittest.TestCase): diff --git a/tests/test_supersede_reason.py b/tests/test_supersede_reason.py index 6d67205..022fca9 100644 --- a/tests/test_supersede_reason.py +++ b/tests/test_supersede_reason.py @@ -15,7 +15,7 @@ def claim(ident, **kwargs): def correction(ident, target, fields): return { - "schema": 2, + "schema": ledger.SCHEMA, "kind": "correction", "id": ident, "corrects": target, diff --git a/tests/test_support.py b/tests/test_support.py index 88eb49c..320cf55 100644 --- a/tests/test_support.py +++ b/tests/test_support.py @@ -23,7 +23,7 @@ def decision(ident, **kwargs): def review(ident, target, grounds): return { - "schema": 2, + "schema": ledger.SCHEMA, "kind": "review", "id": ident, "reviews": target, diff --git a/tests/test_support_smoke.py b/tests/test_support_smoke.py index 2f91f28..c4de399 100644 --- a/tests/test_support_smoke.py +++ b/tests/test_support_smoke.py @@ -14,7 +14,10 @@ class RepositoryLedgerTests(unittest.TestCase): def test_no_current_record_loses_its_grounds(self): # This ledger records no rejection, revocation or reversal, so nothing # is lost to one; cycles built by forward resolution are flagged, not lost. - projected = ledger.project(ledger.read(LEDGER), validated=True) + try: + projected = ledger.project(ledger.read(LEDGER), validated=True) + except ledger.SchemaTooOld: + self.skipTest("this checkout's ledger is not migrated yet") lost = {e["id"]: e["lost_grounds"] for e in projected if support.surfaced(e, "unsupported")} self.assertEqual(lost, {}) diff --git a/tests/test_web.py b/tests/test_web.py index 54e943c..7a4cf28 100644 --- a/tests/test_web.py +++ b/tests/test_web.py @@ -254,12 +254,14 @@ def test_a_record_with_no_relation_is_drawn(self): alone = {"id": "d7", "kind": "decision", "text": "t"} with ( + mock.patch("docket.env.read", return_value=[]), mock.patch("docket.cli.web.selection", return_value=([alone], [alone], False)), mock.patch("docket.ledger.project", return_value=[alone]), ): dot = json.loads(web._payload(argparse.Namespace(), {}))["dot"] self.assertIn('"d7" [', dot) with ( + mock.patch("docket.env.read", return_value=[]), mock.patch("docket.cli.web.selection", return_value=([alone], [alone], False)), mock.patch("docket.ledger.project", return_value=[alone]), ): diff --git a/tests/test_where.py b/tests/test_where.py index 918b80b..174ee51 100644 --- a/tests/test_where.py +++ b/tests/test_where.py @@ -40,6 +40,42 @@ def hit(query, **fields): return where.parse(query).matches(entry(**fields)) +class WasTermTests(unittest.TestCase): + def test_was_matches_the_old_id_exactly(self): + self.assertTrue(hit("was:c3", migrated_from="c3")) + self.assertFalse(hit("was:c3", migrated_from="c30")) + self.assertFalse(hit("was:c3", migrated_from="c13")) + self.assertFalse(hit("was:c3")) + + def test_was_also_matches_the_schema_1_source_id(self): + # Schema 1 ids map number for number to schema 2 ids with a possibly + # different letter, so c4 may carry legacy.source_id d4. + self.assertTrue(hit("was:d4", legacy={"source_id": "d4"})) + self.assertTrue(hit("was:d4", legacy={"source_id": "d4"}, migrated_from="c4")) + self.assertFalse(hit("was:d4", legacy={"source_id": "d40"})) + self.assertFalse(hit("was:d4", legacy="not a dict")) + + def test_was_ignores_case(self): + self.assertTrue(hit("was:C3", migrated_from="c3")) + + def test_two_records_sharing_one_old_id_both_match(self): + first = entry(id="c1", migrated_from="c3", branch="a") + second = entry(id="c2", migrated_from="c3", branch="b") + both = where.parse("was:c3") + self.assertTrue(both.matches(first) and both.matches(second)) + narrowed = where.parse("was:c3 branch:b") + self.assertEqual([e["id"] for e in (first, second) if narrowed.matches(e)], ["c2"]) + + def test_repeated_was_terms_or_and_a_dash_negates(self): + self.assertTrue(hit("was:c3 was:d4", migrated_from="d4")) + self.assertFalse(hit("-was:c3", migrated_from="c3")) + self.assertTrue(hit("-was:c3", migrated_from="d4")) + + def test_was_needs_a_value(self): + with self.assertRaisesRegex(where.WhereError, "needs a value"): + where.parse("was:") + + class TokenizerTests(unittest.TestCase): def test_cases_shared_with_the_viewer(self): for query, expected in SHARED_CASES: @@ -243,6 +279,8 @@ def test_wants_retired(self): self.assertTrue(where.parse("kind:decision is:retired").wants_retired) self.assertFalse(where.parse("-is:retired").wants_retired) self.assertFalse(where.parse("retired").wants_retired) + self.assertTrue(where.parse("was:d98").wants_retired) + self.assertFalse(where.parse("-was:d98").wants_retired) self.assertFalse(where.parse("").wants_retired) def test_has_fields(self):