@okfit/profiles 0.3.1 → 0.5.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/Derivation.js CHANGED
@@ -50,10 +50,23 @@ const localPartOf = (email) => {
50
50
  const local = at === -1 ? email : email.slice(0, at);
51
51
  return local.length > 0 && !/\s/.test(local) ? local : void 0;
52
52
  };
53
+ /**
54
+ * `value` without leading and trailing `-`. An index walk rather than
55
+ * `/^-+|-+$/`: the `-+$` alternative backtracks from every position of a
56
+ * long dash run (CodeQL js/polynomial-redos, okfit alert #1), and the input
57
+ * here is a git author name nobody vetted.
58
+ */
59
+ const trimDashes = (value) => {
60
+ let start = 0;
61
+ let end = value.length;
62
+ while (start < end && value.charCodeAt(start) === 45) start++;
63
+ while (end > start && value.charCodeAt(end - 1) === 45) end--;
64
+ return value.slice(start, end);
65
+ };
53
66
  /** P-13 step 3: lower-case, runs outside `[a-z0-9._-]` to `-`, leading and trailing `-` trimmed. */
54
67
  const slugOf = (name) => {
55
68
  if (name === void 0) return void 0;
56
- const slug = name.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
69
+ const slug = trimDashes(name.toLowerCase().replace(/[^a-z0-9._-]+/g, "-"));
57
70
  return slug.length > 0 ? slug : void 0;
58
71
  };
59
72
  const humanActorId = (identity, humans) => {
package/README.md CHANGED
@@ -19,7 +19,7 @@ guidance = "Exactly one Project exists and it lives at the bundle root as the pr
19
19
 
20
20
  [types.Module]
21
21
  description = "A unit of code with an owner and a boundary."
22
- guidance = "One per workspace package, plugin, website, or action. Link to the Decisions that shaped it and the Conventions it is bound by."
22
+ guidance = "One per workspace package, plugin, website, action, test harness, or config dependency. Link to the Decisions that shaped it and the Conventions it is bound by."
23
23
  required = ["resource", "kind"]
24
24
 
25
25
  [types.Module.fields.kind]
@@ -29,11 +29,20 @@ values.package = "A publishable npm package under packages/."
29
29
  values.website = "A docs or marketing site, usually RSPress."
30
30
  values.plugin = "A Claude Code or editor plugin distributed outside npm."
31
31
  values.action = "A GitHub Action."
32
+ values.harness = "A private test-only package or package group that exercises built artifacts and is never published."
33
+ values.config-dependency = "A package consumed through pnpm configDependencies rather than dependencies, loaded before the workspace resolves."
32
34
 
33
35
  [types.Module.fields.resource]
34
36
  description = "A path relative to this concept file, normally escaping the bundle, for example ../../packages/core."
35
37
  kind = "path"
36
38
 
39
+ [types.Module.fields.layer]
40
+ description = "The dependency layer this module sits in under the repository's own layering scheme, for example L2, so a reader can query every module at one layer."
41
+
42
+ [types.Module.fields.pins]
43
+ description = "Paths to the sibling Module concepts this module is exact-version-pinned alongside, one entry per sibling."
44
+ kind = "path"
45
+
37
46
  [types.Decision]
38
47
  description = "A choice made, the alternatives rejected, and why."
39
48
  guidance = "Never edit a stable Decision; deprecate it and write a new one that names it in supersedes. A Decision counts as settled only once a human has verified it."
@@ -59,6 +68,7 @@ values.cli = "A command-line interface: commands, flags, and exit codes."
59
68
  values.config = "A configuration file schema other tools read or write."
60
69
  values.wire = "A network or IPC wire format."
61
70
  values.mcp = "An MCP tool or resource surface."
71
+ values.runtime = "A runtime binding or platform capability consumers invoke rather than a shape they write: worker bindings, environment contracts, platform flags."
62
72
 
63
73
  [types.Interface.fields.resource]
64
74
  description = "A path relative to this concept file, normally escaping the bundle, for example ../../packages/core/src/index.ts."
@@ -69,6 +79,66 @@ description = "Mirrored external material kept under the references directory."
69
79
  guidance = "Only for material this repository must cite reliably even if the original moves. Every Reference declares where it came from in sources."
70
80
  required = ["sources"]
71
81
 
82
+ [types.Runbook]
83
+ description = "A repeatable operational procedure with a trigger and an observable end state."
84
+ guidance = "Write the steps in the order they are performed, not as rules. Name the trigger that starts the procedure and the observable state that means it succeeded."
85
+
86
+ [types.Runbook.fields.resource]
87
+ description = "A path relative to this concept file to the script, workflow, or config the procedure runs through, when one exists in this repository."
88
+ kind = "path"
89
+
90
+ [types.Glossary]
91
+ description = "A term this repository uses in its own sense, one term per concept."
92
+ guidance = "Define the term as this repository means it, not as the wider ecosystem means it, and say plainly where the two differ. A term earns a concept on a collision or a trap; one that merely names a Module belongs in that Module."
93
+
94
+ [types.Limitation]
95
+ description = "A known edge of a contract: something that does not work, and why that is acceptable."
96
+ guidance = "State the condition that triggers it and the observable symptom, not just the cause, and name the Interface or Module whose promise it bounds. If it is fixable and merely unfixed, say what the fix would take."
97
+
98
+ [types.Limitation.fields.bounds]
99
+ description = "The Interface or Module concept whose promise this limitation bounds."
100
+ kind = "path"
101
+
102
+ [types.DataModel]
103
+ description = "An internal source-of-truth structure that other artifacts are derived from."
104
+ guidance = "Document the shape from the maintainer's side: what an entry contains, what is derived from it, and what breaks if an entry is wrong. Distinct from Interface, which documents a promise to consumers."
105
+ required = ["resource"]
106
+
107
+ [types.DataModel.fields.resource]
108
+ description = "A path relative to this concept file, normally escaping the bundle, to the file or directory that holds the structure."
109
+ kind = "path"
110
+
111
+ [types.Gotcha]
112
+ description = "A state or result that looks like one thing and is the opposite: breakage that is transient, or success that did nothing."
113
+ guidance = "Describe what a reader sees, what they will wrongly conclude, and what is actually true, and point resource at the code or command that produces the misleading signal. Give it a staleness window, since a trap fixed upstream turns into misinformation."
114
+
115
+ [types.Gotcha.fields.resource]
116
+ description = "A path relative to this concept file to the code, script, or config that produces the misleading signal."
117
+ kind = "path"
118
+
119
+ [types.Consumer]
120
+ description = "An external application that consumes this repository and thereby scopes it."
121
+ guidance = "Name the surfaces it exercises, where the edge between the two repositories sits, and the open questions it raises, so the boundary of this repository is read from its consumers rather than inferred. Deprecate it when the consumer stops consuming."
122
+ required = ["repository"]
123
+
124
+ [types.Consumer.fields.repository]
125
+ description = "Where the consumer lives, as a URL or an owner/name pair, since it is outside this repository."
126
+
127
+ [types.Roadmap]
128
+ description = "A gate and the forward-looking work behind it, held as intent rather than as a Decision."
129
+ guidance = "List the phases and what remains in each, and give it a staleness window so queued work is re-examined instead of read as settled. Deprecate it when the gate holds and write the Decisions the work produced."
130
+
131
+ [types.Roadmap.fields.gate]
132
+ description = "The observable condition that closes this roadmap, for example a release shipped or a benchmark met."
133
+
134
+ [types.Measurement]
135
+ description = "A dated empirical result: what was measured, how, and what the numbers ruled in or out."
136
+ guidance = "Record the inputs, the method, and the numbers so a reader can judge whether they still hold, and give it a staleness window because numbers rot. A Decision links to the Measurement that justified it instead of embedding the result in its body."
137
+
138
+ [types.Measurement.fields.justifies]
139
+ description = "Paths to the Decisions this measurement supports, one entry per Decision."
140
+ kind = "path"
141
+
72
142
  [tags.architecture]
73
143
  description = "Concerns the shape of the system rather than one module."
74
144
 
@@ -83,6 +153,24 @@ description = "Concerns trust boundaries, secrets, permissions, or attack surfac
83
153
 
84
154
  [tags.performance]
85
155
  description = "Concerns speed, memory, or resource cost and the trade-offs made for them."
156
+
157
+ [tags.dx]
158
+ description = "Concerns the experience of the people and agents who author, build, and debug the code."
159
+
160
+ [tags.ci]
161
+ description = "Concerns the unattended path: what runs without a human present, and how it fails."
162
+
163
+ [tags.compat]
164
+ description = "Concerns compatibility across versions of the runtime, the package manager, or a dependency."
165
+
166
+ [tags.bundle]
167
+ description = "Concerns install weight and reachability: tree-shaking, subpath entrypoints, and dependency edges declined for their cost."
168
+
169
+ [tags.observability]
170
+ description = "Concerns how the system reports on itself: events, metrics, logs, sinks, and artifacts."
171
+
172
+ [tags.deps]
173
+ description = "Concerns how third-party dependencies are declared, pinned, and distributed."
86
174
  ```
87
175
 
88
176
  Only `concepts`, `types`, and `tags` carry real vocabulary; the literal's `extensions: {}` is `OkfitConfig`'s one required key and never appears on disk, since the codec folds unknown top-level keys into it (P-24: `fields.<k>.kind = "path"` and the `tags` table are vocabulary only — core enforces none of it yet). `Reference.required = ["sources"]` checks presence only: `sources = []` passes, and each entry's shape is core's `family-invalid` (P-23).
@@ -105,6 +193,14 @@ directories:
105
193
  conventions/ -> Convention
106
194
  interfaces/ -> Interface
107
195
  references/ -> Reference
196
+ runbooks/ -> Runbook
197
+ glossary/ -> Glossary
198
+ limitations/ -> Limitation
199
+ models/ -> DataModel
200
+ gotchas/ -> Gotcha
201
+ consumers/ -> Consumer
202
+ roadmaps/ -> Roadmap
203
+ measurements/ -> Measurement
108
204
  ```
109
205
 
110
206
  Each directory carries its own `index.md`. What `okfit init` writes into these files is the CLI plan's concern, not this package's.
@@ -22,7 +22,7 @@ const config = {
22
22
  },
23
23
  Module: {
24
24
  description: "A unit of code with an owner and a boundary.",
25
- guidance: "One per workspace package, plugin, website, or action. Link to the Decisions that shaped it and the Conventions it is bound by.",
25
+ guidance: "One per workspace package, plugin, website, action, test harness, or config dependency. Link to the Decisions that shaped it and the Conventions it is bound by.",
26
26
  required: ["resource", "kind"],
27
27
  fields: {
28
28
  kind: {
@@ -32,12 +32,19 @@ const config = {
32
32
  package: "A publishable npm package under packages/.",
33
33
  website: "A docs or marketing site, usually RSPress.",
34
34
  plugin: "A Claude Code or editor plugin distributed outside npm.",
35
- action: "A GitHub Action."
35
+ action: "A GitHub Action.",
36
+ harness: "A private test-only package or package group that exercises built artifacts and is never published.",
37
+ "config-dependency": "A package consumed through pnpm configDependencies rather than dependencies, loaded before the workspace resolves."
36
38
  }
37
39
  },
38
40
  resource: {
39
41
  description: "A path relative to this concept file, normally escaping the bundle, for example ../../packages/core.",
40
42
  kind: "path"
43
+ },
44
+ layer: { description: "The dependency layer this module sits in under the repository's own layering scheme, for example L2, so a reader can query every module at one layer." },
45
+ pins: {
46
+ description: "Paths to the sibling Module concepts this module is exact-version-pinned alongside, one entry per sibling.",
47
+ kind: "path"
41
48
  }
42
49
  }
43
50
  },
@@ -66,7 +73,8 @@ const config = {
66
73
  cli: "A command-line interface: commands, flags, and exit codes.",
67
74
  config: "A configuration file schema other tools read or write.",
68
75
  wire: "A network or IPC wire format.",
69
- mcp: "An MCP tool or resource surface."
76
+ mcp: "An MCP tool or resource surface.",
77
+ runtime: "A runtime binding or platform capability consumers invoke rather than a shape they write: worker bindings, environment contracts, platform flags."
70
78
  }
71
79
  },
72
80
  resource: {
@@ -79,6 +87,62 @@ const config = {
79
87
  description: "Mirrored external material kept under the references directory.",
80
88
  guidance: "Only for material this repository must cite reliably even if the original moves. Every Reference declares where it came from in sources.",
81
89
  required: ["sources"]
90
+ },
91
+ Runbook: {
92
+ description: "A repeatable operational procedure with a trigger and an observable end state.",
93
+ guidance: "Write the steps in the order they are performed, not as rules. Name the trigger that starts the procedure and the observable state that means it succeeded.",
94
+ fields: { resource: {
95
+ description: "A path relative to this concept file to the script, workflow, or config the procedure runs through, when one exists in this repository.",
96
+ kind: "path"
97
+ } }
98
+ },
99
+ Glossary: {
100
+ description: "A term this repository uses in its own sense, one term per concept.",
101
+ guidance: "Define the term as this repository means it, not as the wider ecosystem means it, and say plainly where the two differ. A term earns a concept on a collision or a trap; one that merely names a Module belongs in that Module."
102
+ },
103
+ Limitation: {
104
+ description: "A known edge of a contract: something that does not work, and why that is acceptable.",
105
+ guidance: "State the condition that triggers it and the observable symptom, not just the cause, and name the Interface or Module whose promise it bounds. If it is fixable and merely unfixed, say what the fix would take.",
106
+ fields: { bounds: {
107
+ description: "The Interface or Module concept whose promise this limitation bounds.",
108
+ kind: "path"
109
+ } }
110
+ },
111
+ DataModel: {
112
+ description: "An internal source-of-truth structure that other artifacts are derived from.",
113
+ guidance: "Document the shape from the maintainer's side: what an entry contains, what is derived from it, and what breaks if an entry is wrong. Distinct from Interface, which documents a promise to consumers.",
114
+ required: ["resource"],
115
+ fields: { resource: {
116
+ description: "A path relative to this concept file, normally escaping the bundle, to the file or directory that holds the structure.",
117
+ kind: "path"
118
+ } }
119
+ },
120
+ Gotcha: {
121
+ description: "A state or result that looks like one thing and is the opposite: breakage that is transient, or success that did nothing.",
122
+ guidance: "Describe what a reader sees, what they will wrongly conclude, and what is actually true, and point resource at the code or command that produces the misleading signal. Give it a staleness window, since a trap fixed upstream turns into misinformation.",
123
+ fields: { resource: {
124
+ description: "A path relative to this concept file to the code, script, or config that produces the misleading signal.",
125
+ kind: "path"
126
+ } }
127
+ },
128
+ Consumer: {
129
+ description: "An external application that consumes this repository and thereby scopes it.",
130
+ guidance: "Name the surfaces it exercises, where the edge between the two repositories sits, and the open questions it raises, so the boundary of this repository is read from its consumers rather than inferred. Deprecate it when the consumer stops consuming.",
131
+ required: ["repository"],
132
+ fields: { repository: { description: "Where the consumer lives, as a URL or an owner/name pair, since it is outside this repository." } }
133
+ },
134
+ Roadmap: {
135
+ description: "A gate and the forward-looking work behind it, held as intent rather than as a Decision.",
136
+ guidance: "List the phases and what remains in each, and give it a staleness window so queued work is re-examined instead of read as settled. Deprecate it when the gate holds and write the Decisions the work produced.",
137
+ fields: { gate: { description: "The observable condition that closes this roadmap, for example a release shipped or a benchmark met." } }
138
+ },
139
+ Measurement: {
140
+ description: "A dated empirical result: what was measured, how, and what the numbers ruled in or out.",
141
+ guidance: "Record the inputs, the method, and the numbers so a reader can judge whether they still hold, and give it a staleness window because numbers rot. A Decision links to the Measurement that justified it instead of embedding the result in its body.",
142
+ fields: { justifies: {
143
+ description: "Paths to the Decisions this measurement supports, one entry per Decision.",
144
+ kind: "path"
145
+ } }
82
146
  }
83
147
  },
84
148
  tags: {
@@ -86,7 +150,13 @@ const config = {
86
150
  testing: { description: "Concerns how the system is verified: strategy, fixtures, and coverage policy." },
87
151
  release: { description: "Concerns how changes ship: versioning, changelogs, publishing, and tagging." },
88
152
  security: { description: "Concerns trust boundaries, secrets, permissions, or attack surface." },
89
- performance: { description: "Concerns speed, memory, or resource cost and the trade-offs made for them." }
153
+ performance: { description: "Concerns speed, memory, or resource cost and the trade-offs made for them." },
154
+ dx: { description: "Concerns the experience of the people and agents who author, build, and debug the code." },
155
+ ci: { description: "Concerns the unattended path: what runs without a human present, and how it fails." },
156
+ compat: { description: "Concerns compatibility across versions of the runtime, the package manager, or a dependency." },
157
+ bundle: { description: "Concerns install weight and reachability: tree-shaking, subpath entrypoints, and dependency edges declined for their cost." },
158
+ observability: { description: "Concerns how the system reports on itself: events, metrics, logs, sinks, and artifacts." },
159
+ deps: { description: "Concerns how third-party dependencies are declared, pinned, and distributed." }
90
160
  },
91
161
  extensions: {}
92
162
  };
@@ -117,6 +187,38 @@ const layout = {
117
187
  {
118
188
  directory: "references",
119
189
  type: "Reference"
190
+ },
191
+ {
192
+ directory: "runbooks",
193
+ type: "Runbook"
194
+ },
195
+ {
196
+ directory: "glossary",
197
+ type: "Glossary"
198
+ },
199
+ {
200
+ directory: "limitations",
201
+ type: "Limitation"
202
+ },
203
+ {
204
+ directory: "models",
205
+ type: "DataModel"
206
+ },
207
+ {
208
+ directory: "gotchas",
209
+ type: "Gotcha"
210
+ },
211
+ {
212
+ directory: "consumers",
213
+ type: "Consumer"
214
+ },
215
+ {
216
+ directory: "roadmaps",
217
+ type: "Roadmap"
218
+ },
219
+ {
220
+ directory: "measurements",
221
+ type: "Measurement"
120
222
  }
121
223
  ]
122
224
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@okfit/profiles",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "private": false,
5
5
  "description": "Named OKF configuration profiles for okfit, starting with the software-project profile.",
6
6
  "keywords": [
@@ -37,7 +37,7 @@
37
37
  "peerDependencies": {
38
38
  "@effected/git": "^0.15.0",
39
39
  "@effected/markdown": "^0.10.0",
40
- "@okfit/core": "^0.3.1",
40
+ "@okfit/core": "^0.4.1",
41
41
  "effect": "4.0.0-rc.115"
42
42
  },
43
43
  "engines": {