yarramate 0.8.0 → 0.8.1

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.
@@ -1,6 +1,6 @@
1
1
  format: yarramate/question-catalogue/v1
2
2
  id: core-enrichment
3
- version: "0.4"
3
+ version: "0.5"
4
4
  profile: yarramate/core@0.1
5
5
  presentation:
6
6
  title: Core enrichment interview
@@ -122,7 +122,9 @@ questions:
122
122
  authority: either
123
123
  resolution: >-
124
124
  Add realization relationships from the fulfilling capability or
125
- service, or record the aspirational status in the goal's description.
125
+ service, record the aspirational status in the goal's description,
126
+ or retire the goal (status: retired) to record that it no longer
127
+ steers design.
126
128
 
127
129
 
128
130
  - id: goal-no-driver
@@ -219,8 +221,11 @@ questions:
219
221
  roadmap.
220
222
  authority: either
221
223
  resolution: >-
222
- Add realization from the fulfilling service, component, or behavior,
223
- or record the descoping decision and remove the requirement.
224
+ Add realization from the fulfilling service, component, or
225
+ behavior; to descope instead, retire the requirement (status:
226
+ retired) — retirement preserves the decision on record and closes
227
+ the question (ADR 0064). Delete only when the history itself is
228
+ noise.
224
229
 
225
230
  - id: principle-unapplied
226
231
  wave: motivation
@@ -123,7 +123,24 @@ const itemMap = (source, collection, id) => {
123
123
  };
124
124
  // The indent item fields sit at, read off the item's own first field.
125
125
  const fieldIndentOf = (source, map) => indentAt(source, nodeRange(map.items[0].key)[0]);
126
+ // A flow-style item (`- { id: x, ... }`) cannot take block field lines;
127
+ // splicing them after it corrupts the sequence (Codex dogfood finding,
128
+ // 2026-08-01). The whole item is rewritten as a block mapping with the
129
+ // mutation applied — churn confined to the item being edited.
130
+ const rewriteFlowItem = (source, map, mutate) => {
131
+ const mutated = mutate(map.toJSON());
132
+ const [start, valueEnd] = nodeRange(map);
133
+ const fieldIndent = indentAt(source, start);
134
+ const rendered = reindent(stringify(mutated, { lineWidth: 0 }).trimEnd(), fieldIndent);
135
+ return splice(source, start, valueEnd, rendered);
136
+ };
126
137
  const setScalarField = (source, map, key, value) => {
138
+ if (map.flow) {
139
+ return rewriteFlowItem(source, map, (fields) => ({
140
+ ...fields,
141
+ [key]: value,
142
+ }));
143
+ }
127
144
  const indent = fieldIndentOf(source, map);
128
145
  const rendered = reindent(valueText(value), indent + 2);
129
146
  const pair = pairFor(map, key);
@@ -134,6 +151,15 @@ const setScalarField = (source, map, key, value) => {
134
151
  return splice(source, start, valueEnd, rendered);
135
152
  };
136
153
  const appendListField = (source, map, key, additions) => {
154
+ if (map.flow) {
155
+ return rewriteFlowItem(source, map, (fields) => ({
156
+ ...fields,
157
+ [key]: [
158
+ ...(fields[key] ?? []),
159
+ ...additions,
160
+ ],
161
+ }));
162
+ }
137
163
  const indent = fieldIndentOf(source, map);
138
164
  const pair = pairFor(map, key);
139
165
  if (pair === undefined) {
@@ -163,11 +189,19 @@ const appendListField = (source, map, key, additions) => {
163
189
  return splice(source, start, valueEnd, `\n${sequenceEntries(merged, indent + 2)}`);
164
190
  };
165
191
  // Retraction (#115): delete the field's whole entry, from the start of its
166
- // key line through the end of its value's last line.
192
+ // key line through the end of its value's last line. A flow item is
193
+ // rewritten instead — line-based deletion there would take the whole item
194
+ // with it.
167
195
  const removeField = (source, map, key) => {
168
196
  const pair = pairFor(map, key);
169
197
  if (pair === undefined)
170
198
  return undefined;
199
+ if (map.flow) {
200
+ return rewriteFlowItem(source, map, (fields) => {
201
+ const { [key]: _removed, ...rest } = fields;
202
+ return rest;
203
+ });
204
+ }
171
205
  const start = lineStartOf(source, nodeRange(pair.key)[0]);
172
206
  const valueEnd = pair.value === null || pair.value === undefined
173
207
  ? nodeRange(pair.key)[2]
@@ -12,12 +12,6 @@ const indexGraph = (graph) => {
12
12
  const stateSubjects = new Set(graph.claims
13
13
  .filter(({ predicate }) => predicate === 'yarramate/state/type')
14
14
  .map(({ subject }) => subject));
15
- // Architecture states carry concept subjects in the graph but are not
16
- // enrichment targets; the catalogue interrogates the model, not the
17
- // planning overlay.
18
- const concepts = new Set(graph.subjects
19
- .filter(({ id, type }) => type === 'concept' && !stateSubjects.has(id))
20
- .map(({ id }) => id));
21
15
  const claimsBySubject = new Map();
22
16
  const kindOf = new Map();
23
17
  const nameOf = new Map();
@@ -50,6 +44,16 @@ const indexGraph = (graph) => {
50
44
  }
51
45
  }
52
46
  }
47
+ // Architecture states carry concept subjects in the graph but are not
48
+ // enrichment targets; the catalogue interrogates the model, not the
49
+ // planning overlay. Retired concepts are excluded for the same reason
50
+ // (ADR 0064): retirement is the recorded decision that a subject left
51
+ // the design conversation, so no question stays open against it.
52
+ const concepts = new Set(graph.subjects
53
+ .filter(({ id, type }) => type === 'concept' &&
54
+ !stateSubjects.has(id) &&
55
+ statusOf.get(id) !== 'retired')
56
+ .map(({ id }) => id));
53
57
  return {
54
58
  concepts,
55
59
  claimsBySubject,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yarramate",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "Tool-neutral semantic architecture engine and guided methodology",
5
5
  "license": "MIT",
6
6
  "repository": {