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,285 @@
1
+ import { createGlossaryEvidenceCapsule } from "../registries/glossaryCandidateContracts.js";
2
+ import { personalGlossaryAdmissionContract } from "../registries/glossaryEntryContract.js";
3
+ import { PERSONAL_GLOSSARY_MINING_POLICY_VERSION } from "../registries/glossaryMiningAuthority.js";
4
+ import { stableGlossaryTermIdentity } from "../registries/glossaryTermIdentity.js";
5
+ import { assessTiers, recoveryForState } from "./extractCorpus/tierReader.js";
6
+ import { readSignalTier, resolveEvidenceAnchor, } from "./extractCorpus/evidenceTiers.js";
7
+ import { EXPLICIT_GLOSSARY_REASONS, candidateBounds, compareText, dataObject, rawCues, retractionInvalidatesCue, utf8Span, validCue, } from "./personalGlossaryExplicit.js";
8
+ const SHA256_RE = /^[a-f0-9]{64}$/u;
9
+ function recordText(record) {
10
+ const data = dataObject(record);
11
+ for (const field of ["text", "prompt", "content"]) {
12
+ if (typeof data[field] === "string")
13
+ return data[field];
14
+ }
15
+ return "";
16
+ }
17
+ function recordIsUserAuthored(signal, record) {
18
+ const data = dataObject(record);
19
+ return ((record.source_kind === "conversation_turn" || record.source_kind === "history_prompt") &&
20
+ record.author_class === "user" &&
21
+ (signal.author_class === undefined || signal.author_class === "user") &&
22
+ data.actor !== "assistant" &&
23
+ data.actor !== "agent" &&
24
+ data.injected !== true &&
25
+ record.source_class !== "injected");
26
+ }
27
+ function makeAbstention(sourceId, anchor, reason, term = null) {
28
+ const cleanTerm = term && term.trim() ? term.trim() : null;
29
+ return {
30
+ term: cleanTerm,
31
+ candidate_id: cleanTerm ? stableGlossaryTermIdentity(cleanTerm) : null,
32
+ source_id: sourceId,
33
+ evidence_anchor: anchor,
34
+ reason,
35
+ };
36
+ }
37
+ function compareAbstentions(left, right) {
38
+ return (compareText(left.source_id, right.source_id) ||
39
+ compareText(left.evidence_anchor, right.evidence_anchor) ||
40
+ compareText(left.term ?? "", right.term ?? "") ||
41
+ compareText(left.reason, right.reason));
42
+ }
43
+ function compareCandidates(left, right) {
44
+ return (compareText(left.candidate.capsule.term, right.candidate.capsule.term) ||
45
+ compareText(left.candidate.capsule.meaning, right.candidate.capsule.meaning) ||
46
+ compareText(left.sourceId, right.sourceId) ||
47
+ compareText(left.anchor, right.anchor) ||
48
+ left.cue.termStart - right.cue.termStart ||
49
+ left.cue.meaningStart - right.cue.meaningStart);
50
+ }
51
+ function compareCandidateSource(left, right) {
52
+ return (compareText(left.sourceId, right.sourceId) ||
53
+ compareText(left.anchor, right.anchor) ||
54
+ left.cue.termStart - right.cue.termStart ||
55
+ left.cue.meaningStart - right.cue.meaningStart ||
56
+ compareText(left.candidate.capsule.term, right.candidate.capsule.term) ||
57
+ compareText(left.candidate.capsule.meaning, right.candidate.capsule.meaning));
58
+ }
59
+ function sameRecord(signal, record) {
60
+ if (signal.evidence_anchor !== signal.source_id ||
61
+ record.source_id !== signal.source_id ||
62
+ record.source_kind !== signal.source_kind) {
63
+ return "stale";
64
+ }
65
+ const dataSignal = dataObject(record).signal_type;
66
+ if (record.source_kind === "conversation_turn" && dataSignal !== signal.signal_type)
67
+ return "stale";
68
+ for (const field of [
69
+ "origin_id",
70
+ "content_fingerprint",
71
+ "author_class",
72
+ "session_id",
73
+ "project_id",
74
+ ]) {
75
+ const expected = signal[field];
76
+ if (expected !== undefined && record[field] !== expected)
77
+ return "stale";
78
+ }
79
+ return "valid";
80
+ }
81
+ function provenanceValue(signal, field) {
82
+ return field === "evidence_anchor" ? signal.evidence_anchor : signal[field];
83
+ }
84
+ function recordProvenanceValue(record, field) {
85
+ if (field === "evidence_anchor")
86
+ return record.source_id;
87
+ if (field === "signal_type")
88
+ return dataObject(record).signal_type;
89
+ return record[field];
90
+ }
91
+ function hasCompleteProvenance(signal, record, requiredFields) {
92
+ if (requiredFields.length === 0 || signal.source_kind !== "conversation_turn")
93
+ return false;
94
+ for (const field of requiredFields) {
95
+ const signalValue = provenanceValue(signal, field);
96
+ const recordValue = recordProvenanceValue(record, field);
97
+ if (typeof signalValue !== "string" || signalValue.length === 0)
98
+ return false;
99
+ if (typeof recordValue !== "string" || recordValue.length === 0)
100
+ return false;
101
+ if (signalValue !== recordValue)
102
+ return false;
103
+ if ((field === "origin_id" || field === "content_fingerprint") &&
104
+ !SHA256_RE.test(signalValue)) {
105
+ return false;
106
+ }
107
+ }
108
+ return true;
109
+ }
110
+ function unavailable(state) {
111
+ return {
112
+ state,
113
+ generation: null,
114
+ candidates: [],
115
+ abstentions: [],
116
+ recovery: recoveryForState(state),
117
+ };
118
+ }
119
+ function candidateWithSource(signal, cue, text, generation) {
120
+ const capsule = createGlossaryEvidenceCapsule({
121
+ term: cue.term,
122
+ meaning: cue.meaning,
123
+ scope: "personal",
124
+ provenance_kind: "personal_explicit_definition",
125
+ evidence: [
126
+ {
127
+ source_id: signal.source_id,
128
+ evidence_anchor: signal.evidence_anchor,
129
+ signal_type: signal.signal_type,
130
+ },
131
+ ],
132
+ policy_version: PERSONAL_GLOSSARY_MINING_POLICY_VERSION,
133
+ generation,
134
+ });
135
+ return {
136
+ candidate: {
137
+ capsule,
138
+ term_span: utf8Span(text, cue.termStart, cue.termEnd),
139
+ meaning_span: utf8Span(text, cue.meaningStart, cue.meaningEnd),
140
+ project_ids: [signal.project_id],
141
+ },
142
+ sourceId: signal.source_id,
143
+ anchor: signal.evidence_anchor,
144
+ identity: stableGlossaryTermIdentity(cue.term),
145
+ meaning: cue.meaning,
146
+ cue,
147
+ };
148
+ }
149
+ function userCue(signal, record, text, rawCue, allCues, bounds, generation) {
150
+ const result = validCue(text, rawCue, bounds, record);
151
+ if (!result.cue) {
152
+ return {
153
+ candidate: null,
154
+ abstention: result.reason
155
+ ? makeAbstention(signal.source_id, signal.evidence_anchor, result.reason, text.slice(rawCue.termStart, rawCue.termEnd))
156
+ : null,
157
+ };
158
+ }
159
+ const cue = result.cue;
160
+ if (!recordIsUserAuthored(signal, record)) {
161
+ return {
162
+ candidate: null,
163
+ abstention: makeAbstention(signal.source_id, signal.evidence_anchor, EXPLICIT_GLOSSARY_REASONS.userAuthorshipRequired, cue.term),
164
+ };
165
+ }
166
+ if (retractionInvalidatesCue(text, cue, allCues)) {
167
+ return {
168
+ candidate: null,
169
+ abstention: makeAbstention(signal.source_id, signal.evidence_anchor, EXPLICIT_GLOSSARY_REASONS.retractedDefinition, cue.term),
170
+ };
171
+ }
172
+ return { candidate: candidateWithSource(signal, cue, text, generation), abstention: null };
173
+ }
174
+ function uniqueCandidateSources(candidates) {
175
+ const unique = new Map();
176
+ for (const item of candidates) {
177
+ const key = `${item.identity}:${item.meaning}:${item.anchor}`;
178
+ const previous = unique.get(key);
179
+ if (!previous || compareCandidateSource(item, previous) < 0)
180
+ unique.set(key, item);
181
+ }
182
+ return [...unique.values()].sort(compareCandidates);
183
+ }
184
+ function classifyRecord(signal, record, generation, bounds, requiredProvenanceFields) {
185
+ if (!hasCompleteProvenance(signal, record, requiredProvenanceFields)) {
186
+ return {
187
+ candidates: [],
188
+ abstentions: [
189
+ makeAbstention(signal.source_id, signal.evidence_anchor, EXPLICIT_GLOSSARY_REASONS.provenanceIncomplete),
190
+ ],
191
+ };
192
+ }
193
+ const text = recordText(record);
194
+ const raw = rawCues(text);
195
+ const candidates = [];
196
+ const abstentions = [];
197
+ const local = raw.map((cue) => userCue(signal, record, text, cue, raw, bounds, generation));
198
+ for (const item of local) {
199
+ if (item.abstention)
200
+ abstentions.push(item.abstention);
201
+ if (item.candidate)
202
+ candidates.push(item.candidate);
203
+ }
204
+ const byIdentity = new Map();
205
+ for (const item of candidates) {
206
+ const group = byIdentity.get(item.identity) ?? [];
207
+ group.push(item);
208
+ byIdentity.set(item.identity, group);
209
+ }
210
+ const filtered = [];
211
+ for (const group of byIdentity.values()) {
212
+ if (new Set(group.map((item) => item.meaning)).size > 1) {
213
+ const first = [...group].sort(compareCandidates)[0];
214
+ abstentions.push(makeAbstention(first.sourceId, first.anchor, EXPLICIT_GLOSSARY_REASONS.conflictingMeaning, first.candidate.capsule.term));
215
+ continue;
216
+ }
217
+ filtered.push([...group].sort(compareCandidateSource)[0]);
218
+ }
219
+ return { candidates: filtered, abstentions };
220
+ }
221
+ export function mineExplicitGlossaryCandidates(input, resolveAnchor = resolveEvidenceAnchor) {
222
+ const assessment = assessTiers(input.tiersDir);
223
+ if (!assessment.analyzable)
224
+ return unavailable(assessment.state);
225
+ const tier = readSignalTier(input.tiersDir, { allowProvenanceGaps: true });
226
+ if (!tier)
227
+ return unavailable("corrupt");
228
+ const authority = personalGlossaryAdmissionContract();
229
+ const allowedSignalTypes = new Set(authority.explicitSignalTypes);
230
+ const selected = tier.records
231
+ .filter((signal) => allowedSignalTypes.has(signal.signal_type))
232
+ .sort((left, right) => compareText(left.source_id, right.source_id) ||
233
+ compareText(left.evidence_anchor, right.evidence_anchor) ||
234
+ compareText(left.signal_type, right.signal_type));
235
+ const bounds = candidateBounds();
236
+ const resolvedByAnchor = new Map();
237
+ for (const signal of selected) {
238
+ if (!resolvedByAnchor.has(signal.evidence_anchor)) {
239
+ resolvedByAnchor.set(signal.evidence_anchor, resolveAnchor(signal.evidence_anchor, input.tiersDir));
240
+ }
241
+ }
242
+ const candidates = [];
243
+ const abstentions = [];
244
+ for (const signal of selected) {
245
+ const record = resolvedByAnchor.get(signal.evidence_anchor) ?? null;
246
+ if (!record) {
247
+ abstentions.push(makeAbstention(signal.source_id, signal.evidence_anchor, EXPLICIT_GLOSSARY_REASONS.unresolvedAnchor));
248
+ continue;
249
+ }
250
+ if (sameRecord(signal, record) === "stale") {
251
+ abstentions.push(makeAbstention(signal.source_id, signal.evidence_anchor, EXPLICIT_GLOSSARY_REASONS.staleAnchor));
252
+ continue;
253
+ }
254
+ const classified = classifyRecord(signal, record, tier.manifest.generation, bounds, authority.explicitProvenanceFields);
255
+ candidates.push(...classified.candidates);
256
+ abstentions.push(...classified.abstentions);
257
+ }
258
+ const uniqueCandidates = uniqueCandidateSources(candidates);
259
+ const globalGroups = new Map();
260
+ for (const item of uniqueCandidates) {
261
+ const group = globalGroups.get(item.identity) ?? [];
262
+ group.push(item);
263
+ globalGroups.set(item.identity, group);
264
+ }
265
+ const globallyEligible = [];
266
+ for (const group of globalGroups.values()) {
267
+ const ordered = [...group].sort(compareCandidates);
268
+ if (new Set(ordered.map((item) => item.meaning)).size > 1) {
269
+ for (const item of ordered) {
270
+ abstentions.push(makeAbstention(item.sourceId, item.anchor, EXPLICIT_GLOSSARY_REASONS.conflictingMeaning, item.candidate.capsule.term));
271
+ }
272
+ continue;
273
+ }
274
+ globallyEligible.push([...group].sort(compareCandidateSource)[0]);
275
+ }
276
+ return {
277
+ state: assessment.state,
278
+ generation: tier.manifest.generation,
279
+ candidates: globallyEligible.sort(compareCandidates).map((item) => item.candidate),
280
+ abstentions: abstentions.sort(compareAbstentions),
281
+ recovery: null,
282
+ };
283
+ }
284
+ export const minePersonalExplicitGlossaryCandidates = mineExplicitGlossaryCandidates;
285
+ export const mineExplicitGlossaryEvidence = mineExplicitGlossaryCandidates;
@@ -0,0 +1,41 @@
1
+ const SENTENCE_TERMINATORS = new Set([".", "!", "?"]);
2
+ export function contextText(text, cue) {
3
+ return text.slice(cue.sentenceStart, cue.sentenceEnd);
4
+ }
5
+ function adjacentSentence(text, start, direction) {
6
+ if (direction === -1) {
7
+ const end = Math.max(0, start);
8
+ let boundary = -1;
9
+ for (let index = end - 1; index >= 0; index -= 1) {
10
+ if (SENTENCE_TERMINATORS.has(text[index])) {
11
+ boundary = index;
12
+ break;
13
+ }
14
+ }
15
+ const previousEnd = boundary + 1;
16
+ let previousBoundary = -1;
17
+ for (let index = previousEnd - 2; index >= 0; index -= 1) {
18
+ if (SENTENCE_TERMINATORS.has(text[index])) {
19
+ previousBoundary = index;
20
+ break;
21
+ }
22
+ }
23
+ return text.slice(previousBoundary + 1, previousEnd).trim();
24
+ }
25
+ const startAt = Math.min(text.length, start);
26
+ let end = text.length;
27
+ for (let index = startAt; index < text.length; index += 1) {
28
+ if (SENTENCE_TERMINATORS.has(text[index])) {
29
+ end = index + 1;
30
+ break;
31
+ }
32
+ }
33
+ return text.slice(startAt, end).trim();
34
+ }
35
+ export function adjacentScopeTexts(text, cue) {
36
+ return [
37
+ adjacentSentence(text, cue.sentenceStart, -1),
38
+ contextText(text, cue),
39
+ adjacentSentence(text, cue.sentenceEnd, 1),
40
+ ];
41
+ }