Reusable safety primitives for Claude Code orchestrator harnesses
Project description
core-harness
Reusable safety primitives for Claude Code orchestrator harnesses (permission schema, hook framework, audit/journal).
Status: pre-1.0, API not frozen. Latest release: v0.3.1. Expect breaking changes between minor versions until 1.0. See
docs/semver-policy.md.
Not an AI agent framework.
core-harnessprovides Claude Code-specific governance primitives (permission schema, hook framework, audit/journal). It does not implement agent runtime abstractions such asagent/tool/run/state/handoff/memory/trace— those concerns belong in higher layers (e.g. consumer harnesses likeclaude-org-ja) or in dedicated agent frameworks (LangChain, AutoGen, CrewAI, OpenAI Agents SDK).
Overview
core-harness is Layer 1 of the claude-org 4-layer architecture:
Layer 4: Org-specific orchestrators (e.g. claude-org-ja)
Layer 3: Org-specific roles & playbooks
Layer 2: Shared role contracts
Layer 1: core-harness <-- you are here
(permission schema, hook framework, audit/journal)
core-harness is generic and consumer-agnostic: it does not know about
secretaries, dispatchers, curators, workers, or any specific org. It does not
import, reference, or special-case claude-org or claude-org-ja. Dependency
is strictly one-way — consumers depend on core-harness, never the reverse.
This Q4 (Layer 1 purity) invariant is enforced by the test suite. See
docs/canonical-ownership.md.
claude-org-ja is the first consumer and drove much of the initial design,
but the public surface is intended for any team building a Claude Code
orchestrator harness who wants to reuse the permission schema, hook framework,
or audit journal rather than rebuild them.
Install
pip install git+https://github.com/suisya-systems/core-harness@v0.3.1
PyPI publish is deferred until 1.0; until then GitHub Releases / git tags are the only distribution channel.
Usage
The shipped public surface in v0.3.1:
core_harness.schema
Loads the framework JSON Schema (permission rules, required hook scripts, forbidden-allow patterns) and merges it with consumer-supplied org extensions.
from core_harness.schema import load_framework_schema, merge_schemas
framework = load_framework_schema()
merged = merge_schemas(framework, org_extension)
Exports: load_framework_schema, framework_schema_path, merge_schemas,
SchemaError.
core_harness.validator
Fail-closed validation for settings.local.json (and settings.json) against
the framework schema plus an optional org extension. Returns structured
Findings and a ValidationResult.
from core_harness.validator import validate_settings, check_worker_settings
result = validate_settings(settings_path, schema=merged)
if not result.ok:
for f in result.findings:
print(f.code, f.path, f.message)
check_worker_settings(worker_dir, schema=merged, include_worktrees=False)
Exports: validate_settings, validate_config, validate_schema_integrity,
extract_role_blocks, check_worker_settings (kw-only include_worktrees),
matches_worker_template, Finding, ValidationResult.
core_harness.generator
Renders a role template into a worker directory, substituting consumer- supplied placeholders. Detects unresolved placeholders rather than letting them leak into generated config.
from core_harness.generator import generate_settings, UnresolvedPlaceholderError
generate_settings(role="worker", target_dir=worker_dir, context={...})
Exports: generate_settings, render_role, UnresolvedPlaceholderError.
core_harness.hooks
Standard contract for Claude Code PreToolUse hooks: a Python HookRunner
plus a parallel bash library accessible via lib_path() for shell-based
hooks. Block messages are locale-neutral by default (English "Blocked: ")
and overridable via the CORE_HARNESS_BLOCK_PREFIX environment variable.
from core_harness.hooks import HookRunner, parse_pretooluse_stdin, exit_with_block, lib_path
event = parse_pretooluse_stdin()
runner = HookRunner(rules=[...])
decision = runner.evaluate(event)
if decision.block:
exit_with_block(decision.reason)
# bash hooks source the shipped library
. "$(python -c 'from core_harness.hooks import lib_path; print(lib_path())')"
Exports: HookRunner, parse_pretooluse_stdin, exit_with_block, exit_ok,
lib_path.
core_harness.audit
Per-pane append-only Journal for orchestrator audit events. The journal
path is consumer-injected (core-harness does not pick a default location)
and writes are concurrency-safe via file locking. A parallel bash helper is
exposed via lib_path().
from core_harness.audit import Journal, append_event, iter_events
journal = Journal(path=consumer_chosen_path)
append_event(journal, event_type="dispatch", payload={...})
for ev in iter_events(journal):
...
Exports: Journal, append_event, iter_events, lib_path, JournalError,
JournalLockError, JournalReadError.
See docs/api-surface-v0.x.md for the full
evolving contract.
Versioning
Pre-1.0 semver (see docs/semver-policy.md):
- Minor bumps (
0.X.0) may include breaking changes. - Patch bumps (
0.X.Y) are additive and bug-fix only. - Removing or breaking a previously-shipped public symbol requires one minor
version of overlap with a
DeprecationWarningbefore removal.
1.0 graduation requires all of:
- At least two independent consumers running on the same minor for one month without needing a breaking change.
- Two consecutive minor releases shipped with no breaking changes.
- The public surface in
docs/api-surface-v0.x.mdmarked stable (no remainingexperimental:entries for items intended for 1.0).
Releasing
Releases are tag-driven. Pushing a tag matching v* triggers
.github/workflows/release.yml,
which:
- Builds an sdist and a wheel via
python -m build. - Publishes the artefacts to PyPI through a Trusted Publisher (OIDC — no API token is stored in the repo).
- Creates / updates a GitHub Release with the same tag and attaches the built artefacts.
Cutting a release:
# 1. Bump version in pyproject.toml and update CHANGELOG.md.
# 2. Land both via PR.
git tag -s vX.Y.Z -m "vX.Y.Z"
git push origin vX.Y.Z
One-time setup before the first PyPI publish. PyPI must have a Trusted Publisher entry registered for this repo. On pypi.org/manage/project/core-harness/settings/publishing/, add a publisher with:
- Owner:
suisya-systems - Repository:
core-harness - Workflow:
release.yml - Environment:
pypi
Until that entry exists, the publish step in release.yml will fail.
The build and GitHub-Release jobs still succeed independently, so
re-tagging after the entry is registered is enough to publish.
If Trusted Publisher is not desired, the workflow has an API-token
fallback commented out — uncomment it, drop the id-token: write
permission, and add PYPI_API_TOKEN to repo secrets.
PyPI publishing remains deferred until the 1.0 cut; the workflow landing here is the skeleton, not a release.
Related
- v0.3.1 release notes
- claude-org-ja Issue #128 (closed) — extraction tracking
- claude-org-ja PR #196 — extraction design
- claude-org-ja shim PRs: #197 (Step B), #198 (Step C), #199 (Step D), #201 (0.3.1 follow-up)
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file core_harness-0.3.2.tar.gz.
File metadata
- Download URL: core_harness-0.3.2.tar.gz
- Upload date:
- Size: 36.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3ec26710e499de4a20ade2ec41276a567f438e3a33a14c70095f977e80a91b55
|
|
| MD5 |
c2f6f89bcf4ee3a6cd57d0165cb83692
|
|
| BLAKE2b-256 |
7e73704014e931325baf1a83918e87d042d6ff97345ec7b42150cc566dc98a05
|
Provenance
The following attestation bundles were made for core_harness-0.3.2.tar.gz:
Publisher:
release.yml on suisya-systems/core-harness
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
core_harness-0.3.2.tar.gz -
Subject digest:
3ec26710e499de4a20ade2ec41276a567f438e3a33a14c70095f977e80a91b55 - Sigstore transparency entry: 1424851356
- Sigstore integration time:
-
Permalink:
suisya-systems/core-harness@65b7e8c3671a86e69d6c44bbc28a3ee792fa447b -
Branch / Tag:
refs/tags/v0.3.2 - Owner: https://github.com/suisya-systems
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@65b7e8c3671a86e69d6c44bbc28a3ee792fa447b -
Trigger Event:
push
-
Statement type:
File details
Details for the file core_harness-0.3.2-py3-none-any.whl.
File metadata
- Download URL: core_harness-0.3.2-py3-none-any.whl
- Upload date:
- Size: 28.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8c6b55a532c3dd8bea2e7c616d38a4e0b894727ffdf4780a6fce50cf2b2f57b3
|
|
| MD5 |
93af489136ed687306b8eca09e207494
|
|
| BLAKE2b-256 |
e42bf7f8678c3dbc2a6b3f754bfe61a040c759abebea67d298ceee078c4ba92d
|
Provenance
The following attestation bundles were made for core_harness-0.3.2-py3-none-any.whl:
Publisher:
release.yml on suisya-systems/core-harness
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
core_harness-0.3.2-py3-none-any.whl -
Subject digest:
8c6b55a532c3dd8bea2e7c616d38a4e0b894727ffdf4780a6fce50cf2b2f57b3 - Sigstore transparency entry: 1424851492
- Sigstore integration time:
-
Permalink:
suisya-systems/core-harness@65b7e8c3671a86e69d6c44bbc28a3ee792fa447b -
Branch / Tag:
refs/tags/v0.3.2 - Owner: https://github.com/suisya-systems
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@65b7e8c3671a86e69d6c44bbc28a3ee792fa447b -
Trigger Event:
push
-
Statement type: