agentera 3.0.0-dev.72 → 3.0.0-dev.75

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 (93) 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/analysis/verification-policy.yaml +8 -13
  13. package/bundle/references/artifacts/glossary-entry-contract.yaml +1533 -35
  14. package/bundle/references/cli/update-channels.yaml +2 -2
  15. package/bundle/references/cli/vocabulary.md +1 -1
  16. package/bundle/references/meta/retained-reference-authority.yaml +16 -1
  17. package/bundle/skills/agentera/capabilities/profile/schemas/artifacts.yaml +11 -7
  18. package/bundle/skills/agentera/capabilities/profile/schemas/exit.yaml +6 -3
  19. package/bundle/skills/agentera/capabilities/profile/schemas/validation.yaml +13 -7
  20. package/bundle/skills/agentera/schemas/artifacts/glossary.yaml +5 -0
  21. package/bundle/skills/agentera/schemas/artifacts/plan.yaml +7 -0
  22. package/dist/.agentera-build-source.json +8 -0
  23. package/dist/analytics/extractCorpus/copilotSessions.js +13 -4
  24. package/dist/analytics/extractCorpus/core.js +223 -3
  25. package/dist/analytics/extractCorpus/corpus.js +18 -1
  26. package/dist/analytics/extractCorpus/cursorSessions.js +22 -4
  27. package/dist/analytics/extractCorpus/evidenceTiers.js +123 -17
  28. package/dist/analytics/extractCorpus/filesystemSources.js +4 -0
  29. package/dist/analytics/extractCorpus/index.js +2 -2
  30. package/dist/analytics/extractCorpus/jsonlSessions.js +52 -3
  31. package/dist/analytics/extractCorpus/sqliteSessions.js +12 -3
  32. package/dist/analytics/personalGlossaryAdmission.js +26 -46
  33. package/dist/analytics/personalGlossaryCandidateProjection.js +692 -0
  34. package/dist/analytics/personalGlossaryCandidateProjectionExcerpts.js +144 -0
  35. package/dist/analytics/personalGlossaryCandidateReadView.js +23 -0
  36. package/dist/analytics/personalGlossaryCurrentGeneration.js +25 -0
  37. package/dist/analytics/personalGlossaryDecision.js +203 -0
  38. package/dist/analytics/personalGlossaryExplicit.js +788 -0
  39. package/dist/analytics/personalGlossaryExplicitMining.js +285 -0
  40. package/dist/analytics/personalGlossaryExplicitScope.js +41 -0
  41. package/dist/analytics/personalGlossaryExplicitSegments.js +418 -0
  42. package/dist/analytics/personalGlossaryExplicitTypes.js +26 -0
  43. package/dist/analytics/personalGlossaryLexicalClassifier.js +175 -0
  44. package/dist/analytics/personalGlossaryProfile.js +13 -3
  45. package/dist/analytics/personalGlossaryRecurrence.js +618 -0
  46. package/dist/analytics/personalGlossaryReviewRecordStorage.js +428 -0
  47. package/dist/analytics/personalGlossaryReviewRecords.js +332 -0
  48. package/dist/capabilities/index.js +5 -1
  49. package/dist/capabilities/profile/instructions.js +50 -15
  50. package/dist/cli/commands/personalGlossaryCandidateReads.js +744 -0
  51. package/dist/cli/commands/personalGlossaryDecision.js +349 -0
  52. package/dist/cli/commands/personalGlossaryPublish.js +484 -0
  53. package/dist/cli/commands/personalGlossaryReviewRecordReads.js +209 -0
  54. package/dist/cli/commands/personalGlossaryReviewRecords.js +623 -0
  55. package/dist/cli/commands/prime/briefOrientation.js +118 -19
  56. package/dist/cli/commands/report.js +18 -2
  57. package/dist/cli/commands/schema.js +179 -0
  58. package/dist/cli/commands/verify.js +51 -9
  59. package/dist/cli/dispatch/lifecycle.js +51 -6
  60. package/dist/cli/help.js +48 -2
  61. package/dist/cli/migrationRequired.js +4 -1
  62. package/dist/core/atomicWriter.js +4 -1
  63. package/dist/core/developmentInvocation.js +4 -1
  64. package/dist/core/yaml.js +53 -1
  65. package/dist/eval/glossaryEvaluation.js +751 -0
  66. package/dist/eval/glossaryEvaluationProcess.js +29 -0
  67. package/dist/eval/glossaryEvaluationRunner.js +571 -0
  68. package/dist/eval/glossaryEvaluationSuccessReport.js +297 -0
  69. package/dist/registries/activationTuples.js +31 -3
  70. package/dist/registries/evidenceTierContract.js +4 -0
  71. package/dist/registries/explicitSegmentGrammarContract.js +619 -0
  72. package/dist/registries/glossaryCandidateContractPaths.js +6 -0
  73. package/dist/registries/glossaryCandidateContracts.js +820 -0
  74. package/dist/registries/glossaryCandidateDecisionAuthority.js +119 -0
  75. package/dist/registries/glossaryCandidateDecisionContract.js +62 -0
  76. package/dist/registries/glossaryCandidateProjectionAuthority.js +197 -0
  77. package/dist/registries/glossaryCandidateProjectionContract.js +104 -0
  78. package/dist/registries/glossaryEntryContract.js +105 -103
  79. package/dist/registries/glossaryEntryTemporal.js +12 -0
  80. package/dist/registries/glossaryMiningAuthority.js +764 -0
  81. package/dist/registries/glossaryProfileFullContract.js +24 -0
  82. package/dist/registries/glossaryReviewRecordsAuthority.js +426 -0
  83. package/dist/registries/glossaryReviewRecordsContract.js +129 -0
  84. package/dist/registries/glossaryTermIdentity.js +122 -0
  85. package/dist/registries/packagePublication.js +3 -3
  86. package/dist/registries/personalGlossaryContracts.js +1 -0
  87. package/dist/release/releaseMetadata.js +15 -8
  88. package/dist/upgrade/npxPlatformStatus.js +2 -1
  89. package/dist/upgrade/projectIntegration.js +7 -1
  90. package/dist/validate/activationArtifactEvidence.js +18 -4
  91. package/dist/validate/activationEvidenceManifest.js +101 -22
  92. package/package.json +2 -4
  93. package/dist/cli/commands/personalGlossary.js +0 -176
@@ -0,0 +1,119 @@
1
+ function mapping(value) {
2
+ return value !== null && typeof value === "object" && !Array.isArray(value)
3
+ ? value
4
+ : null;
5
+ }
6
+ function strings(value) {
7
+ return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : [];
8
+ }
9
+ function exactStrings(actual, expected) {
10
+ return JSON.stringify(strings(actual)) === JSON.stringify(expected);
11
+ }
12
+ function nonEmpty(value) {
13
+ return typeof value === "string" && value.trim().length > 0;
14
+ }
15
+ export const GLOSSARY_ADMISSION_OUTCOMES = [
16
+ "automatic_admission", "review_required", "abstain",
17
+ ];
18
+ export const GLOSSARY_ADMISSION_REASONS_BY_OUTCOME = {
19
+ automatic_admission: ["explicit_current_authorized"],
20
+ review_required: [
21
+ "inferred_requires_review",
22
+ "scope_ambiguous",
23
+ "classification_inconsistent",
24
+ "classification_changed",
25
+ "entry_conflict",
26
+ "evidence_retracted_or_conflicted",
27
+ "quality_gate_not_authorizing",
28
+ ],
29
+ abstain: ["scope_project", "evidence_unavailable", "evidence_changed"],
30
+ };
31
+ export const GLOSSARY_ADMISSION_REASONS = [
32
+ ...GLOSSARY_ADMISSION_REASONS_BY_OUTCOME.automatic_admission,
33
+ ...GLOSSARY_ADMISSION_REASONS_BY_OUTCOME.review_required,
34
+ ...GLOSSARY_ADMISSION_REASONS_BY_OUTCOME.abstain,
35
+ ];
36
+ export function hasGlossaryAdmissionReasonCodesByOutcome(value) {
37
+ const reasonCodes = mapping(value);
38
+ return reasonCodes !== null
39
+ && exactStrings(Object.keys(reasonCodes), GLOSSARY_ADMISSION_OUTCOMES)
40
+ && GLOSSARY_ADMISSION_OUTCOMES.every((outcome) => exactStrings(reasonCodes[outcome], GLOSSARY_ADMISSION_REASONS_BY_OUTCOME[outcome]));
41
+ }
42
+ /** Validates the CLI admission layer's authority-owned vocabulary and command contract. */
43
+ export function validateGlossaryCandidateDecisionAuthority(authority) {
44
+ const errors = [];
45
+ const candidate = mapping(authority.candidate_contracts);
46
+ const layers = mapping(candidate?.layers);
47
+ const decisionLayer = mapping(layers?.cli_decision);
48
+ if (!exactStrings(decisionLayer?.outcomes, GLOSSARY_ADMISSION_OUTCOMES)) {
49
+ errors.push("CLI decision outcomes must use the approved vocabulary");
50
+ }
51
+ if (!exactStrings(decisionLayer?.reason_codes, GLOSSARY_ADMISSION_REASONS)) {
52
+ errors.push("CLI decision reasons must use the approved vocabulary");
53
+ }
54
+ if (!hasGlossaryAdmissionReasonCodesByOutcome(decisionLayer?.reason_codes_by_outcome)) {
55
+ errors.push("CLI decision reasons must declare the approved outcome/reason pairs");
56
+ }
57
+ const automatic = mapping(decisionLayer?.automatic_admission);
58
+ const automaticClassification = mapping(automatic?.required_classification);
59
+ if (automatic?.allowed_provenance !== "provenance_variants.personal_explicit_definition" ||
60
+ automatic?.inferred_automatic_admission !== "disabled" ||
61
+ automaticClassification?.scope !== "personal" ||
62
+ automaticClassification?.consistency !== "consistent" ||
63
+ automaticClassification?.term !== "exact_capsule_term" ||
64
+ automaticClassification?.meaning !== "exact_capsule_meaning" ||
65
+ automatic?.current_evidence !== "required" ||
66
+ automatic?.quality_gate !== "personal_mining_authority.admission.quality_threshold") {
67
+ errors.push("CLI automatic admission must be explicit-only and inferred automatic admission disabled");
68
+ }
69
+ const command = mapping(decisionLayer?.command);
70
+ const request = mapping(command?.request);
71
+ const result = mapping(command?.result);
72
+ const receiptConstruction = mapping(command?.receipt_construction);
73
+ const receiptConstructionResult = mapping(receiptConstruction?.result);
74
+ if (command?.canonical !== "npx -y agentera@next report personal-glossary-decision" ||
75
+ command?.namespace !== "report" ||
76
+ command?.input_flag !== "--input" ||
77
+ command?.stdin_value !== "-" ||
78
+ command?.format !== "json" ||
79
+ command?.project_checkout !== "not_required" ||
80
+ request?.schema_version !== "agentera.personalGlossaryAdmissionRequest.v1" ||
81
+ !exactStrings(request?.required_fields, ["schema_version", "receipt"]) ||
82
+ request?.additional_fields !== "forbidden" ||
83
+ request?.max_utf8_bytes !== 16384 ||
84
+ result?.schema_version !== "agentera.personalGlossaryAdmissionResult.v1" ||
85
+ !exactStrings(result?.fields, ["schemaVersion", "command", "status", "decision", "reason", "effects"]) ||
86
+ !exactStrings(result?.statuses, GLOSSARY_ADMISSION_OUTCOMES) ||
87
+ result?.max_utf8_bytes !== 4096 ||
88
+ !exactStrings(result?.effects, []) ||
89
+ receiptConstruction?.schema_version !== "agentera.personalGlossaryAdmissionRequest.v2" ||
90
+ !exactStrings(receiptConstruction?.required_fields, [
91
+ "schema_version",
92
+ "candidate_id",
93
+ "candidate_revision",
94
+ "candidate_capsule_sha256",
95
+ "candidate_projection_sha256",
96
+ "generation",
97
+ "policy_version",
98
+ "classification",
99
+ ]) ||
100
+ receiptConstruction?.additional_fields !== "forbidden" ||
101
+ receiptConstruction?.max_utf8_bytes !== 16384 ||
102
+ receiptConstructionResult?.schema_version !== "agentera.personalGlossaryAdmissionResult.v2" ||
103
+ !exactStrings(receiptConstructionResult?.fields, [
104
+ "schemaVersion",
105
+ "command",
106
+ "status",
107
+ "receipt",
108
+ "decision",
109
+ "reason",
110
+ "effects",
111
+ ]) ||
112
+ !exactStrings(receiptConstructionResult?.statuses, GLOSSARY_ADMISSION_OUTCOMES) ||
113
+ receiptConstructionResult?.max_utf8_bytes !== 16384 ||
114
+ !exactStrings(receiptConstructionResult?.effects, []) ||
115
+ !nonEmpty(command?.rule)) {
116
+ errors.push("CLI decision command must remain bounded, structured, read-only, and current-projection bound");
117
+ }
118
+ return errors;
119
+ }
@@ -0,0 +1,62 @@
1
+ import { loadYamlMappingFile } from "../core/yaml.js";
2
+ import { projectGlossaryDevelopmentValue } from "../core/developmentInvocation.js";
3
+ import { hasGlossaryAdmissionReasonCodesByOutcome } from "./glossaryCandidateDecisionAuthority.js";
4
+ import { glossaryEntryAuthorityPath } from "./glossaryEntryContract.js";
5
+ function mapping(value) {
6
+ return value !== null && typeof value === "object" && !Array.isArray(value)
7
+ ? value
8
+ : null;
9
+ }
10
+ function strings(value) {
11
+ return Array.isArray(value) && value.every((item) => typeof item === "string")
12
+ ? [...value]
13
+ : [];
14
+ }
15
+ /** Load the bounded receipt-validation and deterministic-decision settings. */
16
+ export function personalGlossaryCandidateDecisionContract(pathname = glossaryEntryAuthorityPath()) {
17
+ const authority = loadYamlMappingFile(pathname);
18
+ const candidateContracts = mapping(authority.candidate_contracts);
19
+ const layers = mapping(candidateContracts?.layers);
20
+ const decision = mapping(layers?.cli_decision);
21
+ const command = mapping(decision?.command);
22
+ const request = mapping(command?.request);
23
+ const result = mapping(command?.result);
24
+ const receiptConstruction = mapping(command?.receipt_construction);
25
+ const receiptConstructionResult = mapping(receiptConstruction?.result);
26
+ const automatic = mapping(decision?.automatic_admission);
27
+ const reasonCodesByOutcome = mapping(decision?.reason_codes_by_outcome);
28
+ if (!reasonCodesByOutcome || !hasGlossaryAdmissionReasonCodesByOutcome(reasonCodesByOutcome)) {
29
+ throw new TypeError("invalid development command projection: personal glossary decision outcome/reason authority is unavailable");
30
+ }
31
+ return {
32
+ command: projectGlossaryDevelopmentValue(command?.canonical, "candidate_decision.command"),
33
+ requestSchemaVersion: typeof request?.schema_version === "string" ? request.schema_version : "",
34
+ requestFields: strings(request?.required_fields),
35
+ maxRequestUtf8Bytes: typeof request?.max_utf8_bytes === "number" ? request.max_utf8_bytes : 0,
36
+ resultSchemaVersion: typeof result?.schema_version === "string" ? result.schema_version : "",
37
+ resultFields: strings(result?.fields),
38
+ resultStatuses: strings(result?.statuses),
39
+ reasonCodesByOutcome: Object.fromEntries(Object.entries(reasonCodesByOutcome).map(([outcome, reasons]) => [outcome, strings(reasons)])),
40
+ maxResultUtf8Bytes: typeof result?.max_utf8_bytes === "number" ? result.max_utf8_bytes : 0,
41
+ receiptConstructionRequestSchemaVersion: typeof receiptConstruction?.schema_version === "string"
42
+ ? receiptConstruction.schema_version
43
+ : "",
44
+ receiptConstructionRequestFields: strings(receiptConstruction?.required_fields),
45
+ receiptConstructionMaxRequestUtf8Bytes: typeof receiptConstruction?.max_utf8_bytes === "number"
46
+ ? receiptConstruction.max_utf8_bytes
47
+ : 0,
48
+ receiptConstructionResultSchemaVersion: typeof receiptConstructionResult?.schema_version === "string"
49
+ ? receiptConstructionResult.schema_version
50
+ : "",
51
+ receiptConstructionResultFields: strings(receiptConstructionResult?.fields),
52
+ receiptConstructionResultStatuses: strings(receiptConstructionResult?.statuses),
53
+ receiptConstructionMaxResultUtf8Bytes: typeof receiptConstructionResult?.max_utf8_bytes === "number"
54
+ ? receiptConstructionResult.max_utf8_bytes
55
+ : 0,
56
+ automaticProvenance: typeof automatic?.allowed_provenance === "string" ? automatic.allowed_provenance : "",
57
+ inferredAutomaticAdmission: typeof automatic?.inferred_automatic_admission === "string"
58
+ ? automatic.inferred_automatic_admission
59
+ : "",
60
+ qualityGate: typeof automatic?.quality_gate === "string" ? automatic.quality_gate : "",
61
+ };
62
+ }
@@ -0,0 +1,197 @@
1
+ function mapping(value) {
2
+ return value !== null && typeof value === "object" && !Array.isArray(value)
3
+ ? value
4
+ : null;
5
+ }
6
+ function strings(value) {
7
+ return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : [];
8
+ }
9
+ function sameStrings(actual, expected) {
10
+ return JSON.stringify(strings(actual)) === JSON.stringify(expected);
11
+ }
12
+ function nonEmpty(value) {
13
+ return typeof value === "string" && value.trim().length > 0;
14
+ }
15
+ /** Validate the authority-owned bounds for the internal candidate projection. */
16
+ export function validatePersonalCandidateProjectionAuthority(authority) {
17
+ const mining = mapping(authority.personal_mining_authority);
18
+ const projection = mapping(mining?.candidate_projection);
19
+ const selection = mapping(projection?.selection);
20
+ const sourceFamilies = mapping(selection?.source_families);
21
+ const projectIdentity = mapping(selection?.project_identity);
22
+ const excerpts = mapping(projection?.excerpts);
23
+ const excerptCompatibility = mapping(excerpts?.compatibility);
24
+ const retention = mapping(projection?.retention);
25
+ const persistence = mapping(projection?.persistence);
26
+ const retrieval = mapping(mining?.candidate_retrieval);
27
+ const currentGeneration = mapping(retrieval?.current_generation);
28
+ const retrievalCommand = mapping(retrieval?.command);
29
+ const list = mapping(retrieval?.list);
30
+ const filters = mapping(list?.filters);
31
+ const cursor = mapping(list?.cursor);
32
+ const safeContextView = mapping(retrieval?.safe_context_view);
33
+ const exact = mapping(retrieval?.exact);
34
+ const occurrence = mapping(exact?.occurrence);
35
+ const privacy = mapping(mining?.privacy);
36
+ const contentExclusion = mapping(privacy?.content_exclusion);
37
+ const storageFilesystem = mapping(mapping(privacy?.storage)?.filesystem);
38
+ if (projection?.status !== "active" ||
39
+ projection?.runtime !==
40
+ "packages/cli/src/analytics/personalGlossaryCandidateProjection.ts#projectPersonalGlossaryCandidates" ||
41
+ projection?.schema_version !== "agentera.personalGlossaryCandidateProjection.v1" ||
42
+ projection?.owner !== "deterministic_discovery_projection" ||
43
+ !nonEmpty(projection?.input) ||
44
+ !nonEmpty(projection?.output) ||
45
+ !nonEmpty(projection?.implementation_boundary) ||
46
+ selection?.candidates_max !== 50 ||
47
+ selection?.project_ids_max_per_candidate !== 100 ||
48
+ !sameStrings(Object.keys(sourceFamilies ?? {}), ["explicit", "recurring"]) ||
49
+ !sameStrings(sourceFamilies?.explicit, ["personal_explicit_definition"]) ||
50
+ !sameStrings(sourceFamilies?.recurring, [
51
+ "personal_inferred_usage",
52
+ "personal_inferred_conversation",
53
+ ]) ||
54
+ selection?.algorithm !== "least_retained_source_family_then_project_then_canonical_candidate" ||
55
+ selection?.tie_break !== "candidate_id_then_candidate_revision_then_capsule_sha256" ||
56
+ projectIdentity?.schema_version !== "agentera.personalGlossaryProjectionProjectIdentity.v1" ||
57
+ projectIdentity?.algorithm !== "sha256" ||
58
+ projectIdentity?.input !== "canonical_utf8_json_of_exact_transient_project_id" ||
59
+ projectIdentity?.output !== "lowercase_hex" ||
60
+ !nonEmpty(projectIdentity?.rule) ||
61
+ !nonEmpty(selection?.coverage) ||
62
+ excerpts?.source_max_utf8_bytes !== 4096 ||
63
+ excerpts?.max_per_candidate !== 1 ||
64
+ excerpts?.authority !== "personal_mining_authority.privacy.excerpts" ||
65
+ excerpts?.input_rule !== "candidate_adjacent_text_must_contain_the_exact_candidate_term" ||
66
+ !sameStrings(excerpts?.output_fields, ["text", "expires_at", "redacted"]) ||
67
+ excerptCompatibility?.redacted_field !== "retained_for_v1_consumers" ||
68
+ excerptCompatibility?.new_projection_value !== false ||
69
+ !sameStrings(excerpts?.omission_reasons, [
70
+ "no_excerpt",
71
+ "unrelated_context",
72
+ "source_bound_exceeded",
73
+ "unsafe_tool_arguments",
74
+ "unsafe_content",
75
+ ]) ||
76
+ !nonEmpty(excerpts?.rule) ||
77
+ retention?.authority !== "personal_mining_authority.privacy.retention" ||
78
+ retention?.purge !== "personal_mining_authority.privacy.purge" ||
79
+ !nonEmpty(retention?.rule) ||
80
+ persistence?.root !== "$AGENTERA_PROFILE_DIR/intermediate/personal-glossary" ||
81
+ persistence?.file !== "candidate-projection.json" ||
82
+ persistence?.canonicalization !== "candidate_contracts.canonicalization" ||
83
+ !sameStrings(persistence?.fields, [
84
+ "schema_version",
85
+ "owner",
86
+ "generation",
87
+ "policy_version",
88
+ "retained_at",
89
+ "candidates",
90
+ "report",
91
+ "projection_sha256",
92
+ ]) ||
93
+ persistence?.replay !== "byte_identical_projection_is_unchanged_replay" ||
94
+ persistence?.project_storage !== "forbidden" ||
95
+ persistence?.public_reads !== "forbidden" ||
96
+ !sameStrings(persistence?.private_machine_reads, ["candidate_retrieval", "cli_decision"]) ||
97
+ persistence?.review_disposition_writes !== "forbidden" ||
98
+ retrieval?.status !== "active" ||
99
+ retrieval?.owner !== "private_user_local_candidate_retrieval" ||
100
+ retrieval?.runtime !==
101
+ "packages/cli/src/cli/commands/personalGlossaryCandidateReads.ts#runPersonalGlossaryCandidateReadsCommand" ||
102
+ retrieval?.input !==
103
+ "current_validated_user_local_candidate_projection_bound_to_current_tier_generation" ||
104
+ currentGeneration?.source !== "current.json_readable_bounded_evidence_tier_generation" ||
105
+ currentGeneration?.projection_generation !== "exact_match_required" ||
106
+ currentGeneration?.unavailable_behavior !== "current_generation_unavailable" ||
107
+ currentGeneration?.stale_projection_behavior !== "projection_stale" ||
108
+ !nonEmpty(retrieval?.rule) ||
109
+ retrievalCommand?.canonical !==
110
+ "npx -y agentera@next report personal-glossary-candidates" ||
111
+ retrievalCommand?.namespace !== "report" ||
112
+ retrievalCommand?.format !== "json" ||
113
+ retrievalCommand?.project_checkout !== "not_required" ||
114
+ list?.schema_version !== "agentera.personalGlossaryCandidateRetrieval.v1" ||
115
+ list?.default_limit !== 20 ||
116
+ list?.maximum_limit !== 50 ||
117
+ list?.max_serialized_utf8_bytes !== 32768 ||
118
+ list?.order !== "candidate_id_then_candidate_revision_then_capsule_sha256" ||
119
+ list?.projection_binding_field !== "candidate_projection_sha256" ||
120
+ !sameStrings(filters?.source_family, ["explicit", "recurring"]) ||
121
+ filters?.provenance_kind_from !== "candidate_projection.selection.source_families" ||
122
+ !sameStrings(filters?.scope, ["personal", "ambiguous"]) ||
123
+ cursor?.authority !==
124
+ "references/artifacts/state-storage-authority.yaml#entity_target.public_retrieval.policy.cursor" ||
125
+ cursor?.vocabulary !== "opaque_snapshot_cursor" ||
126
+ !sameStrings(cursor?.binding, [
127
+ "collection",
128
+ "generation",
129
+ "policy_version",
130
+ "filters",
131
+ "limit",
132
+ "order",
133
+ "snapshot",
134
+ ]) ||
135
+ cursor?.invalid_behavior !== "cursor_invalid" ||
136
+ cursor?.unavailable_behavior !== "cursor_snapshot_unavailable" ||
137
+ !nonEmpty(list?.summaries) ||
138
+ !nonEmpty(list?.abstentions) ||
139
+ !nonEmpty(list?.coverage) ||
140
+ safeContextView?.authority !== "personal_mining_authority.privacy.retention" ||
141
+ safeContextView?.retention_days !== 30 ||
142
+ safeContextView?.expiry !== "expires_at_lte_read_time_is_unavailable" ||
143
+ safeContextView?.mutation !== "forbidden" ||
144
+ safeContextView?.snapshot !== "effective_availability_bound_to_opaque_cursor_snapshot" ||
145
+ !nonEmpty(safeContextView?.rule) ||
146
+ exact?.schema_version !== "agentera.personalGlossaryCandidateRetrieval.v1" ||
147
+ !sameStrings(exact?.required_bindings, [
148
+ "candidate_id",
149
+ "candidate_revision",
150
+ "generation",
151
+ "policy_version",
152
+ ]) ||
153
+ exact?.projection_binding_field !== "candidate_projection_sha256" ||
154
+ exact?.occurrences_max !== 100 ||
155
+ exact?.safe_context_max_utf8_bytes !== 500 ||
156
+ exact?.max_serialized_utf8_bytes !== 32768 ||
157
+ occurrence?.schema_version !== "agentera.personalGlossaryCandidateOccurrence.v1" ||
158
+ occurrence?.identity !== "opaque_sha256_of_validated_evidence_and_candidate_binding" ||
159
+ !sameStrings(occurrence?.allowed_fields, [
160
+ "occurrence_id",
161
+ "source_kind",
162
+ "signal_type",
163
+ "author_class",
164
+ ]) ||
165
+ !nonEmpty(exact?.rule) ||
166
+ contentExclusion?.owner !== "glossary_content_policy" ||
167
+ contentExclusion?.classification !== "actual_secret_or_sensitive_value" ||
168
+ contentExclusion?.conceptual_terminology !== "eligible" ||
169
+ !sameStrings(contentExclusion?.candidate_fields, ["term", "meaning"]) ||
170
+ contentExclusion?.candidate_action !== "reject_before_projection" ||
171
+ contentExclusion?.candidate_reason !== "secret_content" ||
172
+ contentExclusion?.excerpt_action !== "omit_complete_excerpt_before_projection" ||
173
+ !sameStrings(contentExclusion?.secret_classes, [
174
+ "api_keys",
175
+ "access_tokens",
176
+ "passwords",
177
+ "cookies",
178
+ "private_keys",
179
+ "authorization_headers",
180
+ "personal_contact_data",
181
+ "session_identifiers",
182
+ "runtime_store_paths",
183
+ ]) ||
184
+ !nonEmpty(contentExclusion?.rule) ||
185
+ storageFilesystem?.authority !== "host_filesystem" ||
186
+ storageFilesystem?.configured_path !== "use_as_provided" ||
187
+ storageFilesystem?.outcomes !== "ordinary_permissions_and_io" ||
188
+ storageFilesystem?.same_user_path_manipulation !== "outside_agentera_threat_model" ||
189
+ storageFilesystem?.symlink_confinement !== "not_claimed" ||
190
+ !nonEmpty(storageFilesystem?.rule) ||
191
+ !nonEmpty(persistence?.rule)) {
192
+ return [
193
+ "personal_mining_authority candidate projection must bound deterministic allocation, private retrieval, content exclusion, safe excerpts, host-filesystem storage, retention, and user-local replay",
194
+ ];
195
+ }
196
+ return [];
197
+ }
@@ -0,0 +1,104 @@
1
+ import { loadYamlMappingFile } from "../core/yaml.js";
2
+ import { projectGlossaryDevelopmentValue } from "../core/developmentInvocation.js";
3
+ import { glossaryEntryAuthorityPath } from "./glossaryEntryContract.js";
4
+ function mapping(value) {
5
+ return value !== null && typeof value === "object" && !Array.isArray(value)
6
+ ? value
7
+ : null;
8
+ }
9
+ function strings(value) {
10
+ return Array.isArray(value) && value.every((item) => typeof item === "string")
11
+ ? [...value]
12
+ : [];
13
+ }
14
+ /** Load the internal projection settings from the glossary authority. */
15
+ export function personalGlossaryCandidateProjectionContract(pathname = glossaryEntryAuthorityPath()) {
16
+ const authority = loadYamlMappingFile(pathname);
17
+ const mining = mapping(authority.personal_mining_authority);
18
+ const projection = mapping(mining?.candidate_projection);
19
+ const selection = mapping(projection?.selection);
20
+ const excerpts = mapping(projection?.excerpts);
21
+ const privacy = mapping(mining?.privacy);
22
+ const contentExclusion = mapping(privacy?.content_exclusion);
23
+ const retention = mapping(privacy?.retention);
24
+ const projectIdentity = mapping(selection?.project_identity);
25
+ const persistence = mapping(projection?.persistence);
26
+ const families = mapping(selection?.source_families);
27
+ const sourceFamilies = Object.fromEntries(Object.entries(families ?? {}).flatMap(([family, values]) => Array.isArray(values) && values.every((value) => typeof value === "string")
28
+ ? [[family, [...values]]]
29
+ : []));
30
+ const retrieval = mapping(mining?.candidate_retrieval);
31
+ const currentGeneration = mapping(retrieval?.current_generation);
32
+ const retrievalCommand = mapping(retrieval?.command);
33
+ const list = mapping(retrieval?.list);
34
+ const filters = mapping(list?.filters);
35
+ const cursor = mapping(list?.cursor);
36
+ const exact = mapping(retrieval?.exact);
37
+ const safeContextView = mapping(retrieval?.safe_context_view);
38
+ return {
39
+ schemaVersion: typeof projection?.schema_version === "string" ? projection.schema_version : "",
40
+ owner: typeof projection?.owner === "string" ? projection.owner : "",
41
+ candidatesMax: typeof selection?.candidates_max === "number" ? selection.candidates_max : 0,
42
+ projectIdsMaxPerCandidate: typeof selection?.project_ids_max_per_candidate === "number"
43
+ ? selection.project_ids_max_per_candidate
44
+ : 0,
45
+ sourceExcerptMaxUtf8Bytes: typeof excerpts?.source_max_utf8_bytes === "number" ? excerpts.source_max_utf8_bytes : 0,
46
+ pendingExcerptDays: typeof retention?.pending_excerpt_days === "number" ? retention.pending_excerpt_days : 0,
47
+ sourceFamilies,
48
+ selectionAlgorithm: typeof selection?.algorithm === "string" ? selection.algorithm : "",
49
+ tieBreak: typeof selection?.tie_break === "string" ? selection.tie_break : "",
50
+ projectIdentitySchemaVersion: typeof projectIdentity?.schema_version === "string" ? projectIdentity.schema_version : "",
51
+ storageFile: typeof persistence?.file === "string" ? persistence.file : "",
52
+ candidateSecretReason: typeof contentExclusion?.candidate_reason === "string"
53
+ ? contentExclusion.candidate_reason
54
+ : "",
55
+ excerptSensitiveContentAction: typeof contentExclusion?.excerpt_action === "string" ? contentExclusion.excerpt_action : "",
56
+ candidateReadCommand: projectGlossaryDevelopmentValue(retrievalCommand?.canonical, "candidate_retrieval.command"),
57
+ candidateReadSchemaVersion: typeof list?.schema_version === "string" ? list.schema_version : "",
58
+ candidateReadDefaultLimit: typeof list?.default_limit === "number" ? list.default_limit : 0,
59
+ candidateReadMaximumLimit: typeof list?.maximum_limit === "number" ? list.maximum_limit : 0,
60
+ candidateReadOrder: typeof list?.order === "string" ? list.order : "",
61
+ candidateReadListProjectionBindingField: typeof list?.projection_binding_field === "string" ? list.projection_binding_field : "",
62
+ candidateReadSourceFamilies: Object.keys(sourceFamilies),
63
+ candidateReadProvenanceKinds: [
64
+ ...new Set(Object.values(sourceFamilies).flat()),
65
+ ].sort(),
66
+ candidateReadScopes: strings(filters?.scope),
67
+ candidateReadMaxSerializedUtf8Bytes: typeof list?.max_serialized_utf8_bytes === "number"
68
+ ? list.max_serialized_utf8_bytes
69
+ : 0,
70
+ candidateReadCursorVocabulary: typeof cursor?.vocabulary === "string" ? cursor.vocabulary : "",
71
+ candidateReadCursorBinding: strings(cursor?.binding),
72
+ candidateReadCursorInvalidBehavior: typeof cursor?.invalid_behavior === "string" ? cursor.invalid_behavior : "",
73
+ candidateReadCursorUnavailableBehavior: typeof cursor?.unavailable_behavior === "string"
74
+ ? cursor.unavailable_behavior
75
+ : "",
76
+ candidateReadExactRequiredBindings: strings(exact?.required_bindings),
77
+ candidateReadExactProjectionBindingField: typeof exact?.projection_binding_field === "string" ? exact.projection_binding_field : "",
78
+ candidateReadExactOccurrencesMax: typeof exact?.occurrences_max === "number" ? exact.occurrences_max : 0,
79
+ candidateReadSafeContextMaxUtf8Bytes: typeof exact?.safe_context_max_utf8_bytes === "number"
80
+ ? exact.safe_context_max_utf8_bytes
81
+ : 0,
82
+ candidateReadExactMaxSerializedUtf8Bytes: typeof exact?.max_serialized_utf8_bytes === "number"
83
+ ? exact.max_serialized_utf8_bytes
84
+ : 0,
85
+ candidateReadCursorAuthority: typeof cursor?.authority === "string" ? cursor.authority : "",
86
+ candidateReadSafeContextViewAuthority: typeof safeContextView?.authority === "string" ? safeContextView.authority : "",
87
+ candidateReadSafeContextRetentionDays: typeof safeContextView?.retention_days === "number"
88
+ ? safeContextView.retention_days
89
+ : 0,
90
+ candidateReadSafeContextViewExpiry: typeof safeContextView?.expiry === "string" ? safeContextView.expiry : "",
91
+ candidateReadSafeContextViewMutation: typeof safeContextView?.mutation === "string" ? safeContextView.mutation : "",
92
+ candidateReadSafeContextViewSnapshot: typeof safeContextView?.snapshot === "string" ? safeContextView.snapshot : "",
93
+ candidateReadCurrentGenerationSource: typeof currentGeneration?.source === "string" ? currentGeneration.source : "",
94
+ candidateReadCurrentGenerationProjectionBinding: typeof currentGeneration?.projection_generation === "string"
95
+ ? currentGeneration.projection_generation
96
+ : "",
97
+ candidateReadCurrentGenerationUnavailableBehavior: typeof currentGeneration?.unavailable_behavior === "string"
98
+ ? currentGeneration.unavailable_behavior
99
+ : "",
100
+ candidateReadCurrentGenerationStaleProjectionBehavior: typeof currentGeneration?.stale_projection_behavior === "string"
101
+ ? currentGeneration.stale_projection_behavior
102
+ : "",
103
+ };
104
+ }