The ASSEMBLY ROOT of the opendox project — the repository you clone.
It holds no product code of its own: it holds the manifest that says what this
project IS, the two legs as submodules, and the pins that say which commit of
each leg this project is.
Scaffolded from opensoft/openRepoShape
at e9c4827b85f50503bbdd9e5b4fac9d6c3d0baf63. Elected by Brett Heap on 2026-09-05, against
openxFactory docs/project-repo-schema.md.
git clone --recurse-submodules https://github.com/opensoft/openDox.git
cd openDox
make bootstrapmake bootstrap puts each leg on the main branch at its
pinned commit (so you are not staring at a detached HEAD), runs the three
neutral validators, and prints whatever review authority a wallet register
names for this project — or says plainly that authority is not wallet-carried
here, and continues.
| role | repository | path | holds |
|---|---|---|---|
| assembly | opensoft/openDox |
. |
this manifest, the pins, the gate |
| spec | opensoft/openDox-spec |
spec/ |
requirements, decisions, acceptance |
| code | opensoft/openDox-code |
code/ |
the implementation and its tests |
All three carry the GitHub topic xf-project-opendox, so the organisation's own search
surfaces the group without a checkout.
If opensoft/openDox-spec or opensoft/openDox-code is private or internal,
the validate workflow's default GITHUB_TOKEN cannot clone it as a
submodule.
Preferred: a dedicated GitHub App — permissions Contents: Read-only and Metadata: Read, installed on this organisation with access to the legs — mints a short-lived token at run time:
gh secret set SHAPE_LEGS_APP_ID --org <your-org> --body '<app id>'
gh secret set SHAPE_LEGS_APP_PRIVATE_KEY --org <your-org> < app-private-key.pemFallback: a fine-grained SHAPE_LEGS_TOKEN PAT, contents:read on the
LEGS ONLY:
gh secret set SHAPE_LEGS_TOKEN --org <your-org> --body '<token>'On the GitHub Free plan, set these as REPOSITORY secrets. GitHub delivers
an ORGANISATION secret only to PUBLIC repositories on Free, so on a private
repository secrets.SHAPE_LEGS_APP_ID is the empty string — silently — the
App steps skip, and validate goes GREEN with the lockstep pin check degraded
away rather than red. Use --repo <org>/<Repo> in place of --org <your-org>
above, or upgrade the organisation to Team. (Measured on InkRouter,
2026-09-04.)
The root repository itself is always readable by the workflow's own default
token, so actions/checkout never carries a token: override — putting a
legs-scoped credential there instead is what broke the ROOT checkout with a
403 the first time a PAT was tried for real. Whichever credential resolves is
read only inside the guarded "fetch the legs (submodules)" step, scoped to
that step's env:, and used through a git -c url.<...>.insteadOf=<...>
rewrite covering both HTTPS and SSH leg URLs — it never touches the root
checkout.
validate tries the App first — a mint a leg-reader token from the GitHub App step, scoped by repositories: to the legs this organisation itself
owns (a leg under a different owner is excluded with a warning, since an
installation token is per-owner) — and falls back to SHAPE_LEGS_TOKEN when
the App is not configured. A configured App that fails to mint fails the job
outright, naming both secrets and the required installation, rather than
degrading.
Without either credential the workflow does not go red on that account: it
checks out the root without submodules, tries git submodule update --init --recursive best-effort, and — if that fails — still runs the naming and
manifest checks, skips validate-pins.py with a warning explaining why, and
only fails outright if a credential (App or PAT) is configured and the
fetch still failed — naming which source it used. That presence check reads
job-level env: SHAPE_LEGS_APP_SET / SHAPE_LEGS_TOKEN_SET booleans rather
than the secrets context directly in the step's if: — the secrets
context is not allowed in a step-level if: expression, and using it there
makes GitHub reject the whole workflow file instead of just that step.
For each leg, THREE things name the same commit and they move in ONE commit:
- the gitlink — the
160000entry recorded at the leg's path commit:incontracts/<role>-pin.yaml- every
.github/workflows/*.yml@<sha>reference naming that leg
python3 scripts/validate-pins.py (also make pins, also the validate check
on every pull request) refuses if they disagree, and recomputes the leg's tree
digest on top. Advancing a pin is therefore one commit that touches the
submodule, the pin file, and any workflow ref — never a bare git submodule update followed by a commit.
This is written down because the family learned it the expensive way: seven
consecutive pin-syncs in the xFactory aggregation moved the gitlink alone and
left validate red on every pull request for a day, unnoticed because the
check runs on pull requests only.
Nothing. Electing this shape changes no gate, no floor, no grant and no
clearance eligibility; a one-repository project is reviewed identically,
because the authority travels in the grants rather than in the layout. The
role: fields in project.yaml are navigation. A tool that reads role: spec
as "spec authority lives here" has quietly turned a layout into a governance
boundary, and is defective.
AGENTS-shape.md the RULES OF THE SHAPE, for an agent (copied)
AGENTS.md this project's own instructions (yours)
CLAUDE.md one line, pointing at AGENTS.md
project.yaml the manifest — the SOURCE of this group
contracts/repository-naming.yaml the four naming families (copied from the shape)
contracts/spec-pin.yaml the spec leg's commit + tree digest
contracts/code-pin.yaml the code leg's commit + tree digest
contracts/shape-pin.yaml the openRepoShape revision + per-file digests
scripts/bootstrap.py the one command after a recursive clone
scripts/validate-manifest.py project.yaml, and the legs' names
scripts/validate-pins.py THE LOCKSTEP VALIDATOR
scripts/validate-repository-naming.py
scripts/repo_shape.py shared helpers, standard library only
.github/workflows/validate.yml the neutral gate, on pull_request
Everything under scripts/, plus contracts/repository-naming.yaml and
AGENTS-shape.md, is a COPY from opensoft/openRepoShape, digest-pinned in
contracts/shape-pin.yaml. Edit them upstream, not here — a local edit is
reported as drift. AGENTS.md and CLAUDE.md have no row and are this
project's own.
This repository carries the openDox project's posture files:
CONTRIBUTING.md (how to contribute across all three
repositories), CODE_OF_CONDUCT.md, and
SECURITY.md (security reports go through GitHub's private
vulnerability-reporting form, never a public issue). All three repositories
share the Apache License 2.0. In all three, the validate check
is a required status check on main, enforced by a repository ruleset — see
docs/branch-protection.md.
The doc index for this repository. Everything under docs/ is listed here,
and a new document is linked from this table in the same pull request that
adds it — the xFactory family's standing rule, levelled across all six
openDox/openXdox repositories by the OQ-O scaffold pass
(opensoft/openxFactory#656).
| document | what it is |
|---|---|
| docs/branch-protection.md | the repository ruleset that makes validate a required status check on main, its evaluate → active history, and the one policy difference between the two families |