Project-agnostic Goal B operating layer: bind sub-goals to goals via executable anchors, machine-checked.
Project description
pharnoss
A project-agnostic Goal B operating layer. pharnoss (pharos, the lighthouse, + harness) lets many contributors share one goal and contribute building blocks without the global plan, with alignment machine-checked instead of argued in a PR.
It pairs with any contract-first / executable-test gate. A team's goal stays the lighthouse; each iteration goal is written as an executable, self-checkable anchor bound to a real requirement; pharnoss enforces that binding deterministically.
pharnoss carries nothing project-specific: everything that binds it to a project lives in a per-project
pharnoss.toml+ an adapter doc. Drop it into any repo, point it at that repo's goal graph, and the gate runs.
Install
pharnoss is pure-stdlib (Python 3.11+, no third-party dependencies — just tomllib),
so you can install it straight from GitHub with no package index. Pin a tag or commit
(not a branch) so you control when you upgrade.
# Run ephemerally, npx-style (no permanent install):
uvx --from git+https://github.com/IanYHChu/pharnoss@v0.2.0 pharnoss init
# Or install as a re-runnable user tool:
pipx install git+https://github.com/IanYHChu/pharnoss.git@v0.2.0
# Or into the current environment:
pip install "git+https://github.com/IanYHChu/pharnoss.git@v0.2.0"
Local / editable for development: pip install -e /path/to/pharnoss. You can also run it
without installing anything — see "No-install" below.
Quickstart
The Claude-Code-native path — install the skill once, then bind each project from inside Claude Code:
pharnoss install # put the /pharnoss skill at ~/.claude (available everywhere)
# then, in Claude Code, inside any project:
/pharnoss init # interactively scan, confirm layout, write the binding
Or scaffold a project directly from the shell:
cd your-project
pharnoss init # scaffold: pharnoss.toml, the skill, a starter adapter,
# empty anchors/claims, a GOALS.md stub
pharnoss init --example # ...or a runnable sample (one goal + differential anchor)
pharnoss init --auto # headless: scan + pre-fill [repos] and goal source, no prompts
# edit pharnoss.toml ([goal].source + id_pattern) and .pharnoss/adapter.md
pharnoss check # the alignment gate: exit 0 aligned / 1 misaligned / 2 setup
pharnoss check --report # human view of goal -> anchor -> claim
pharnoss run # the reference runner: anchors as pending/frozen tests
pharnoss install puts the project-agnostic /pharnoss skill at the user level
(~/.claude/skills/pharnoss/SKILL.md, or --local for one project) so /pharnoss init
exists before any project is bound. pharnoss init is the one-command bind into a project:
idempotent (skips existing files; --force to overwrite), and it also drops the skill into
.claude/skills/pharnoss/SKILL.md for that project.
Multi-repo projects
pharnoss binds at the umbrella / control root, once — not per repo. Declare the repos in
[repos] (name = "path"; ../name when the repos sit beside a control folder) and give each
anchor a target_repo from that set. With [repos] present the gate hard-fails any anchor whose
target_repo is not a declared repo. pharnoss scan discovers the layout and repos, and
/pharnoss init (or pharnoss init --auto) fills [repos] in for you.
CLI
| Command | Does |
|---|---|
pharnoss install [--global|--local] [--force] |
install the /pharnoss skill (user-level by default) so it is available before any project is bound |
pharnoss check [--config P] [--report] |
run the alignment gate (orphan / claim / manifest / repo-binding integrity hard; coverage advisory) |
pharnoss run [--config P] [--report] |
run anchors via the reference runner (pending/frozen lifecycle; exit 0/1/2) |
pharnoss init [--path D] [--force] [--example [ECO]] [--auto] |
scaffold pharnoss into a project (--example adds a runnable sample; --auto scans + fills [repos]) |
pharnoss scan [--path D] [--json] |
discover project layout + sub-repos (drives interactive /pharnoss init) |
pharnoss update [--config P] [--json] |
re-sync scaffolded files to the installed pharnoss version (see Updating) |
pharnoss stamp [--config P] |
record the current scaffolded state as the update baseline |
python -m pharnoss … |
same, without the console script |
No-install: the repo also ships check_alignment.py, a stdlib shim, so a consumer
can run the gate with zero install: python3 /path/to/pharnoss/check_alignment.py
(handy for CI or a consumer repo that doesn't want pharnoss as a dependency).
Updating
pharnoss has two layers, updated separately:
-
The engine (this package — the gate, the runner, the CLI). The package manager owns it; pin a newer tag:
pipx upgrade pharnoss # if installed via pipx pip install --force-reinstall "git+https://github.com/IanYHChu/pharnoss.git@v0.3.0"
-
The scaffolded files that live inside your repo — chiefly the
/pharnossskill. These go stale when the engine moves on.pharnoss updatere-syncs them without clobbering your work:pharnoss update # in your project, after upgrading the engine
It records a base in
.pharnoss/install.json(the pharnoss version that last scaffolded the project + a hash per tracked file) so it can tell a pristine file (safe to overwrite) from one you edited. Pristine skill files are overwritten to the latest; a file you customized is reported asneeds_mergeand left untouched; new optionalpharnoss.tomlkeys are reported, never force-written. Your goal graph, anchors, claims, and adapter prose are never overwritten.Because pharnoss is a Claude Code extension, the merge of customized files is LLM-assisted: run
/pharnoss updatein Claude Code and the skill reads the report plus the maintainer-authored upgrade notes for the version span and merges new capability into your files additively, showing you a diff before finalizing.
For maintainers: any release that changes a scaffolded file (the skill, the config schema, or the adapter template) ships an upgrade note under
pharnoss/upgrades/<version>.md. Keep config changes additive and backward-compatible (new keys optional with a default, no renames) so an update introduces capability rather than forcing a migration.
What pharnoss owns vs what your project owns
pharnoss owns the project-agnostic core: the manifest + claim schemas, the alignment
gate (pharnoss/align.py), the /pharnoss skill (pharnoss/skill/SKILL.md), and the
lifecycle (pending → frozen = promote; the ratchet; informant-vs-judge). The default
status vocabulary is pending/frozen (override via [anchors].statuses).
Your project owns the binding (pharnoss.toml): the goal graph and its id format
([goal]), the anchor manifest, the executable runner ([runner] — pharnoss ships a
replaceable reference runner, pharnoss run, or point it at your own: pytest, make,
cargo, …), and the adapter doc ([adapter].doc) with the project-specific HOW. See
pharnoss.example.toml for the full schema.
The alignment gate
check binds three artifacts named in pharnoss.toml: the goal graph ([goal].source),
the anchor manifest ([anchors].manifest, each anchor names a parent goal id), and the
claim ledger ([claims].file). It finds pharnoss.toml in the current directory or any
parent unless --config is given. ORPHAN anchor (parent not a real goal) and CLAIM
integrity hard-fail (exit 1); goal COVERAGE is advisory — a goal with no anchor is a
backfill worklist, not a failure.
The runner
check proves anchors bind to real goals; the runner proves each anchor is
executable. pharnoss does not force a runner, but ships a reference one: pharnoss run
reads each anchor's status and runs its check command (cmd, else [runner].anchor_cmd
with {name} substituted), applying:
| status | check fails | check passes |
|---|---|---|
| pending | expected → green | READY TO PROMOTE → red (freeze it) |
| frozen | REGRESSION → red | ok → green |
Exit 0 green / 1 red / 2 setup. Promotion = flip status pending→frozen (one field;
the test does not move). A project with its own contract harness points [runner] at it and
ignores pharnoss run. pharnoss init --example scaffolds a working end-to-end sample (one
goal, one differential anchor, a tiny impl) where both check and run are green.
Status
Standalone, installable from GitHub, with a CLI and project scaffolding. Dogfooded on a
real Rust project and a non-Rust toy project (markdown goals / Python runner). Next:
publish to an index; a richer init (detect the project's runner); per-project
skill-install via pharnoss init.
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 pharnoss-0.2.0.tar.gz.
File metadata
- Download URL: pharnoss-0.2.0.tar.gz
- Upload date:
- Size: 34.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
046200d6d03ea49ec7104a027d6c5b2b842b8e56dc3600cc521a16c44a43556d
|
|
| MD5 |
0b1ba2a56cdd64cc4474402f41ac7002
|
|
| BLAKE2b-256 |
ddf5aa69807c502790ce3c33e20de9912ff0f6d7165171af5759f3f8e8935e5f
|
Provenance
The following attestation bundles were made for pharnoss-0.2.0.tar.gz:
Publisher:
release.yml on IanYHChu/pharnoss
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pharnoss-0.2.0.tar.gz -
Subject digest:
046200d6d03ea49ec7104a027d6c5b2b842b8e56dc3600cc521a16c44a43556d - Sigstore transparency entry: 1731226870
- Sigstore integration time:
-
Permalink:
IanYHChu/pharnoss@769ae1979cf24f8a416ce2b80c47f7bb53092192 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/IanYHChu
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@769ae1979cf24f8a416ce2b80c47f7bb53092192 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pharnoss-0.2.0-py3-none-any.whl.
File metadata
- Download URL: pharnoss-0.2.0-py3-none-any.whl
- Upload date:
- Size: 36.1 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 |
7bbfa7cbdf5b9444c8de972ab8473f103491227a1e5ea6711886611160f14aa5
|
|
| MD5 |
c8284311510658c2f587d409520ebaaa
|
|
| BLAKE2b-256 |
0d8a4bdab3246ef8f3183f79d66f508da89d32d9a7d8c21ffb8a5f770a3c033b
|
Provenance
The following attestation bundles were made for pharnoss-0.2.0-py3-none-any.whl:
Publisher:
release.yml on IanYHChu/pharnoss
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pharnoss-0.2.0-py3-none-any.whl -
Subject digest:
7bbfa7cbdf5b9444c8de972ab8473f103491227a1e5ea6711886611160f14aa5 - Sigstore transparency entry: 1731226928
- Sigstore integration time:
-
Permalink:
IanYHChu/pharnoss@769ae1979cf24f8a416ce2b80c47f7bb53092192 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/IanYHChu
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@769ae1979cf24f8a416ce2b80c47f7bb53092192 -
Trigger Event:
release
-
Statement type: