agentera 3.0.0-dev.72 → 3.0.0-dev.74

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.
Files changed (92) hide show
  1. package/README.md +111 -0
  2. package/bundle/.agentera-build-source.json +8 -0
  3. package/bundle/CHANGELOG.md +17 -17
  4. package/bundle/extract-corpus-parity.json +1 -1
  5. package/bundle/references/adapters/package-publication.json +49 -53
  6. package/bundle/references/adapters/package-registry.yaml +5 -1
  7. package/bundle/references/adapters/package-surface-characterization.md +6 -4
  8. package/bundle/references/analysis/evidence-tier-authority.yaml +45 -4
  9. package/bundle/references/analysis/personal-glossary-evaluation-authority.yaml +175 -0
  10. package/bundle/references/analysis/personal-glossary-evaluation-corpus.yaml +291 -0
  11. package/bundle/references/analysis/personal-glossary-holdout.yaml +192 -0
  12. package/bundle/references/artifacts/glossary-entry-contract.yaml +1533 -35
  13. package/bundle/references/cli/update-channels.yaml +2 -2
  14. package/bundle/references/cli/vocabulary.md +1 -1
  15. package/bundle/references/meta/retained-reference-authority.yaml +15 -0
  16. package/bundle/skills/agentera/capabilities/profile/schemas/artifacts.yaml +11 -7
  17. package/bundle/skills/agentera/capabilities/profile/schemas/exit.yaml +6 -3
  18. package/bundle/skills/agentera/capabilities/profile/schemas/validation.yaml +13 -7
  19. package/bundle/skills/agentera/schemas/artifacts/glossary.yaml +5 -0
  20. package/bundle/skills/agentera/schemas/artifacts/plan.yaml +7 -0
  21. package/dist/.agentera-build-source.json +8 -0
  22. package/dist/analytics/extractCorpus/copilotSessions.js +13 -4
  23. package/dist/analytics/extractCorpus/core.js +223 -3
  24. package/dist/analytics/extractCorpus/corpus.js +18 -1
  25. package/dist/analytics/extractCorpus/cursorSessions.js +22 -4
  26. package/dist/analytics/extractCorpus/evidenceTiers.js +123 -17
  27. package/dist/analytics/extractCorpus/filesystemSources.js +4 -0
  28. package/dist/analytics/extractCorpus/index.js +2 -2
  29. package/dist/analytics/extractCorpus/jsonlSessions.js +52 -3
  30. package/dist/analytics/extractCorpus/sqliteSessions.js +12 -3
  31. package/dist/analytics/personalGlossaryAdmission.js +26 -46
  32. package/dist/analytics/personalGlossaryCandidateProjection.js +692 -0
  33. package/dist/analytics/personalGlossaryCandidateProjectionExcerpts.js +144 -0
  34. package/dist/analytics/personalGlossaryCandidateReadView.js +23 -0
  35. package/dist/analytics/personalGlossaryCurrentGeneration.js +25 -0
  36. package/dist/analytics/personalGlossaryDecision.js +203 -0
  37. package/dist/analytics/personalGlossaryExplicit.js +788 -0
  38. package/dist/analytics/personalGlossaryExplicitMining.js +285 -0
  39. package/dist/analytics/personalGlossaryExplicitScope.js +41 -0
  40. package/dist/analytics/personalGlossaryExplicitSegments.js +418 -0
  41. package/dist/analytics/personalGlossaryExplicitTypes.js +26 -0
  42. package/dist/analytics/personalGlossaryLexicalClassifier.js +175 -0
  43. package/dist/analytics/personalGlossaryProfile.js +13 -3
  44. package/dist/analytics/personalGlossaryRecurrence.js +618 -0
  45. package/dist/analytics/personalGlossaryReviewRecordStorage.js +428 -0
  46. package/dist/analytics/personalGlossaryReviewRecords.js +332 -0
  47. package/dist/capabilities/index.js +5 -1
  48. package/dist/capabilities/profile/instructions.js +50 -15
  49. package/dist/cli/commands/personalGlossaryCandidateReads.js +744 -0
  50. package/dist/cli/commands/personalGlossaryDecision.js +349 -0
  51. package/dist/cli/commands/personalGlossaryPublish.js +484 -0
  52. package/dist/cli/commands/personalGlossaryReviewRecordReads.js +209 -0
  53. package/dist/cli/commands/personalGlossaryReviewRecords.js +623 -0
  54. package/dist/cli/commands/prime/briefOrientation.js +118 -19
  55. package/dist/cli/commands/report.js +18 -2
  56. package/dist/cli/commands/schema.js +179 -0
  57. package/dist/cli/commands/verify.js +51 -9
  58. package/dist/cli/dispatch/lifecycle.js +51 -6
  59. package/dist/cli/help.js +48 -2
  60. package/dist/cli/migrationRequired.js +4 -1
  61. package/dist/core/atomicWriter.js +4 -1
  62. package/dist/core/developmentInvocation.js +4 -1
  63. package/dist/core/yaml.js +53 -1
  64. package/dist/eval/glossaryEvaluation.js +751 -0
  65. package/dist/eval/glossaryEvaluationProcess.js +29 -0
  66. package/dist/eval/glossaryEvaluationRunner.js +571 -0
  67. package/dist/eval/glossaryEvaluationSuccessReport.js +297 -0
  68. package/dist/registries/activationTuples.js +31 -3
  69. package/dist/registries/evidenceTierContract.js +4 -0
  70. package/dist/registries/explicitSegmentGrammarContract.js +619 -0
  71. package/dist/registries/glossaryCandidateContractPaths.js +6 -0
  72. package/dist/registries/glossaryCandidateContracts.js +820 -0
  73. package/dist/registries/glossaryCandidateDecisionAuthority.js +119 -0
  74. package/dist/registries/glossaryCandidateDecisionContract.js +62 -0
  75. package/dist/registries/glossaryCandidateProjectionAuthority.js +197 -0
  76. package/dist/registries/glossaryCandidateProjectionContract.js +104 -0
  77. package/dist/registries/glossaryEntryContract.js +105 -103
  78. package/dist/registries/glossaryEntryTemporal.js +12 -0
  79. package/dist/registries/glossaryMiningAuthority.js +764 -0
  80. package/dist/registries/glossaryProfileFullContract.js +24 -0
  81. package/dist/registries/glossaryReviewRecordsAuthority.js +426 -0
  82. package/dist/registries/glossaryReviewRecordsContract.js +129 -0
  83. package/dist/registries/glossaryTermIdentity.js +122 -0
  84. package/dist/registries/packagePublication.js +3 -3
  85. package/dist/registries/personalGlossaryContracts.js +1 -0
  86. package/dist/release/releaseMetadata.js +14 -7
  87. package/dist/upgrade/npxPlatformStatus.js +2 -1
  88. package/dist/upgrade/projectIntegration.js +7 -1
  89. package/dist/validate/activationArtifactEvidence.js +18 -4
  90. package/dist/validate/activationEvidenceManifest.js +101 -22
  91. package/package.json +2 -4
  92. package/dist/cli/commands/personalGlossary.js +0 -176
@@ -0,0 +1,619 @@
1
+ import path from "node:path";
2
+ import { loadYamlMappingFile } from "../core/yaml.js";
3
+ import { resolveSourceRoot } from "../core/sourceRoot.js";
4
+ export const EXPLICIT_SEGMENT_GRAMMAR_SCHEMA_VERSION = "agentera.personalGlossarySegmentGrammar.v1";
5
+ export const EXPLICIT_SEGMENT_FORM_IDS = [
6
+ "quoted_means",
7
+ "definition_list_colon",
8
+ "acronym_stands_for",
9
+ "acronym_parenthetical",
10
+ "by_i_mean",
11
+ "use_for",
12
+ "use_to_mean",
13
+ "refers_to",
14
+ "clarification_prefer_to_mean",
15
+ "correction_means",
16
+ ];
17
+ export const EXPLICIT_SEGMENT_STATES = [
18
+ "outside",
19
+ "cue",
20
+ "inline_meaning",
21
+ "continuation",
22
+ "structural_config",
23
+ "terminated",
24
+ "rejected",
25
+ ];
26
+ export const EXPLICIT_SEGMENT_INPUTS = [
27
+ "approved_cue",
28
+ "non_empty_inline_meaning",
29
+ "continuation_line",
30
+ "blank_line",
31
+ "next_cue",
32
+ "structural_fragment",
33
+ "comment",
34
+ "list_boundary",
35
+ "indentation",
36
+ "nested_marker",
37
+ "block_scalar",
38
+ "prose",
39
+ "unsupported",
40
+ "eof",
41
+ ];
42
+ export const EXPLICIT_SEGMENT_REASONS = {
43
+ unsupportedTransition: "unsupported_transition",
44
+ structuralFragment: "structural_fragment",
45
+ emptyMeaning: "empty_meaning",
46
+ meaningBoundExceeded: "meaning_bound_exceeded",
47
+ ambiguousReference: "ambiguous_reference",
48
+ conflictingMeaning: "conflicting_meaning",
49
+ invalidExitBoundary: "invalid_exit_boundary",
50
+ };
51
+ function transition(from, input, to, action, reason) {
52
+ return { from, input, to, action, ...(reason === undefined ? {} : { reason }) };
53
+ }
54
+ const REQUIRED_TRANSITIONS = [
55
+ transition("outside", "approved_cue", "cue", "enter_cue_segment"),
56
+ transition("outside", "structural_fragment", "structural_config", "enter_structural_config", EXPLICIT_SEGMENT_REASONS.structuralFragment),
57
+ transition("outside", "list_boundary", "structural_config", "enter_structural_config", EXPLICIT_SEGMENT_REASONS.structuralFragment),
58
+ transition("outside", "unsupported", "rejected", "reject", EXPLICIT_SEGMENT_REASONS.unsupportedTransition),
59
+ transition("cue", "non_empty_inline_meaning", "inline_meaning", "capture_inline_meaning"),
60
+ transition("cue", "blank_line", "rejected", "reject", EXPLICIT_SEGMENT_REASONS.emptyMeaning),
61
+ transition("cue", "next_cue", "rejected", "reject", EXPLICIT_SEGMENT_REASONS.emptyMeaning),
62
+ transition("cue", "structural_fragment", "rejected", "reject", EXPLICIT_SEGMENT_REASONS.emptyMeaning),
63
+ transition("cue", "unsupported", "rejected", "reject", EXPLICIT_SEGMENT_REASONS.unsupportedTransition),
64
+ transition("inline_meaning", "continuation_line", "continuation", "append_original_newline"),
65
+ transition("inline_meaning", "blank_line", "terminated", "finish_before_boundary"),
66
+ transition("inline_meaning", "next_cue", "terminated", "finish_before_boundary"),
67
+ transition("inline_meaning", "structural_fragment", "terminated", "finish_before_boundary"),
68
+ transition("inline_meaning", "comment", "terminated", "finish_before_boundary"),
69
+ transition("inline_meaning", "list_boundary", "terminated", "finish_before_boundary"),
70
+ transition("inline_meaning", "prose", "continuation", "append_original_newline"),
71
+ transition("inline_meaning", "eof", "terminated", "finish_at_eof"),
72
+ transition("inline_meaning", "unsupported", "rejected", "reject", EXPLICIT_SEGMENT_REASONS.unsupportedTransition),
73
+ transition("continuation", "continuation_line", "continuation", "append_original_newline"),
74
+ transition("continuation", "prose", "continuation", "append_original_newline"),
75
+ transition("continuation", "blank_line", "terminated", "finish_before_boundary"),
76
+ transition("continuation", "next_cue", "terminated", "finish_before_boundary"),
77
+ transition("continuation", "structural_fragment", "terminated", "finish_before_boundary"),
78
+ transition("continuation", "comment", "terminated", "finish_before_boundary"),
79
+ transition("continuation", "list_boundary", "terminated", "finish_before_boundary"),
80
+ transition("continuation", "eof", "terminated", "finish_at_eof"),
81
+ transition("continuation", "unsupported", "rejected", "reject", EXPLICIT_SEGMENT_REASONS.unsupportedTransition),
82
+ transition("structural_config", "approved_cue", "rejected", "reject", EXPLICIT_SEGMENT_REASONS.structuralFragment),
83
+ transition("structural_config", "structural_fragment", "structural_config", "reject_structural_fragment", EXPLICIT_SEGMENT_REASONS.structuralFragment),
84
+ transition("structural_config", "comment", "structural_config", "reject_structural_fragment", EXPLICIT_SEGMENT_REASONS.structuralFragment),
85
+ transition("structural_config", "blank_line", "structural_config", "reject_structural_fragment", EXPLICIT_SEGMENT_REASONS.structuralFragment),
86
+ transition("structural_config", "indentation", "structural_config", "reject_structural_fragment", EXPLICIT_SEGMENT_REASONS.structuralFragment),
87
+ transition("structural_config", "nested_marker", "structural_config", "reject_structural_fragment", EXPLICIT_SEGMENT_REASONS.structuralFragment),
88
+ transition("structural_config", "block_scalar", "structural_config", "reject_structural_fragment", EXPLICIT_SEGMENT_REASONS.structuralFragment),
89
+ transition("structural_config", "list_boundary", "structural_config", "reject_structural_fragment", EXPLICIT_SEGMENT_REASONS.structuralFragment),
90
+ transition("structural_config", "prose", "outside", "reject_fragment_then_exit", EXPLICIT_SEGMENT_REASONS.structuralFragment),
91
+ transition("structural_config", "unsupported", "rejected", "reject", EXPLICIT_SEGMENT_REASONS.unsupportedTransition),
92
+ transition("structural_config", "eof", "rejected", "reject", EXPLICIT_SEGMENT_REASONS.structuralFragment),
93
+ transition("terminated", "unsupported", "rejected", "reject", EXPLICIT_SEGMENT_REASONS.unsupportedTransition),
94
+ transition("rejected", "unsupported", "rejected", "reject", EXPLICIT_SEGMENT_REASONS.unsupportedTransition),
95
+ ];
96
+ export class ExplicitSegmentGrammarContractError extends Error {
97
+ }
98
+ function mapping(value) {
99
+ return value !== null && typeof value === "object" && !Array.isArray(value)
100
+ ? value
101
+ : null;
102
+ }
103
+ function strings(value) {
104
+ return Array.isArray(value) && value.every((item) => typeof item === "string")
105
+ ? [...value]
106
+ : [];
107
+ }
108
+ function sameStrings(value, expected) {
109
+ return JSON.stringify(strings(value)) === JSON.stringify(expected);
110
+ }
111
+ function nonEmpty(value) {
112
+ return typeof value === "string" && value.trim().length > 0;
113
+ }
114
+ function isState(value) {
115
+ return EXPLICIT_SEGMENT_STATES.includes(value);
116
+ }
117
+ function isInput(value) {
118
+ return EXPLICIT_SEGMENT_INPUTS.includes(value);
119
+ }
120
+ function isReason(value) {
121
+ return Object.values(EXPLICIT_SEGMENT_REASONS).includes(value);
122
+ }
123
+ function transitionKey(from, input) {
124
+ return `${from}:${input}`;
125
+ }
126
+ function formMappings(value) {
127
+ return Array.isArray(value)
128
+ ? value.map(mapping).filter((item) => item !== null)
129
+ : [];
130
+ }
131
+ function validateTransition(value, label, fallback, errors) {
132
+ const transition = mapping(value);
133
+ if (!transition) {
134
+ errors.push(`${label} must be a mapping`);
135
+ return;
136
+ }
137
+ if (!isState(transition.from))
138
+ errors.push(`${label}.from is not a declared state`);
139
+ if (fallback) {
140
+ if (transition.input !== "unsupported") {
141
+ errors.push(`${label}.input must be unsupported`);
142
+ }
143
+ }
144
+ else if (!isInput(transition.input)) {
145
+ errors.push(`${label}.input is not a declared input class`);
146
+ }
147
+ if (!isState(transition.to))
148
+ errors.push(`${label}.to is not a declared state`);
149
+ if (!nonEmpty(transition.action))
150
+ errors.push(`${label}.action is required`);
151
+ if (transition.reason !== undefined && !isReason(transition.reason)) {
152
+ errors.push(`${label}.reason is not a stable grammar reason`);
153
+ }
154
+ }
155
+ function validateExactObjectFields(value, fields, label, errors) {
156
+ const result = mapping(value);
157
+ if (!result) {
158
+ errors.push(`${label} must be a mapping`);
159
+ return null;
160
+ }
161
+ for (const field of fields) {
162
+ if (result[field] === undefined)
163
+ errors.push(`${label}.${field} is required`);
164
+ }
165
+ return result;
166
+ }
167
+ /** Validate the finite grammar projection nested under explicit_discovery.grammar. */
168
+ export function validateExplicitSegmentGrammar(value) {
169
+ const errors = [];
170
+ const grammar = mapping(value);
171
+ const segment = mapping(grammar?.segment_grammar);
172
+ if (!segment) {
173
+ errors.push("explicit segment grammar must declare segment_grammar");
174
+ return errors;
175
+ }
176
+ if (segment.schema_version !== EXPLICIT_SEGMENT_GRAMMAR_SCHEMA_VERSION) {
177
+ errors.push("explicit segment grammar schema_version is unsupported");
178
+ }
179
+ if (segment.segment_class !== "explicit_cue_segment") {
180
+ errors.push("explicit segment grammar must declare explicit_cue_segment");
181
+ }
182
+ if (!sameStrings(segment.states, EXPLICIT_SEGMENT_STATES)) {
183
+ errors.push("explicit segment grammar states must remain finite and ordered");
184
+ }
185
+ if (!sameStrings(segment.input_classes, EXPLICIT_SEGMENT_INPUTS)) {
186
+ errors.push("explicit segment grammar input_classes must remain finite and ordered");
187
+ }
188
+ if (segment.initial_state !== "outside") {
189
+ errors.push("explicit segment grammar initial_state must be outside");
190
+ }
191
+ if (!sameStrings(segment.terminal_states, ["terminated", "rejected"])) {
192
+ errors.push("explicit segment grammar terminal_states must be terminated and rejected");
193
+ }
194
+ const forms = formMappings(grammar?.forms);
195
+ if (!sameStrings(forms.map((form) => String(form.id)), EXPLICIT_SEGMENT_FORM_IDS)) {
196
+ errors.push("explicit segment grammar must cover the approved ten cue forms in order");
197
+ }
198
+ for (const [index, form] of forms.entries()) {
199
+ if (!EXPLICIT_SEGMENT_FORM_IDS.includes(form.id)) {
200
+ errors.push(`explicit segment grammar form[${index}].id is not approved`);
201
+ }
202
+ if (form.segment_class !== "explicit_cue_segment") {
203
+ errors.push(`explicit segment grammar form[${index}] must map to explicit_cue_segment`);
204
+ }
205
+ if (!nonEmpty(form.syntax))
206
+ errors.push(`explicit segment grammar form[${index}].syntax is required`);
207
+ if (form.entry !== "outside_approved_cue") {
208
+ errors.push(`explicit segment grammar form[${index}].entry is invalid`);
209
+ }
210
+ if (form.termination !== "shared_bounded_termination") {
211
+ errors.push(`explicit segment grammar form[${index}].termination is invalid`);
212
+ }
213
+ if (form.output !== "shared_cue_segment_output") {
214
+ errors.push(`explicit segment grammar form[${index}].output is invalid`);
215
+ }
216
+ }
217
+ const entry = validateExactObjectFields(segment.entry, ["from", "input", "to", "accepted_forms", "unsupported_reason"], "explicit segment grammar entry", errors);
218
+ if (entry) {
219
+ if (entry.from !== "outside" || entry.input !== "approved_cue" || entry.to !== "cue") {
220
+ errors.push("explicit segment grammar entry must transition outside approved_cue to cue");
221
+ }
222
+ if (!sameStrings(entry.accepted_forms, EXPLICIT_SEGMENT_FORM_IDS)) {
223
+ errors.push("explicit segment grammar entry must accept every approved cue form");
224
+ }
225
+ if (entry.unsupported_reason !== EXPLICIT_SEGMENT_REASONS.unsupportedTransition) {
226
+ errors.push("explicit segment grammar entry must fail closed with unsupported_transition");
227
+ }
228
+ }
229
+ const termination = validateExactObjectFields(segment.termination, [
230
+ "start_state",
231
+ "continuation_state",
232
+ "terminal_state",
233
+ "required",
234
+ "boundary_inputs",
235
+ "maximum_meaning_utf8_bytes",
236
+ "limit",
237
+ "over_limit_reason",
238
+ ], "explicit segment grammar termination", errors);
239
+ if (termination) {
240
+ if (termination.start_state !== "inline_meaning" ||
241
+ termination.continuation_state !== "continuation" ||
242
+ termination.terminal_state !== "terminated" ||
243
+ termination.required !== "non_empty_inline_meaning") {
244
+ errors.push("explicit segment grammar termination states are invalid");
245
+ }
246
+ if (!sameStrings(termination.boundary_inputs, [
247
+ "blank_line",
248
+ "next_cue",
249
+ "structural_fragment",
250
+ "comment",
251
+ "list_boundary",
252
+ ])) {
253
+ errors.push("explicit segment grammar termination boundary_inputs are invalid");
254
+ }
255
+ if (termination.maximum_meaning_utf8_bytes !== 4096 || termination.limit !== "inclusive") {
256
+ errors.push("explicit segment grammar termination must accept exactly 4096 UTF-8 bytes");
257
+ }
258
+ if (termination.over_limit_reason !== EXPLICIT_SEGMENT_REASONS.meaningBoundExceeded) {
259
+ errors.push("explicit segment grammar termination over_limit_reason is invalid");
260
+ }
261
+ }
262
+ const output = validateExactObjectFields(segment.output, ["fields", "span_encoding", "source_semantics"], "explicit segment grammar output", errors);
263
+ if (output) {
264
+ if (!sameStrings(output.fields, ["term", "meaning", "term_span", "meaning_span"])) {
265
+ errors.push("explicit segment grammar output fields are invalid");
266
+ }
267
+ if (output.span_encoding !== "utf8_byte_offsets") {
268
+ errors.push("explicit segment grammar output must use UTF-8 byte offsets");
269
+ }
270
+ if (output.source_semantics !== "exact_source_bytes_without_unicode_normalization") {
271
+ errors.push("explicit segment grammar output must preserve exact source bytes");
272
+ }
273
+ }
274
+ const continuation = validateExactObjectFields(segment.continuation, [
275
+ "starts_after",
276
+ "preserves",
277
+ "stops_on",
278
+ "maximum_utf8_bytes",
279
+ "limit",
280
+ "over_limit",
281
+ "over_limit_reason",
282
+ ], "explicit segment grammar continuation", errors);
283
+ if (continuation) {
284
+ if (continuation.starts_after !== "non_empty_inline_meaning") {
285
+ errors.push("explicit segment grammar continuation must start after non-empty inline meaning");
286
+ }
287
+ if (continuation.preserves !== "exact_source_newlines_and_utf8_bytes") {
288
+ errors.push("explicit segment grammar continuation must preserve original newlines and bytes");
289
+ }
290
+ if (!sameStrings(continuation.stops_on, [
291
+ "blank_line",
292
+ "next_cue",
293
+ "structural_fragment",
294
+ "comment",
295
+ "list_boundary",
296
+ ])) {
297
+ errors.push("explicit segment grammar continuation stops_on is invalid");
298
+ }
299
+ if (continuation.maximum_utf8_bytes !== 4096 || continuation.limit !== "inclusive") {
300
+ errors.push("explicit segment grammar continuation must accept exactly 4096 UTF-8 bytes");
301
+ }
302
+ if (continuation.over_limit !== "reject" ||
303
+ continuation.over_limit_reason !== EXPLICIT_SEGMENT_REASONS.meaningBoundExceeded) {
304
+ errors.push("explicit segment grammar continuation must reject one byte over the bound");
305
+ }
306
+ }
307
+ const structural = validateExactObjectFields(segment.structural_configuration, ["state", "entry_inputs", "persist_inputs", "reject_inputs", "exit"], "explicit segment grammar structural_configuration", errors);
308
+ if (structural) {
309
+ if (structural.state !== "structural_config") {
310
+ errors.push("explicit segment grammar structural_configuration state is invalid");
311
+ }
312
+ if (!sameStrings(structural.entry_inputs, ["structural_fragment", "list_boundary"])) {
313
+ errors.push("explicit segment grammar structural_configuration entry_inputs are invalid");
314
+ }
315
+ if (!sameStrings(structural.persist_inputs, [
316
+ "comment",
317
+ "blank_line",
318
+ "indentation",
319
+ "nested_marker",
320
+ "block_scalar",
321
+ "structural_fragment",
322
+ "list_boundary",
323
+ ])) {
324
+ errors.push("explicit segment grammar structural_configuration persist_inputs are invalid");
325
+ }
326
+ if (!sameStrings(structural.reject_inputs, [
327
+ "comment",
328
+ "blank_line",
329
+ "indentation",
330
+ "nested_marker",
331
+ "block_scalar",
332
+ "structural_fragment",
333
+ "list_boundary",
334
+ "approved_cue",
335
+ ])) {
336
+ errors.push("explicit segment grammar structural_configuration reject_inputs are invalid");
337
+ }
338
+ const exit = mapping(structural.exit);
339
+ if (!exit) {
340
+ errors.push("explicit segment grammar structural_configuration.exit must be a mapping");
341
+ }
342
+ else if (exit.input !== "prose" ||
343
+ !nonEmpty(exit.condition) ||
344
+ !nonEmpty(exit.action) ||
345
+ exit.next_state !== "outside" ||
346
+ exit.definition_allowed !== "next_physical_line_only") {
347
+ errors.push("explicit segment grammar structural_configuration must have one finite prose exit");
348
+ }
349
+ }
350
+ const references = validateExactObjectFields(segment.reference_binding, [
351
+ "following",
352
+ "this",
353
+ "exact_term",
354
+ "matching",
355
+ "duplicate_target_reason",
356
+ "missing_target_reason",
357
+ "duplicate_target_outcome",
358
+ "missing_target_outcome",
359
+ "unrelated_cue_outcome",
360
+ ], "explicit segment grammar reference_binding", errors);
361
+ if (references) {
362
+ if (references.following !== "nearest_next_cue" ||
363
+ references.this !== "nearest_previous_cue" ||
364
+ references.exact_term !== "nearest_matching_cue" ||
365
+ references.matching !== "unicode_caseless_exact_no_normalization" ||
366
+ references.duplicate_target_reason !== EXPLICIT_SEGMENT_REASONS.ambiguousReference ||
367
+ references.missing_target_reason !== EXPLICIT_SEGMENT_REASONS.ambiguousReference ||
368
+ references.duplicate_target_outcome !== "exclude_bound_cue_only" ||
369
+ references.missing_target_outcome !== "exclude_bound_cue_only" ||
370
+ references.unrelated_cue_outcome !== "retain") {
371
+ errors.push("explicit segment grammar reference_binding direction and ambiguity rules are invalid");
372
+ }
373
+ }
374
+ const deduplication = validateExactObjectFields(segment.deduplication, [
375
+ "identity",
376
+ "same_identity_same_meaning",
377
+ "same_identity_different_meaning",
378
+ "unrelated_cue_outcome",
379
+ ], "explicit segment grammar deduplication", errors);
380
+ if (deduplication) {
381
+ if (deduplication.identity !== "personal_mining_authority.term_identity.stable_term_identity" ||
382
+ deduplication.same_identity_same_meaning !== "retain_one_earliest_source_span" ||
383
+ deduplication.same_identity_different_meaning !== "reject_all_conflicting_meaning" ||
384
+ deduplication.unrelated_cue_outcome !== "retain") {
385
+ errors.push("explicit segment grammar deduplication must preserve identity and conflict semantics");
386
+ }
387
+ }
388
+ const order = validateExactObjectFields(segment.canonical_order, ["fields", "comparator", "direction"], "explicit segment grammar canonical_order", errors);
389
+ if (order) {
390
+ if (!sameStrings(order.fields, ["term", "meaning", "term_span.start", "meaning_span.start"]) ||
391
+ order.comparator !== "unicode_scalar_code_point_ascending" ||
392
+ order.direction !== "ascending") {
393
+ errors.push("explicit segment grammar canonical_order must remain lexical and ascending");
394
+ }
395
+ }
396
+ const transitions = Array.isArray(segment.transitions) ? segment.transitions : [];
397
+ const canonicalTransitionKeys = new Set(REQUIRED_TRANSITIONS.map((transition) => transitionKey(transition.from, transition.input)));
398
+ const transitionKeys = new Set();
399
+ for (const [index, value] of transitions.entries()) {
400
+ validateTransition(value, `explicit segment grammar transitions[${index}]`, false, errors);
401
+ const transition = mapping(value);
402
+ if (transition && isState(transition.from) && isInput(transition.input)) {
403
+ const key = transitionKey(transition.from, transition.input);
404
+ if (transitionKeys.has(key))
405
+ errors.push(`explicit segment grammar transition ${key} is duplicated`);
406
+ transitionKeys.add(key);
407
+ if (!canonicalTransitionKeys.has(key))
408
+ errors.push(`explicit segment grammar transition ${key} is not declared by its finite rule`);
409
+ }
410
+ }
411
+ for (const expected of REQUIRED_TRANSITIONS) {
412
+ const key = transitionKey(expected.from, expected.input);
413
+ const actual = transitions
414
+ .map(mapping)
415
+ .find((transition) => transition?.from === expected.from && transition.input === expected.input);
416
+ if (!actual) {
417
+ errors.push(`explicit segment grammar transition ${key} is required`);
418
+ continue;
419
+ }
420
+ if (actual.to !== expected.to ||
421
+ actual.action !== expected.action ||
422
+ (expected.reason === undefined
423
+ ? actual.reason !== undefined
424
+ : actual.reason !== expected.reason)) {
425
+ errors.push(`explicit segment grammar transition ${key} does not match its finite rule`);
426
+ }
427
+ }
428
+ const fallbacks = mapping(segment.fallback_transitions);
429
+ if (!fallbacks) {
430
+ errors.push("explicit segment grammar fallback_transitions must declare every state");
431
+ }
432
+ else {
433
+ for (const state of EXPLICIT_SEGMENT_STATES) {
434
+ const fallback = mapping(fallbacks[state]);
435
+ if (!fallback) {
436
+ errors.push(`explicit segment grammar fallback_transitions.${state} is required`);
437
+ continue;
438
+ }
439
+ validateTransition(fallback, `explicit segment grammar fallback_transitions.${state}`, true, errors);
440
+ if (fallback.from !== state || fallback.to !== "rejected") {
441
+ errors.push(`explicit segment grammar fallback_transitions.${state} must reject from its state`);
442
+ }
443
+ if (fallback.reason !== EXPLICIT_SEGMENT_REASONS.unsupportedTransition) {
444
+ errors.push(`explicit segment grammar fallback_transitions.${state} must use unsupported_transition`);
445
+ }
446
+ }
447
+ }
448
+ const reasonMap = mapping(segment.reasons);
449
+ if (!reasonMap) {
450
+ errors.push("explicit segment grammar reasons must be declared");
451
+ }
452
+ else {
453
+ for (const [key, reason] of Object.entries(EXPLICIT_SEGMENT_REASONS)) {
454
+ const yamlKey = key.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
455
+ if (reasonMap[yamlKey] !== reason) {
456
+ errors.push(`explicit segment grammar reasons.${yamlKey} must be ${reason}`);
457
+ }
458
+ }
459
+ }
460
+ return errors;
461
+ }
462
+ export function explicitSegmentGrammarAuthorityPath(root = resolveSourceRoot()) {
463
+ return path.join(root, "references", "artifacts", "glossary-entry-contract.yaml");
464
+ }
465
+ function requiredString(value, label) {
466
+ if (!nonEmpty(value))
467
+ throw new ExplicitSegmentGrammarContractError(`${label} must be non-empty`);
468
+ return value;
469
+ }
470
+ /** Load the validated finite contract that a future explicit parser consumes. */
471
+ export function loadExplicitSegmentGrammarContract(pathname = explicitSegmentGrammarAuthorityPath()) {
472
+ let authority;
473
+ try {
474
+ authority = loadYamlMappingFile(pathname);
475
+ }
476
+ catch (error) {
477
+ throw new ExplicitSegmentGrammarContractError(`glossary entry authority ${pathname} is unreadable or malformed: ${error.message}`);
478
+ }
479
+ const mining = mapping(authority.personal_mining_authority);
480
+ const explicitDiscovery = mapping(mining?.explicit_discovery);
481
+ const grammar = mapping(explicitDiscovery?.grammar);
482
+ const errors = validateExplicitSegmentGrammar(grammar);
483
+ if (errors.length > 0)
484
+ throw new ExplicitSegmentGrammarContractError(errors.join("; "));
485
+ const segment = mapping(grammar?.segment_grammar);
486
+ const forms = new Map();
487
+ for (const value of formMappings(grammar?.forms)) {
488
+ const id = value.id;
489
+ forms.set(id, {
490
+ id,
491
+ segmentClass: requiredString(value.segment_class, `form ${id}.segment_class`),
492
+ syntax: requiredString(value.syntax, `form ${id}.syntax`),
493
+ entry: "outside_approved_cue",
494
+ termination: "shared_bounded_termination",
495
+ output: "shared_cue_segment_output",
496
+ });
497
+ }
498
+ const transitions = new Map();
499
+ for (const value of Array.isArray(segment.transitions) ? segment.transitions : []) {
500
+ const transition = mapping(value);
501
+ const from = transition.from;
502
+ const input = transition.input;
503
+ transitions.set(transitionKey(from, input), {
504
+ from,
505
+ input,
506
+ to: transition.to,
507
+ action: requiredString(transition.action, `${from}:${input}.action`),
508
+ ...(transition.reason === undefined
509
+ ? {}
510
+ : { reason: transition.reason }),
511
+ });
512
+ }
513
+ const fallbackMap = new Map();
514
+ const fallbackMappings = mapping(segment.fallback_transitions);
515
+ for (const state of EXPLICIT_SEGMENT_STATES) {
516
+ const value = mapping(fallbackMappings[state]);
517
+ fallbackMap.set(state, {
518
+ from: state,
519
+ input: "unsupported",
520
+ to: "rejected",
521
+ action: requiredString(value.action, `fallback ${state}.action`),
522
+ reason: value.reason,
523
+ });
524
+ }
525
+ const entry = mapping(segment.entry);
526
+ const termination = mapping(segment.termination);
527
+ const continuation = mapping(segment.continuation);
528
+ const structural = mapping(segment.structural_configuration);
529
+ const structuralExit = mapping(structural.exit);
530
+ const references = mapping(segment.reference_binding);
531
+ return {
532
+ schemaVersion: segment.schema_version,
533
+ segmentClass: segment.segment_class,
534
+ states: [...strings(segment.states)],
535
+ inputClasses: [...strings(segment.input_classes)],
536
+ initialState: "outside",
537
+ terminalStates: ["terminated", "rejected"],
538
+ forms,
539
+ entry: {
540
+ from: "outside",
541
+ input: "approved_cue",
542
+ to: "cue",
543
+ acceptedForms: strings(entry.accepted_forms),
544
+ unsupportedReason: entry.unsupported_reason,
545
+ },
546
+ termination: {
547
+ startState: "inline_meaning",
548
+ continuationState: "continuation",
549
+ terminalState: "terminated",
550
+ required: "non_empty_inline_meaning",
551
+ boundaryInputs: strings(termination.boundary_inputs),
552
+ maximumMeaningUtf8Bytes: 4096,
553
+ limit: "inclusive",
554
+ overLimitReason: termination.over_limit_reason,
555
+ },
556
+ output: {
557
+ fields: ["term", "meaning", "term_span", "meaning_span"],
558
+ spanEncoding: "utf8_byte_offsets",
559
+ sourceSemantics: "exact_source_bytes_without_unicode_normalization",
560
+ },
561
+ continuation: {
562
+ startsAfter: "non_empty_inline_meaning",
563
+ preserves: "exact_source_newlines_and_utf8_bytes",
564
+ stopsOn: strings(continuation.stops_on),
565
+ maximumUtf8Bytes: 4096,
566
+ limit: "inclusive",
567
+ overLimit: "reject",
568
+ overLimitReason: continuation.over_limit_reason,
569
+ },
570
+ structuralConfiguration: {
571
+ state: "structural_config",
572
+ entryInputs: strings(structural.entry_inputs),
573
+ persistInputs: strings(structural.persist_inputs),
574
+ rejectInputs: strings(structural.reject_inputs),
575
+ exit: {
576
+ input: "prose",
577
+ condition: requiredString(structuralExit.condition, "structural exit.condition"),
578
+ action: requiredString(structuralExit.action, "structural exit.action"),
579
+ nextState: "outside",
580
+ definitionAllowed: "next_physical_line_only",
581
+ },
582
+ },
583
+ referenceBinding: {
584
+ following: "nearest_next_cue",
585
+ this: "nearest_previous_cue",
586
+ exactTerm: "nearest_matching_cue",
587
+ matching: "unicode_caseless_exact_no_normalization",
588
+ duplicateTargetReason: references.duplicate_target_reason,
589
+ missingTargetReason: references.missing_target_reason,
590
+ duplicateTargetOutcome: "exclude_bound_cue_only",
591
+ missingTargetOutcome: "exclude_bound_cue_only",
592
+ unrelatedCueOutcome: "retain",
593
+ },
594
+ deduplication: {
595
+ identity: "personal_mining_authority.term_identity.stable_term_identity",
596
+ sameIdentitySameMeaning: "retain_one_earliest_source_span",
597
+ sameIdentityDifferentMeaning: "reject_all_conflicting_meaning",
598
+ unrelatedCueOutcome: "retain",
599
+ },
600
+ canonicalOrder: {
601
+ fields: ["term", "meaning", "term_span.start", "meaning_span.start"],
602
+ comparator: "unicode_scalar_code_point_ascending",
603
+ direction: "ascending",
604
+ },
605
+ transitions,
606
+ fallbacks: fallbackMap,
607
+ };
608
+ }
609
+ /** Resolve one transition, falling back to the declared stable rejection. */
610
+ export function explicitSegmentTransition(contract, state, input) {
611
+ return (contract.transitions.get(transitionKey(state, input)) ??
612
+ contract.fallbacks.get(state) ?? {
613
+ from: state,
614
+ input,
615
+ to: "rejected",
616
+ action: "reject",
617
+ reason: EXPLICIT_SEGMENT_REASONS.unsupportedTransition,
618
+ });
619
+ }
@@ -0,0 +1,6 @@
1
+ import path from "node:path";
2
+ import { resolveSourceRoot } from "../core/sourceRoot.js";
3
+ /** Resolve the authority shared by the candidate-layer contract readers. */
4
+ export function glossaryCandidateContractsAuthorityPath(root = resolveSourceRoot()) {
5
+ return path.join(root, "references", "artifacts", "glossary-entry-contract.yaml");
6
+ }