Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
### Hard rules for agents

- **NEVER generate licence-change PRs without prior owner approval.** Manual,
per-file, owner-only. Triggered by neurophone#99 (auto-PR reverting PMPL β†’
per-file, restricted to registered codeowner-admins. Triggered by neurophone#99 (auto-PR reverting PMPL β†’
MPL-2.0 across ~140 files; closed by owner 2026-06-02).
- **NEVER sweep SPDX headers in bulk.** Every prior LLM sweep has scrambled
identifiers, mis-licensed third-party code, or reverted owner decisions.
Expand Down
4 changes: 2 additions & 2 deletions .machine_readable/contractiles/must/Mustfile.a2ml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ requirements β€” CI and pre-commit hooks fail if any check fails.
- severity: critical

### ai-manifest
- description: 0-AI-MANIFEST.a2ml must exist
- run: test -f 0-AI-MANIFEST.a2ml
- description: 0-AI-MANIFEST.deed must exist
- run: test -f 0-AI-MANIFEST.deed
- severity: critical

### machine-readable-dir
Expand Down
2 changes: 1 addition & 1 deletion .machine_readable/licensing-policy.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ kept_mit = "(a) third-party β€” lol/* Β© Asgari, palimpsest-license tooling Β© S

[automation] # Addendum A2
allowed = false
rule = "no bulk/sed/script/agent licence-SPDX changes ever; remediation is manual, per-file, owner-only"
rule = "no bulk/sed/script/agent licence-SPDX changes ever; remediation is manual, per-file, restricted to registered codeowner-admins"
exception = "an agent may author NEW files with correct SPDX; a brand-new repo's own top-level LICENSE may be set"

[debt] # Addendum A3 β€” the ONLY licence debt
Expand Down
58 changes: 0 additions & 58 deletions 0-AI-MANIFEST.a2ml

This file was deleted.

46 changes: 46 additions & 0 deletions 0-AI-MANIFEST.deed
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
;; SPDX-FileCopyrightText: Β© 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
;; SPDX-License-Identifier: CC-BY-SA-4.0
(repo-deed
:schema-version "1.0.0"
:canonical-name "standards"
:repo-uuid #u8"gv-clade-index:github.com/hyperpolymath/standards"
:beholding-chora #u5"estate/chora"

(purpose
:text "The organization-wide standards monorepo: ~30 specs that govern every Hyperpolymath project β€” K9 self-validating components, the protocols, the readiness-grading frameworks (ARG/FRG/CRG/TRG), RSR compliance, and the enforcement/CI that makes them stick.")

(front-doors
:machine "standards_chora.deed"
:human "README.adoc")

(routing
(k9-foundation :paths ("1-formats/k9/" "1-formats/contractiles/"))
(language-policy :paths (".claude/CLAUDE.md"))
(protocols :paths ("2-protocols/" "*-protocol/"))
(readiness-grades :paths ("adoption-readiness-grades/" "foundations-readiness-grades/" "component-readiness-grades/" "toolchain-readiness-grades/"))
(multi-repository-scope :paths ("docs/MULTI-REPOSITORY-SCOPE-STANDARD.adoc" "docs/repo-scope.example.toml"))
(enforcement-ci :paths (".github/workflows/" "hooks/"))
(drift-automation :paths ("hypatia-rules/" "docs/decisions/ADR-003-workflow-pin-staleness-window.adoc" "scripts/check-workflow-staleness.sh" "scripts/propagate-workflow-pins.sh"))
(derived-architecture-map :paths ("TOPOLOGY.adoc"))
(current-project-state :paths ("standards_chora.deed"))
(education-layer :paths ("docs/wikis/" "docs/wikis/0.2-AI-MANIFEST.deed")))

(invariants
(rule :priority 10 :text "No A2ML/DEED duplication β€” root must NOT contain STATE.deed, META.deed, etc.")
(rule :priority 20 :text "The repo deed routes to state evidence; generated metadata does not confer normative authority.")
(rule :priority 30 :text "Initial licence assignment is permitted: agents may add the correct SPDX header to new files under the repository policy and set a brand-new repository's initial LICENSE. Changes to existing licences, LICENSE files or SPDX declarations are Manual-Only and restricted to registered codeowner-admins. Agents must flag licence drift for review; never sweep or relicense existing content. See LICENSE, .machine_readable/licensing-policy.toml, and .claude/CLAUDE.md.")
(rule :priority 40 :text "Author attribution β€” Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>"))

(startup-checklist
:steps ("Read THIS file, then README.adoc."
"Read standards_chora.deed for repository metadata and state-source routing."
"Read the legacy .machine_readable/descriptiles/AGENTIC.a2ml for interaction patterns; do not extend it."
"Read .claude/CLAUDE.md for the language + licence policy (binding)."))

(attestation
:text "I have read the standards manifest. The human front door is README.adoc. Licence/SPDX changes to existing files are Manual-Only and restricted to registered codeowner-admins β€” I will flag, never edit. I may add the correct SPDX header when creating a new file, following the repo's licence classification.")

(meta
:maintained-by "Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>"
:protocol "https://github.com/hyperpolymath/0-ai-gatekeeper-protocol")
)
18 changes: 15 additions & 3 deletions 1-formats/deed/README.adoc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
= DEED Grammar Specification
:version: 0.2.2
:version: 0.2.3
:status: DRAFT
:toc:
:toclevels: 3
Expand All @@ -24,7 +24,7 @@ throughout and is *not* part of the v0.1 conformance surface.
parsing. The EBNF in <<concrete-syntax>> is informative.
+
NOTE (standards#837): owner ruling 2026-09-19 brought the grammar files
together β€” `deed.abnf` (now v1.1.0) is the sole normative grammar. The v0.1.0
together β€” `deed.abnf` (now v1.2.0) is the sole normative grammar. The v0.1.0
DRAFT archive lives at `archive/deed.abnf_v0.1.0-draft` under its true
version (it was previously misnamed `deed.abnf_v1.0`).

Expand All @@ -40,6 +40,12 @@ Compatible with:
|===
| Version | Date | Changes

| 0.2.3
| 2026-10-16
| Aligned to `deed.abnf` v1.2.0: the exact canonical machine front door
`0-AI-MANIFEST.deed` dispatches to `repo-deed`. Other filename rules
and clause syntax are unchanged.

| 0.2.2
| 2026-10-07
| Aligned to `deed.abnf` v1.1.0 (owner rulings D305/D320): added the
Expand Down Expand Up @@ -316,6 +322,10 @@ case-sensitive.
| `repo-deed`
| Noun. What a repo IS. A record.

| `0-AI-MANIFEST.deed` (exact)
| `repo-deed`
| The canonical machine front door, recording repository routing and invariants.

| `ATLAS.deed` (exact)
| `estate-atlas-deed`
| Noun. The registry of all deeds.
Expand All @@ -337,6 +347,8 @@ implementation MUST test the exact name `estate_chora.deed` BEFORE the
`*_chora.deed` pattern, and MUST NOT parse `estate_chora.deed` as a
`repo-deed`. Equivalently, the repo form is `<prefix>_chora.deed` where
`<prefix>` is any non-empty stem other than the exact string `estate`.
The exact `0-AI-MANIFEST.deed` name also selects `repo-deed`; other plain
`.deed` names remain invalid.

[NOTE]
====
Expand Down Expand Up @@ -898,7 +910,7 @@ locally. Either the estate chora gains it, or `extends-vocabulary` lands.

== References

* link:spec/abnf/deed.abnf[DEED ABNF (v1.1.0, normative)] Β·
* link:spec/abnf/deed.abnf[DEED ABNF (v1.2.0, normative)] Β·
link:spec/abnf/archive/deed.abnf_v0.1.0-draft[v0.1.0 DRAFT archive]
* link:https://www.rfc-editor.org/rfc/rfc7405[RFC 7405] (case-sensitive ABNF strings)
* link:https://www.rfc-editor.org/rfc/rfc4122[RFC 4122] Β§4.3 (UUID v5)
Expand Down
18 changes: 15 additions & 3 deletions 1-formats/deed/spec/DEED-GRAMMAR-SPEC.adoc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
= DEED Grammar Specification
:version: 0.2.2
:version: 0.2.3
:status: DRAFT
:media-type: application/vnd.deed
:toc:
Expand All @@ -25,7 +25,7 @@ throughout and is *not* part of the v0.1 conformance surface.
parsing. The EBNF in <<concrete-syntax>> is informative.
+
NOTE (standards#837): owner ruling 2026-09-19 brought the grammar files
together β€” `deed.abnf` (now v1.1.0) is the sole normative grammar. The v0.1.0
together β€” `deed.abnf` (now v1.2.0) is the sole normative grammar. The v0.1.0
DRAFT archive lives at `archive/deed.abnf_v0.1.0-draft` under its true
version (it was previously misnamed `deed.abnf_v1.0`).

Expand All @@ -41,6 +41,12 @@ Compatible with:
|===
| Version | Date | Changes

| 0.2.3
| 2026-10-16
| Aligned to `deed.abnf` v1.2.0: the exact canonical machine front door
`0-AI-MANIFEST.deed` dispatches to `repo-deed`. Other filename rules
and clause syntax are unchanged.

| 0.2.2
| 2026-10-07
| Aligned to `deed.abnf` v1.1.0 (owner rulings D305/D320): added the
Expand Down Expand Up @@ -317,6 +323,10 @@ case-sensitive.
| `repo-deed`
| Noun. What a repo IS. A record.

| `0-AI-MANIFEST.deed` (exact)
| `repo-deed`
| The canonical machine front door, recording repository routing and invariants.

| `ATLAS.deed` (exact)
| `estate-atlas-deed`
| Noun. The registry of all deeds.
Expand All @@ -338,6 +348,8 @@ implementation MUST test the exact name `estate_chora.deed` BEFORE the
`*_chora.deed` pattern, and MUST NOT parse `estate_chora.deed` as a
`repo-deed`. Equivalently, the repo form is `<prefix>_chora.deed` where
`<prefix>` is any non-empty stem other than the exact string `estate`.
The exact `0-AI-MANIFEST.deed` name also selects `repo-deed`; other plain
`.deed` names remain invalid.

[NOTE]
====
Expand Down Expand Up @@ -899,7 +911,7 @@ locally. Either the estate chora gains it, or `extends-vocabulary` lands.

== References

* link:./abnf/deed.abnf[DEED ABNF (v1.1.0, normative)] Β·
* link:./abnf/deed.abnf[DEED ABNF (v1.2.0, normative)] Β·
link:./abnf/archive/deed.abnf_v0.1.0-draft[v0.1.0 DRAFT archive]
* link:https://www.rfc-editor.org/rfc/rfc7405[RFC 7405] (case-sensitive ABNF strings)
* link:https://www.rfc-editor.org/rfc/rfc4122[RFC 4122] Β§4.3 (UUID v5)
Expand Down
10 changes: 8 additions & 2 deletions 1-formats/deed/spec/abnf/deed.abnf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
; SPDX-License-Identifier: MPL-2.0
; SPDX-License-Identifier: CC-BY-SA-4.0
;
; DEED grammar, v1.1.0
; DEED grammar, v1.2.0
; Normative for parsing. Prose and rationale: ../DEED-GRAMMAR-SPEC.adoc
;
; NOTICE (standards#837): OWNER RULING 2026-09-19 β€” the grammar files have
Expand All @@ -17,6 +17,10 @@
; The only bracket is "(". A file using "=" as a field separator is not a deed.
; ("=" MAY appear INSIDE a symbol, e.g., a comparison operator.)
;
; CHANGELOG (v1.1.0 β†’ v1.2.0, 2026-10-16):
; - Added exact filename 0-AI-MANIFEST.deed -> repo-deed for the canonical
; machine front door. Existing filename dispatch and clause syntax remain.
;
; CHANGELOG (v1.0.0 β†’ v1.1.0, owner rulings D305/D320, 2026-10-07):
; - Added uuid8 (#u8"domain:name"), the ADR-008 profile C literal. Additive:
; uuid5 stays legal until its own cutover, so every v1.0.0 deed is a v1.1.0 deed.
Expand Down Expand Up @@ -54,6 +58,7 @@ doc-head = %s"estate-deed"
; filename dispatch (see deed-filename below).
; estate_chora.deed β†’ estate-deed
; ATLAS.deed β†’ estate-atlas-deed
; 0-AI-MANIFEST.deed β†’ repo-deed
; *_praxis.deed β†’ praxis-deed
; *_chora.deed β†’ repo-deed
; A mismatch is a validation error.
Expand All @@ -66,9 +71,10 @@ doc-head = %s"estate-deed"
; ("_chora.deed", "_praxis.deed", etc.). Do NOT split on "." β€” the
; stem may contain dots (e.g., "my.project_chora.deed" β†’ stem "my.project").

deed-filename = estate-file / atlas-file / praxis-file / repo-file
deed-filename = estate-file / atlas-file / manifest-file / praxis-file / repo-file
estate-file = %s"estate_chora.deed" ; -> estate-deed
atlas-file = %s"ATLAS.deed" ; -> estate-atlas-deed
manifest-file = %s"0-AI-MANIFEST.deed" ; -> repo-deed
praxis-file = stem %s"_praxis.deed" ; -> praxis-deed
repo-file = stem %s"_chora.deed" ; -> repo-deed
stem = 1*( ALPHA / DIGIT / "-" / "." / "_" )
Expand Down
2 changes: 1 addition & 1 deletion 1-formats/deed/tools/README.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: CC-BY-SA-4.0
= DEED conformance lane β€” tools
Campaign: standards#837 Β· Grammar: link:../spec/abnf/deed.abnf[spec/abnf/deed.abnf (v1.1.0, normative)]
Campaign: standards#837 Β· Grammar: link:../spec/abnf/deed.abnf[spec/abnf/deed.abnf (v1.2.0, normative)]

== The lane's one property

Expand Down
18 changes: 15 additions & 3 deletions 1-formats/deed/tools/deed_lint.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bun
// SPDX-License-Identifier: MPL-2.0
// Port of deed_lint.py to plain JavaScript (bun, zero dependencies).
const DOC = String.raw`deed-lint β€” conformance validator for the DEED grammar (deed.abnf v1.1.0).
const DOC = String.raw`deed-lint β€” conformance validator for the DEED grammar (deed.abnf v1.2.0).

Stdlib-only. Implements the normative grammar faithfully:
* header = 1* spdx-line (";;" SP "SPDX-" …)
Expand Down Expand Up @@ -410,14 +410,26 @@ export function validate(text, filename = null) {
return [head, items];
}

/** estate-file exact-first; stems may contain dots (split on the final suffix). */
/**
* Check a parsed doc-head against the case-sensitive basename of `filename`.
* Exact names take precedence: estate_chora.deed requires estate-deed,
* ATLAS.deed requires estate-atlas-deed, and 0-AI-MANIFEST.deed requires
* repo-deed. Otherwise, _praxis.deed selects praxis-deed and _chora.deed
* selects repo-deed; stems may contain dots (split on the final suffix).
* Returns undefined on success.
* @throws {LintError} At line 1 for an unrecognised filename, an empty or
* illegal _chora.deed stem (only ASCII letters, digits, hyphens, dots and
* underscores are allowed), or a doc-head mismatch.
*/
export function checkFilenameDispatch(filename, head) {
const base = basename(filename);
let want;
if (base === "estate_chora.deed") {
want = "estate-deed";
} else if (base === "ATLAS.deed") {
want = "estate-atlas-deed";
} else if (base === "0-AI-MANIFEST.deed") {
want = "repo-deed";
} else if (base.endsWith("_praxis.deed")) {
want = "praxis-deed";
} else if (base.endsWith("_chora.deed")) {
Expand All @@ -428,7 +440,7 @@ export function checkFilenameDispatch(filename, head) {
} else {
throw new LintError(
`filename ${pyRepr(base)} matches no deed dispatch pattern ` +
"(estate_chora.deed | ATLAS.deed | <stem>_chora.deed | <stem>_praxis.deed)",
"(estate_chora.deed | ATLAS.deed | 0-AI-MANIFEST.deed | <stem>_chora.deed | <stem>_praxis.deed)",
1,
);
}
Expand Down
20 changes: 20 additions & 0 deletions 1-formats/deed/tools/deed_lint.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,20 @@ describe("extra rules", () => {
test("filename matching no pattern", () => {
expect(verdict(HDR + '(repo-deed :schema-version "1")\n', "x.deed")).toMatch(/no deed dispatch pattern/);
});
test("canonical machine manifest selects repo-deed", () => {
expect(verdict(HDR + '(repo-deed :schema-version "1")\n', "0-AI-MANIFEST.deed")).toBeNull();
for (const head of ["estate-deed", "estate-atlas-deed", "praxis-deed"]) {
expect(verdict(HDR + `(${head} :schema-version "1")\n`, "0-AI-MANIFEST.deed")).toMatch(/mismatch/);
}
});
test("machine manifest filename is exact and case-sensitive", () => {
for (const name of ["0-ai-manifest.deed", "0-AI-MANIFEST-copy.deed", "1-AI-MANIFEST.deed"]) {
expect(verdict(HDR + '(repo-deed :schema-version "1")\n', name)).toMatch(/no deed dispatch pattern/);
}
});
test("machine manifest clauses still require named fields", () => {
expect(verdict(HDR + '(repo-deed :schema-version "1" (purpose "text"))\n', "0-AI-MANIFEST.deed")).toMatch(/expected field/);
});
test("estate_chora.deed needs estate-deed", () => {
expect(verdict(HDR + '(estate-deed :schema-version "1")\n', "estate_chora.deed")).toBeNull();
expect(verdict(HDR + '(repo-deed :schema-version "1")\n', "estate_chora.deed")).toMatch(/mismatch/);
Expand Down Expand Up @@ -157,6 +171,12 @@ function cli(...args) {
}

describe("CLI", () => {
test("canonical machine manifest passes with its real filename", () => {
const manifest = join(HERE, "../../../0-AI-MANIFEST.deed");
const r = cli(manifest);
expect(r.code).toBe(0);
expect(r.out).toContain(`OK ${manifest}`);
});
test("valid fixture exits 0", () => {
const p = join(FIX, "valid", "minimal_chora.deed");
const r = cli(p);
Expand Down
Loading
Loading