@leji-org/leji 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -0
- package/assets-manifest.json +25 -0
- package/cli.json +82 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/conformance.d.ts +24 -0
- package/dist/commands/conformance.js +111 -0
- package/dist/commands/conformance.js.map +1 -0
- package/dist/commands/docs.d.ts +32 -0
- package/dist/commands/docs.js +196 -0
- package/dist/commands/docs.js.map +1 -0
- package/dist/commands/freshness.d.ts +21 -0
- package/dist/commands/freshness.js +41 -0
- package/dist/commands/freshness.js.map +1 -0
- package/dist/commands/indexgen.d.ts +55 -0
- package/dist/commands/indexgen.js +256 -0
- package/dist/commands/indexgen.js.map +1 -0
- package/dist/commands/init.d.ts +28 -0
- package/dist/commands/init.js +378 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/validate.d.ts +25 -0
- package/dist/commands/validate.js +359 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +324 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/findings.d.ts +17 -0
- package/dist/lib/findings.js +29 -0
- package/dist/lib/findings.js.map +1 -0
- package/dist/lib/frontmatter.d.ts +14 -0
- package/dist/lib/frontmatter.js +28 -0
- package/dist/lib/frontmatter.js.map +1 -0
- package/dist/lib/fsx.d.ts +21 -0
- package/dist/lib/fsx.js +100 -0
- package/dist/lib/fsx.js.map +1 -0
- package/dist/lib/git.d.ts +10 -0
- package/dist/lib/git.js +55 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/layer.d.ts +32 -0
- package/dist/lib/layer.js +138 -0
- package/dist/lib/layer.js.map +1 -0
- package/dist/lib/manifest.d.ts +62 -0
- package/dist/lib/manifest.js +54 -0
- package/dist/lib/manifest.js.map +1 -0
- package/dist/lib/schemas.d.ts +38 -0
- package/dist/lib/schemas.js +57 -0
- package/dist/lib/schemas.js.map +1 -0
- package/package.json +61 -0
- package/schemas/README.md +3 -0
- package/schemas/agent-profile.schema.json +129 -0
- package/schemas/context-changelog.schema.json +150 -0
- package/schemas/context-index.schema.json +137 -0
- package/schemas/context-manifest.schema.json +253 -0
- package/schemas/decision-record.schema.json +84 -0
- package/templates/README.md +5 -0
- package/templates/agent-profile.md +25 -0
- package/templates/agents/core.md +27 -0
- package/templates/boot-profile.md +39 -0
- package/templates/decision-record.md +28 -0
- package/templates/docs-viewer-assets/PROVENANCE.txt +18 -0
- package/templates/docs-viewer-assets/docsify-sidebar-collapse.min.css +24 -0
- package/templates/docs-viewer-assets/docsify-sidebar-collapse.min.js +149 -0
- package/templates/docs-viewer-assets/docsify.min.js +1 -0
- package/templates/docs-viewer-assets/search.min.js +314 -0
- package/templates/docs-viewer-assets/vue.css +1063 -0
- package/templates/docs-viewer.html +63 -0
- package/templates/leji.json +56 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://leji.org/schemas/v1.0/context-changelog.schema.json",
|
|
4
|
+
"title": "Leji context changelog",
|
|
5
|
+
"description": "Append-only machine-readable record of context layer changes.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"schemaVersion",
|
|
9
|
+
"entries"
|
|
10
|
+
],
|
|
11
|
+
"additionalProperties": false,
|
|
12
|
+
"properties": {
|
|
13
|
+
"$schema": {
|
|
14
|
+
"description": "Optional pointer to this schema, for editor validation and tooling.",
|
|
15
|
+
"type": "string"
|
|
16
|
+
},
|
|
17
|
+
"schemaVersion": {
|
|
18
|
+
"description": "The Leji spec line this artifact was written against, e.g. \"1.0\".",
|
|
19
|
+
"type": "string",
|
|
20
|
+
"pattern": "^\\d+\\.\\d+$"
|
|
21
|
+
},
|
|
22
|
+
"entries": {
|
|
23
|
+
"description": "Context layer changes. Canonical order is derived by sorting on (date, id) ascending; array position is not significant. New entries may appear anywhere; the oldest may be compacted with a compaction entry.",
|
|
24
|
+
"type": "array",
|
|
25
|
+
"items": {
|
|
26
|
+
"type": "object",
|
|
27
|
+
"required": [
|
|
28
|
+
"id",
|
|
29
|
+
"date",
|
|
30
|
+
"type",
|
|
31
|
+
"summary",
|
|
32
|
+
"paths"
|
|
33
|
+
],
|
|
34
|
+
"additionalProperties": false,
|
|
35
|
+
"properties": {
|
|
36
|
+
"id": {
|
|
37
|
+
"description": "Stable identifier for this change entry, unique within the changelog.",
|
|
38
|
+
"type": "string",
|
|
39
|
+
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
|
|
40
|
+
},
|
|
41
|
+
"date": {
|
|
42
|
+
"description": "ISO 8601 in UTC: a calendar date YYYY-MM-DD (ordered as start of day) or a full timestamp ending in Z, e.g. 2026-06-13T15:04:05Z. Offsets and zoneless times are not allowed, so lexical order is chronological.",
|
|
43
|
+
"type": "string",
|
|
44
|
+
"pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,9})?Z)?$"
|
|
45
|
+
},
|
|
46
|
+
"type": {
|
|
47
|
+
"description": "The kind of change.",
|
|
48
|
+
"enum": [
|
|
49
|
+
"added",
|
|
50
|
+
"changed",
|
|
51
|
+
"deprecated",
|
|
52
|
+
"removed",
|
|
53
|
+
"fixed",
|
|
54
|
+
"decision",
|
|
55
|
+
"governance",
|
|
56
|
+
"compaction"
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
"summary": {
|
|
60
|
+
"description": "One-line description of what changed.",
|
|
61
|
+
"type": "string",
|
|
62
|
+
"minLength": 1
|
|
63
|
+
},
|
|
64
|
+
"paths": {
|
|
65
|
+
"description": "Repository-root-relative paths the change affected.",
|
|
66
|
+
"type": "array",
|
|
67
|
+
"items": {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"pattern": "^(?!/)(?!\\./)(?!.*(^|/)\\.\\.(/|$))(?!.*\\\\).+$"
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"categories": {
|
|
73
|
+
"description": "Content categories the change touched.",
|
|
74
|
+
"type": "array",
|
|
75
|
+
"items": {
|
|
76
|
+
"enum": [
|
|
77
|
+
"domain",
|
|
78
|
+
"system",
|
|
79
|
+
"practice",
|
|
80
|
+
"governance",
|
|
81
|
+
"decisions"
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"decisionRefs": {
|
|
86
|
+
"description": "Ids of decision records related to this change.",
|
|
87
|
+
"type": "array",
|
|
88
|
+
"items": {
|
|
89
|
+
"type": "string"
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"proposedBy": {
|
|
93
|
+
"type": "string",
|
|
94
|
+
"description": "Human or agent that proposed the change."
|
|
95
|
+
},
|
|
96
|
+
"approvedBy": {
|
|
97
|
+
"type": "string",
|
|
98
|
+
"description": "Human who approved the change."
|
|
99
|
+
},
|
|
100
|
+
"breaking": {
|
|
101
|
+
"description": "Whether the change breaks consumers of the context layer.",
|
|
102
|
+
"type": "boolean"
|
|
103
|
+
},
|
|
104
|
+
"compacted": {
|
|
105
|
+
"type": "object",
|
|
106
|
+
"description": "Required on compaction entries: what the compaction removed from the oldest end.",
|
|
107
|
+
"required": [
|
|
108
|
+
"entries",
|
|
109
|
+
"firstId",
|
|
110
|
+
"lastId"
|
|
111
|
+
],
|
|
112
|
+
"additionalProperties": false,
|
|
113
|
+
"properties": {
|
|
114
|
+
"entries": {
|
|
115
|
+
"description": "How many entries this compaction removed from the oldest end.",
|
|
116
|
+
"type": "integer",
|
|
117
|
+
"minimum": 1
|
|
118
|
+
},
|
|
119
|
+
"firstId": {
|
|
120
|
+
"description": "Id of the oldest entry removed by this compaction.",
|
|
121
|
+
"type": "string",
|
|
122
|
+
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
|
|
123
|
+
},
|
|
124
|
+
"lastId": {
|
|
125
|
+
"description": "Id of the newest entry removed by this compaction.",
|
|
126
|
+
"type": "string",
|
|
127
|
+
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
"if": {
|
|
133
|
+
"properties": {
|
|
134
|
+
"type": {
|
|
135
|
+
"const": "compaction"
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
"required": [
|
|
139
|
+
"type"
|
|
140
|
+
]
|
|
141
|
+
},
|
|
142
|
+
"then": {
|
|
143
|
+
"required": [
|
|
144
|
+
"compacted"
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://leji.org/schemas/v1.0/context-index.schema.json",
|
|
4
|
+
"title": "Leji context index",
|
|
5
|
+
"description": "Generated map of the context layer. Never hand-maintained; regenerate on change.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"schemaVersion",
|
|
9
|
+
"generatedAt",
|
|
10
|
+
"rootPath",
|
|
11
|
+
"entries"
|
|
12
|
+
],
|
|
13
|
+
"additionalProperties": false,
|
|
14
|
+
"properties": {
|
|
15
|
+
"$schema": {
|
|
16
|
+
"description": "Optional pointer to this schema, for editor validation and tooling.",
|
|
17
|
+
"type": "string"
|
|
18
|
+
},
|
|
19
|
+
"schemaVersion": {
|
|
20
|
+
"description": "The Leji spec line this artifact was written against, e.g. \"1.0\".",
|
|
21
|
+
"type": "string",
|
|
22
|
+
"pattern": "^\\d+\\.\\d+$"
|
|
23
|
+
},
|
|
24
|
+
"generatedAt": {
|
|
25
|
+
"description": "ISO 8601 timestamp when the index was generated.",
|
|
26
|
+
"type": "string",
|
|
27
|
+
"pattern": "^\\d{4}-\\d{2}-\\d{2}[T ].+$"
|
|
28
|
+
},
|
|
29
|
+
"generator": {
|
|
30
|
+
"description": "The tool that generated this index.",
|
|
31
|
+
"type": "object",
|
|
32
|
+
"additionalProperties": false,
|
|
33
|
+
"properties": {
|
|
34
|
+
"name": {
|
|
35
|
+
"description": "Name of the generating tool, e.g. \"leji\".",
|
|
36
|
+
"type": "string"
|
|
37
|
+
},
|
|
38
|
+
"version": {
|
|
39
|
+
"description": "Version of the generating tool.",
|
|
40
|
+
"type": "string"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"rootPath": {
|
|
45
|
+
"description": "Context root the entries are relative to; mirrors the manifest's rootPath.",
|
|
46
|
+
"type": "string",
|
|
47
|
+
"pattern": "^(?!/)(?!\\./)(?!.*(^|/)\\.\\.(/|$))(?!.*\\\\).*$"
|
|
48
|
+
},
|
|
49
|
+
"entries": {
|
|
50
|
+
"description": "One entry per indexed document in the context layer.",
|
|
51
|
+
"type": "array",
|
|
52
|
+
"items": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"required": [
|
|
55
|
+
"id",
|
|
56
|
+
"path",
|
|
57
|
+
"title",
|
|
58
|
+
"category"
|
|
59
|
+
],
|
|
60
|
+
"additionalProperties": false,
|
|
61
|
+
"properties": {
|
|
62
|
+
"id": {
|
|
63
|
+
"description": "Stable identifier; renames and moves update the path, never the id.",
|
|
64
|
+
"type": "string",
|
|
65
|
+
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
|
|
66
|
+
},
|
|
67
|
+
"path": {
|
|
68
|
+
"description": "Repository-root-relative path to the document.",
|
|
69
|
+
"type": "string",
|
|
70
|
+
"pattern": "^(?!/)(?!\\./)(?!.*(^|/)\\.\\.(/|$))(?!.*\\\\).+$"
|
|
71
|
+
},
|
|
72
|
+
"title": {
|
|
73
|
+
"description": "Human-readable title, from the document's first heading or frontmatter.",
|
|
74
|
+
"type": "string",
|
|
75
|
+
"minLength": 1
|
|
76
|
+
},
|
|
77
|
+
"category": {
|
|
78
|
+
"description": "Which content category this document belongs to.",
|
|
79
|
+
"enum": [
|
|
80
|
+
"domain",
|
|
81
|
+
"system",
|
|
82
|
+
"practice",
|
|
83
|
+
"governance",
|
|
84
|
+
"decisions"
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
"summary": {
|
|
88
|
+
"description": "One-line summary of the document, for routing and navigation.",
|
|
89
|
+
"type": "string"
|
|
90
|
+
},
|
|
91
|
+
"tags": {
|
|
92
|
+
"description": "Optional free-form tags.",
|
|
93
|
+
"type": "array",
|
|
94
|
+
"items": {
|
|
95
|
+
"type": "string"
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"owners": {
|
|
99
|
+
"description": "Optional owners of this document.",
|
|
100
|
+
"type": "array",
|
|
101
|
+
"items": {
|
|
102
|
+
"type": "string"
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
"lastModified": {
|
|
106
|
+
"description": "ISO 8601 date the document last changed, from version control where available.",
|
|
107
|
+
"type": "string",
|
|
108
|
+
"pattern": "^\\d{4}-\\d{2}-\\d{2}([T ].*)?$"
|
|
109
|
+
},
|
|
110
|
+
"contentHash": {
|
|
111
|
+
"description": "Hash of the document's contents, used to detect drift and stable moves.",
|
|
112
|
+
"type": "string"
|
|
113
|
+
},
|
|
114
|
+
"freshness": {
|
|
115
|
+
"description": "Review horizon for this document.",
|
|
116
|
+
"type": "object",
|
|
117
|
+
"additionalProperties": false,
|
|
118
|
+
"properties": {
|
|
119
|
+
"reviewAfter": {
|
|
120
|
+
"description": "ISO 8601 date after which the document should be reviewed for staleness.",
|
|
121
|
+
"type": "string",
|
|
122
|
+
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"links": {
|
|
127
|
+
"description": "Optional outbound references from this document.",
|
|
128
|
+
"type": "array",
|
|
129
|
+
"items": {
|
|
130
|
+
"type": "string"
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://leji.org/schemas/v1.0/context-manifest.schema.json",
|
|
4
|
+
"title": "Leji context manifest (leji.json)",
|
|
5
|
+
"description": "The machine entrypoint of a Leji context layer. Lives at the repository root as leji.json.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"leji",
|
|
9
|
+
"name",
|
|
10
|
+
"rootPath",
|
|
11
|
+
"bootProfilePath",
|
|
12
|
+
"categories",
|
|
13
|
+
"owners"
|
|
14
|
+
],
|
|
15
|
+
"additionalProperties": false,
|
|
16
|
+
"properties": {
|
|
17
|
+
"$schema": {
|
|
18
|
+
"description": "Optional pointer to this schema, for editor validation and tooling.",
|
|
19
|
+
"type": "string"
|
|
20
|
+
},
|
|
21
|
+
"leji": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"description": "The Leji spec line this context layer targets, e.g. \"1.0\". The self-naming key follows the OpenAPI convention and identifies the file as a Leji manifest.",
|
|
24
|
+
"pattern": "^\\d+\\.\\d+$"
|
|
25
|
+
},
|
|
26
|
+
"name": {
|
|
27
|
+
"description": "A short, stable identifier for this context layer, e.g. \"acme-billing-context\".",
|
|
28
|
+
"type": "string",
|
|
29
|
+
"minLength": 1
|
|
30
|
+
},
|
|
31
|
+
"description": {
|
|
32
|
+
"description": "One-line summary of what this context layer covers.",
|
|
33
|
+
"type": "string"
|
|
34
|
+
},
|
|
35
|
+
"rootPath": {
|
|
36
|
+
"type": "string",
|
|
37
|
+
"description": "Context root, POSIX path relative to the repository root. Declares where the context layer lives; it does not re-base other paths: all paths in all Leji artifacts resolve from the repository root.",
|
|
38
|
+
"pattern": "^(?!/)(?!\\./)(?!.*(^|/)\\.\\.(/|$))(?!.*\\\\).*$"
|
|
39
|
+
},
|
|
40
|
+
"bootProfilePath": {
|
|
41
|
+
"description": "Path to the boot profile, the agent-agnostic entrypoint every host and person starts from.",
|
|
42
|
+
"type": "string",
|
|
43
|
+
"pattern": "^(?!/)(?!\\./)(?!.*(^|/)\\.\\.(/|$))(?!.*\\\\).+\\.md$"
|
|
44
|
+
},
|
|
45
|
+
"categories": {
|
|
46
|
+
"type": "object",
|
|
47
|
+
"description": "Logical category to path mapping. Keys are the five category identifiers.",
|
|
48
|
+
"additionalProperties": false,
|
|
49
|
+
"minProperties": 1,
|
|
50
|
+
"properties": {
|
|
51
|
+
"domain": {
|
|
52
|
+
"description": "Where domain content lives: business language and product semantics.",
|
|
53
|
+
"$ref": "#/$defs/categoryMapping"
|
|
54
|
+
},
|
|
55
|
+
"system": {
|
|
56
|
+
"description": "Where system content lives: architecture and the invariants every change respects.",
|
|
57
|
+
"$ref": "#/$defs/categoryMapping"
|
|
58
|
+
},
|
|
59
|
+
"practice": {
|
|
60
|
+
"description": "Where practice content lives: conventions and proven patterns.",
|
|
61
|
+
"$ref": "#/$defs/categoryMapping"
|
|
62
|
+
},
|
|
63
|
+
"governance": {
|
|
64
|
+
"description": "Where governance content lives: agent guardrails and operating rules.",
|
|
65
|
+
"$ref": "#/$defs/categoryMapping"
|
|
66
|
+
},
|
|
67
|
+
"decisions": {
|
|
68
|
+
"description": "Where decision records live: dated records of why things are the way they are.",
|
|
69
|
+
"$ref": "#/$defs/categoryMapping"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"machine": {
|
|
74
|
+
"description": "Locations of the machine-readable artifacts: index, changelog, profiles, and decision records.",
|
|
75
|
+
"type": "object",
|
|
76
|
+
"additionalProperties": false,
|
|
77
|
+
"properties": {
|
|
78
|
+
"indexPath": {
|
|
79
|
+
"description": "Path to the generated context index.",
|
|
80
|
+
"$ref": "#/$defs/relPath"
|
|
81
|
+
},
|
|
82
|
+
"changelogPath": {
|
|
83
|
+
"description": "Path to the machine-readable context changelog.",
|
|
84
|
+
"$ref": "#/$defs/relPath"
|
|
85
|
+
},
|
|
86
|
+
"agentProfilesPath": {
|
|
87
|
+
"description": "Directory holding agent profile documents.",
|
|
88
|
+
"$ref": "#/$defs/relPath"
|
|
89
|
+
},
|
|
90
|
+
"decisionRecordsPath": {
|
|
91
|
+
"description": "Directory holding decision records.",
|
|
92
|
+
"$ref": "#/$defs/relPath"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"agents": {
|
|
97
|
+
"type": "object",
|
|
98
|
+
"description": "Role to agent-profile binding. Keys are role identifiers (e.g. \"thought-partner\", \"reviewer\"); values are paths to agent profile documents. Protocols engage roles; this map decides who fills them.",
|
|
99
|
+
"additionalProperties": false,
|
|
100
|
+
"patternProperties": {
|
|
101
|
+
"^[a-z0-9]+(-[a-z0-9]+)*$": {
|
|
102
|
+
"$ref": "#/$defs/relPath"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"owners": {
|
|
107
|
+
"type": "object",
|
|
108
|
+
"description": "Who is accountable for the context layer's health. Owners answer for the context layer staying current and pruned; they do not author or curate it alone (governance.md).",
|
|
109
|
+
"required": [
|
|
110
|
+
"primary"
|
|
111
|
+
],
|
|
112
|
+
"additionalProperties": false,
|
|
113
|
+
"properties": {
|
|
114
|
+
"primary": {
|
|
115
|
+
"$ref": "#/$defs/owner",
|
|
116
|
+
"description": "The person accountable for the context layer's currency. Ownerless context layers rot."
|
|
117
|
+
},
|
|
118
|
+
"continuity": {
|
|
119
|
+
"$ref": "#/$defs/owner",
|
|
120
|
+
"description": "Optional. A different person who carries the same accountability when the primary is unavailable or steps away; assisted adoptions should name one before outside help leaves. Naming the primary again provides no continuity, and an agent cannot fill it: owners are accountable people."
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
"conformance": {
|
|
125
|
+
"description": "The conformance level this context layer claims, checkable by tooling.",
|
|
126
|
+
"type": "object",
|
|
127
|
+
"additionalProperties": false,
|
|
128
|
+
"properties": {
|
|
129
|
+
"claimedLevel": {
|
|
130
|
+
"description": "The conformance level claimed: core, indexed, governed, or federated.",
|
|
131
|
+
"enum": [
|
|
132
|
+
"core",
|
|
133
|
+
"indexed",
|
|
134
|
+
"governed",
|
|
135
|
+
"federated"
|
|
136
|
+
]
|
|
137
|
+
},
|
|
138
|
+
"claimedAt": {
|
|
139
|
+
"description": "ISO 8601 date the claim was last asserted.",
|
|
140
|
+
"$ref": "#/$defs/isoDate"
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
"federation": {
|
|
145
|
+
"type": "object",
|
|
146
|
+
"additionalProperties": false,
|
|
147
|
+
"properties": {
|
|
148
|
+
"mounts": {
|
|
149
|
+
"type": "array",
|
|
150
|
+
"items": {
|
|
151
|
+
"type": "object",
|
|
152
|
+
"required": [
|
|
153
|
+
"path",
|
|
154
|
+
"name",
|
|
155
|
+
"owner"
|
|
156
|
+
],
|
|
157
|
+
"additionalProperties": false,
|
|
158
|
+
"properties": {
|
|
159
|
+
"path": {
|
|
160
|
+
"$ref": "#/$defs/relPath",
|
|
161
|
+
"description": "Where the sibling layer is mounted in this repository, e.g. \"context/product/\". The sibling's own leji.json lives at this path's root."
|
|
162
|
+
},
|
|
163
|
+
"name": {
|
|
164
|
+
"type": "string",
|
|
165
|
+
"minLength": 1,
|
|
166
|
+
"description": "The sibling layer's name; must match the `name` in the sibling's own manifest."
|
|
167
|
+
},
|
|
168
|
+
"owner": {
|
|
169
|
+
"$ref": "#/$defs/owner",
|
|
170
|
+
"description": "The owner of the sibling layer. Ownership stays with the sibling's team; the host never absorbs its content."
|
|
171
|
+
},
|
|
172
|
+
"role": {
|
|
173
|
+
"type": "string",
|
|
174
|
+
"description": "What this sibling layer carries, e.g. \"product-side context\"."
|
|
175
|
+
},
|
|
176
|
+
"source": {
|
|
177
|
+
"type": "string",
|
|
178
|
+
"description": "Upstream repository URL of the sibling layer. Optional; enables stale-pin reporting when git submodule metadata alone isn't available."
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
"description": "Each mount is a docs-only sibling layer at a pinned version, keeping its own repository, ownership, and review gate."
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
"description": "Sibling layers mounted into this repository (spec: distribution.md pattern 3). The circle composes ownership; it doesn't centralize it."
|
|
186
|
+
},
|
|
187
|
+
"vendorAdapters": {
|
|
188
|
+
"type": "array",
|
|
189
|
+
"description": "Vendor entrypoint files present in this repository; each must redirect to the boot profile.",
|
|
190
|
+
"items": {
|
|
191
|
+
"$ref": "#/$defs/relPath"
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
"docs": {
|
|
195
|
+
"type": "object",
|
|
196
|
+
"description": "Presentation preferences read by `leji docs`. Non-normative convenience configuration; presentation itself is out of normative scope.",
|
|
197
|
+
"additionalProperties": false,
|
|
198
|
+
"properties": {
|
|
199
|
+
"port": {
|
|
200
|
+
"type": "integer",
|
|
201
|
+
"minimum": 1,
|
|
202
|
+
"maximum": 65535,
|
|
203
|
+
"description": "Preferred local-preview port for `leji docs --serve`. The --port flag overrides; the default is 5354 (LEJI on a phone keypad)."
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
"$defs": {
|
|
209
|
+
"relPath": {
|
|
210
|
+
"type": "string",
|
|
211
|
+
"pattern": "^(?!/)(?!\\./)(?!.*(^|/)\\.\\.(/|$))(?!.*\\\\).+$"
|
|
212
|
+
},
|
|
213
|
+
"isoDate": {
|
|
214
|
+
"type": "string",
|
|
215
|
+
"pattern": "^\\d{4}-\\d{2}-\\d{2}([T ].*)?$"
|
|
216
|
+
},
|
|
217
|
+
"owner": {
|
|
218
|
+
"type": "object",
|
|
219
|
+
"required": [
|
|
220
|
+
"name"
|
|
221
|
+
],
|
|
222
|
+
"additionalProperties": false,
|
|
223
|
+
"properties": {
|
|
224
|
+
"name": {
|
|
225
|
+
"description": "The person's name.",
|
|
226
|
+
"type": "string",
|
|
227
|
+
"minLength": 1
|
|
228
|
+
},
|
|
229
|
+
"contact": {
|
|
230
|
+
"description": "How to reach them, e.g. an email address.",
|
|
231
|
+
"type": "string"
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
"categoryMapping": {
|
|
236
|
+
"type": "object",
|
|
237
|
+
"required": [
|
|
238
|
+
"paths"
|
|
239
|
+
],
|
|
240
|
+
"additionalProperties": false,
|
|
241
|
+
"properties": {
|
|
242
|
+
"paths": {
|
|
243
|
+
"description": "One or more repository-root-relative paths where this category's content lives.",
|
|
244
|
+
"type": "array",
|
|
245
|
+
"minItems": 1,
|
|
246
|
+
"items": {
|
|
247
|
+
"$ref": "#/$defs/relPath"
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://leji.org/schemas/v1.0/decision-record.schema.json",
|
|
4
|
+
"title": "Leji decision record frontmatter",
|
|
5
|
+
"description": "Validates the YAML frontmatter of a decision record. The markdown body carries context, decision, and consequences in prose.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"id",
|
|
9
|
+
"title",
|
|
10
|
+
"status",
|
|
11
|
+
"date"
|
|
12
|
+
],
|
|
13
|
+
"additionalProperties": false,
|
|
14
|
+
"properties": {
|
|
15
|
+
"id": {
|
|
16
|
+
"description": "Stable identifier for this decision, e.g. \"adopt-leji\".",
|
|
17
|
+
"type": "string",
|
|
18
|
+
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
|
|
19
|
+
},
|
|
20
|
+
"title": {
|
|
21
|
+
"description": "Short title of the decision.",
|
|
22
|
+
"type": "string",
|
|
23
|
+
"minLength": 1
|
|
24
|
+
},
|
|
25
|
+
"status": {
|
|
26
|
+
"description": "Lifecycle status of the decision.",
|
|
27
|
+
"enum": [
|
|
28
|
+
"proposed",
|
|
29
|
+
"accepted",
|
|
30
|
+
"superseded",
|
|
31
|
+
"deprecated",
|
|
32
|
+
"rejected"
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"date": {
|
|
36
|
+
"description": "ISO 8601 date the decision was made or last changed status.",
|
|
37
|
+
"type": "string",
|
|
38
|
+
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
|
|
39
|
+
},
|
|
40
|
+
"deciders": {
|
|
41
|
+
"description": "People who made the decision.",
|
|
42
|
+
"type": "array",
|
|
43
|
+
"items": {
|
|
44
|
+
"type": "string"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"supersedes": {
|
|
48
|
+
"type": "string",
|
|
49
|
+
"description": "id of the record this decision replaces."
|
|
50
|
+
},
|
|
51
|
+
"supersededBy": {
|
|
52
|
+
"type": "string",
|
|
53
|
+
"description": "id of the record that replaced this one."
|
|
54
|
+
},
|
|
55
|
+
"affectedPaths": {
|
|
56
|
+
"description": "Repository-root-relative paths the decision affects.",
|
|
57
|
+
"type": "array",
|
|
58
|
+
"items": {
|
|
59
|
+
"type": "string",
|
|
60
|
+
"pattern": "^(?!/)(?!\\./)(?!.*(^|/)\\.\\.(/|$))(?!.*\\\\).+$"
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"affectedCategories": {
|
|
64
|
+
"description": "Content categories the decision affects.",
|
|
65
|
+
"type": "array",
|
|
66
|
+
"items": {
|
|
67
|
+
"enum": [
|
|
68
|
+
"domain",
|
|
69
|
+
"system",
|
|
70
|
+
"practice",
|
|
71
|
+
"governance",
|
|
72
|
+
"decisions"
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"links": {
|
|
77
|
+
"description": "Optional outbound references, e.g. to related decisions or issues.",
|
|
78
|
+
"type": "array",
|
|
79
|
+
"items": {
|
|
80
|
+
"type": "string"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Templates
|
|
2
|
+
|
|
3
|
+
Copyable starters: manifest (leji.json), boot profile (boot-profile.md), core agent profile, role profile, decision record. Copy, fill in the placeholders, delete what you don't need. See adoption/README.md for the order.
|
|
4
|
+
|
|
5
|
+
Naming: Leji-owned files use lowercase-kebab (`docs/boot-profile.md`, `agents/core.md`); ecosystem-fixed entrypoints (`README.md`, `CLAUDE.md`, `AGENTS.md`) keep their required names.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: <role-id>
|
|
3
|
+
name: <Role name>
|
|
4
|
+
role: <role>
|
|
5
|
+
purpose: <one line>
|
|
6
|
+
# host + invocation only for agents engaged as external CLIs; omit for the resident agent
|
|
7
|
+
host: <agent host, e.g. codex>
|
|
8
|
+
invocation:
|
|
9
|
+
command: <command template with <prompt> placeholder>
|
|
10
|
+
constraints:
|
|
11
|
+
- <operational constraint worth machine-knowing>
|
|
12
|
+
inherits: core
|
|
13
|
+
requiredRead:
|
|
14
|
+
- docs/boot-profile.md
|
|
15
|
+
- <paths this role loads before any task>
|
|
16
|
+
defaultContext:
|
|
17
|
+
- system
|
|
18
|
+
- practice
|
|
19
|
+
mustAskWhen:
|
|
20
|
+
- <condition>
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
# <Role name>
|
|
24
|
+
|
|
25
|
+
<What this role does in this repository, and how its posture differs from core. Narrower than core, never looser.>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: core
|
|
3
|
+
name: Agent Core
|
|
4
|
+
role: core
|
|
5
|
+
purpose: Shared operating posture every role profile inherits.
|
|
6
|
+
requiredRead:
|
|
7
|
+
- docs/boot-profile.md
|
|
8
|
+
- docs/governance/
|
|
9
|
+
mustAskWhen:
|
|
10
|
+
- the change is destructive or hard to reverse
|
|
11
|
+
- the task touches data covered by a data-handling rule
|
|
12
|
+
- the right answer depends on a decision not yet recorded
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Agent Core
|
|
16
|
+
|
|
17
|
+
The shared posture for all agents working in this repository. Role profiles inherit this file and narrow it; they never loosen it.
|
|
18
|
+
|
|
19
|
+
## Defaults
|
|
20
|
+
|
|
21
|
+
- Read the boot profile and the relevant category before acting, not after.
|
|
22
|
+
- Derive actions from declared intent plus task context; don't re-encode intent into one-off instructions.
|
|
23
|
+
- When context is missing or wrong, propose the fix in the same change set as the work that surfaced it.
|
|
24
|
+
|
|
25
|
+
## Escalation
|
|
26
|
+
|
|
27
|
+
<Who to ask, in what channel, for what kind of question.>
|