Skip to content

Tags: infinri/Writ

Tags

v1.7.0

Toggle v1.7.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Merge pull request #8 from infinri/fix/bench-budget-scale

Size the cold-start bench scale to the slowest runner observed

v1.6.0

Toggle v1.6.0's commit message
Skip the host-settings assertion when ~/.claude/settings.json is absent

The test asserts a stale Bash permission was removed from the HOST's
installed global config; CI runners never had one. Its two guarded
siblings (pol5b4 global-settings check, the installed-systemd-unit
check) already skip this way; this was the only bare host-state read
left in the suite.

v1.5.0

Toggle v1.5.0's commit message
v1.5.0: Unify bible ingestion under writ import-markdown

writ import-markdown becomes the single canonical entry point for ingesting
every node type under bible/ (Rule + Skill + Playbook + AntiPattern + Phase +
Technique + Rationalization + SubagentRole + WorkedExample + ForbiddenResponse).
Pre-1.5.0 the CLI handled only Rule nodes; methodology required shelling out
to scripts/migrate.py --methodology-dir. The duplicate parse/validate/write
loop collapses into one library module that both call sites consume
(DRY-DUP-002). Per-node-type dispatch becomes a registry lookup (SOLID-OCP-002),
and validation failures surface as typed IngestError instead of raw Pydantic
tracebacks (API-ERROR-002).

Added:
- writ/graph/methodology_ingest.py library (ingest_path, ingest_edges,
  INGESTER_REGISTRY, KNOWN_NODE_TYPES, IngestReport, IngestError)
- --only TYPE[,...] and --dry-run flags on writ import-markdown
- tests/_writ_cmd.py shared CLI resolver (.venv/bin/writ -> python -m
  writ.cli fallback) consumed by every test that subprocess-invokes the CLI
- tests/test_import_markdown_unified.py (27 tests, 7 classes)
- tests/test_methodology_ingest.py (14 unit tests)

Changed:
- writ/cli.py import_markdown rewritten as a thin Typer wrapper over the
  library. writ migrate now in-process; exit-code contract preserved.
- scripts/migrate.py reduced from 257 lines to a ~71-line shim that
  preserves --bible-dir / --methodology-dir / --dry-run argparse surface
  and re-exports run_migration + run_methodology_migration for the
  test_phase6bcd_verification import contract.
- tests/conftest.py::pytest_sessionfinish, tests/test_retrieval.py,
  tests/test_post_suite_neo4j_restoration.py, tests/test_graph_proximity.py,
  tests/test_embeddings.py shell out to writ import-markdown bible/ (was:
  scripts/migrate.py --methodology-dir bible/methodology).
- tests/test_ingest.py::TestMigrationIntegration uses MERGE-aware unique
  rule_id count (the 286-vs-276 disparity was 10 enforcement-rule IDs that
  legitimately live in both bible/<topic>/rules.md and
  bible/methodology/<topic>/rules.md).
- .github/actions/setup-writ/action.yml + .github/workflows/pr.yml call
  writ import-markdown bible/. CI gains methodology coverage.
- README.md, bible/methodology/PBK-AUTHOR-001.md,
  docs/extraction/{04,08,09}-*.md, benchmarks/bench_targets.py,
  scripts/instrument-cold-start.py, .claude/CODEBASE.md, templates/CLAUDE.md
  -- migrate.py user-facing references repointed at writ import-markdown.
- Version 1.3.0 -> 1.5.0 across pyproject.toml, .claude-plugin/plugin.json,
  .claude-plugin/marketplace.json (both metadata.version and
  plugins[0].version). tests/test_version_consistency.py EXPECTED_VERSION
  bumped accordingly.
- CHANGELOG.md prepends a [1.5.0] entry that documents both the absorption
  work (commit 0882dd6) and this commit's unify work as a single release.

Fixed:
- writ import-markdown no longer auto-exports the full graph when invoked
  against a subdirectory. Pre-fix, running writ import-markdown
  bible/methodology/ triggered an auto-export whose file-location lookup
  only scanned within the subdir; rules whose original files lived outside
  scope fell through to <output_dir>/<domain>/rules.md, creating bogus
  duplicates like bible/methodology/process/rules.md. Auto-export is now
  gated on path.resolve() == DEFAULT_BIBLE_DIR.resolve(). Regression tests
  in tests/test_import_markdown_unified.py::TestImportMarkdownEdgeCases
  cover the subdir-skip and default-root-still-fires cases.

Notes:
- Backwards compat: python scripts/migrate.py [--bible-dir ...]
  [--methodology-dir ...] [--dry-run] and from scripts.migrate import
  run_migration continue to work unchanged. The shim prints a deprecation
  notice to stderr on direct invocation but does not change exit codes.
- Intentional behavior change: writ import-markdown with no flags now
  imports methodology too. Pre-1.5.0 invocations relying on the Rule-only
  side effect should add --only Rule to preserve the old scope.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

v1.3.0

Toggle v1.3.0's commit message
v1.3.0: per-turn test pipeline + log_friction_event quoting fix

Per-turn test-execution: PostToolUse mark + Stop-hook runner batch the
turn's writes, resolve source -> test via a config-driven path matcher
(generic conventions + Magento layout by default; project override via
.claude/writ.json), invoke pytest / go test / phpunit grouped by runner,
and surface real failures via the existing emit-summary helper. Silent on
pass, terse on fail, per-runner friction telemetry.

Path knowledge is no longer hardcoded in the bash hooks: a new
bin/lib/test_paths.py helper owns match-src / match-test / resolve-test /
runner-for, consumed by both new hooks plus available for any future hook.

Behind that surface this release also repairs a long-standing JSON-quoting
bug in log_friction_event (the ${4:-{}} default-value form was appending a
stray } to every JSON extras argument, breaking json.loads for every
caller that passed extras -- around twenty hooks). Quoting the default
literal {} repairs the parse without touching any caller; friction-log
entries now carry their full payload as designed.

Also fixed: a set -e interaction in the run hook's run_group that aborted
the script when phpunit returned non-zero (warnings-only runs treated as
hook failures); the PHPUnit warning-vs-failure conflation in the summarizer
(numbered warning lists were counted as failures); and a heredoc quoting
bug in validate-test-file.sh that emitted an IndexError traceback on every
internal plan.md update Claude makes.

Magento PHPUnit invocation now passes --cache-directory=/tmp/writ-phpunit-cache
--do-not-cache-result so the result-cache permission warning is suppressed
on default-permission Magento checkouts. Allure extension warning is
documented as environmental and not interpreted as a failure.

71 tests pass (6 version-consistency + 65 new). cache/ added to .gitignore.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

v1.2.0

Toggle v1.2.0's commit message
v1.2.0: observability fixes + non-blocking context warnings

v1.1.0

Toggle v1.1.0's commit message
v1.1.0 - Real-corpus benchmark + Item 1-6 corrections

Headline changes (see commit log 6f66e09..faa0a20 for full detail):
- Item 1c/1d: ENF-SYS-003 cron-job race-condition relabel; SOLID-DIP-002 trigger edit (Q81)
- Item 2: live-vs-synthetic latency gap diagnosed across four hypotheses
- Item 3: domain hit-rate enforced at top-5 on real corpus
- Item 4: HNSW cache check before encoding; cold-start O(N) -> O(1) warm
- Item 5: compression ratio measured on real corpus; non-monotonicity documented
- Item 6: user-facing version refs aligned to v1.1.0
- Docs: HANDBOOK + PROMOTIONAL-BRIEF + extraction docs updated with v1.1.0 benchmarks
- Tooling: per-stage cold-start instrumentation script (evidence source for Item 4)

v1.0.1

Toggle v1.0.1's commit message
v1.0.1: Plugin distribution

Writ is now installable as a Claude Code plugin via:

  claude plugin marketplace add infinri/Writ
  claude plugin install writ@writ

Published to PyPI as claude-writ. The standalone install at
~/.claude/skills/writ/ is byte-identical to v1.0.0 and continues to work.

See CHANGELOG.md for the full set of changes.

v1.0.0

Toggle v1.0.0's commit message
Writ v1.0.0 -- First production release (2026-05-10)

A Claude Code harness with two co-equal layers:

  * Knowledge layer: a hybrid-RAG service running a five-stage retrieval
    pipeline (domain filter, BM25 via Tantivy, ANN via hnswlib over ONNX
    all-MiniLM-L6-v2 embeddings, graph traversal via pre-computed
    adjacency cache, two-pass weighted ranking) over a Neo4j-backed
    knowledge graph. 0.590 ms p95 end-to-end at 276 rules.

  * Enforcement layer: a session-aware state machine plus 30 hook scripts
    wired into Claude Code. Four-mode workflow (Conversation, Debug,
    Review, Work) with two Work-mode gates (plan-approval and
    test-skeletons). Approval requires a one-time token; agent
    self-approval is structurally blocked.

The 220-rule public out-of-the-box rulebook (Security, Clean Code, DRY,
SOLID, Architecture, Testing, Error Handling, Performance & Caching,
Scaling, API Design, Process & Lifecycle, Documentation) is seeded into
the live corpus alongside Writ-specific rules, bringing the live count
to 276 rules / 30 mandatory. 19 of the mandatory rules are backed by
six cross-language regex analyzers in bin/run-analysis.sh.

See CHANGELOG.md for the full release notes.

Verification at release: 1441 tests pass, 15 skipped, 0 failed; live
service reports 276/30/warm; MRR@5 = 0.4886 against the 19-query
ambiguous evaluation set (floor 0.45); hit rate = 0.7636 against the
165-query ground-truth corpus (floor 0.75).

License: MIT. Authored by Lucio Saldivar.