agentera 3.0.0-dev.76 → 3.0.0-dev.78

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 (57) hide show
  1. package/README.md +23 -0
  2. package/bundle/.agentera-build-source.json +5 -5
  3. package/bundle/CHANGELOG.md +10 -1
  4. package/bundle/UPGRADE.md +24 -5
  5. package/bundle/references/adapters/package-publication.json +4 -4
  6. package/bundle/references/adapters/package-registry.yaml +153 -151
  7. package/bundle/references/adapters/product-v1-reset.yaml +101 -0
  8. package/bundle/references/artifacts/glossary-entry-contract.yaml +163 -9
  9. package/bundle/references/artifacts/state-storage-authority.yaml +0 -5
  10. package/bundle/references/cli/update-channels.yaml +1 -1
  11. package/bundle/references/cli/vocabulary-index.yaml +2 -2
  12. package/bundle/references/cli/vocabulary.md +2 -3
  13. package/bundle/references/meta/retained-reference-authority.yaml +5 -0
  14. package/bundle/skills/agentera/schemas/artifacts/decisions.yaml +1 -20
  15. package/bundle/skills/agentera/schemas/artifacts/docs.yaml +0 -31
  16. package/bundle/skills/agentera/schemas/artifacts/experiments.yaml +0 -25
  17. package/bundle/skills/agentera/schemas/artifacts/glossary.yaml +1 -1
  18. package/bundle/skills/agentera/schemas/artifacts/health.yaml +1 -36
  19. package/bundle/skills/agentera/schemas/artifacts/objective.yaml +0 -31
  20. package/bundle/skills/agentera/schemas/artifacts/plan.yaml +1 -35
  21. package/bundle/skills/agentera/schemas/artifacts/progress.yaml +1 -25
  22. package/bundle/skills/agentera/schemas/artifacts/vision.yaml +0 -19
  23. package/dist/.agentera-build-source.json +5 -5
  24. package/dist/analytics/personalGlossaryAdmission.js +1 -1
  25. package/dist/analytics/personalGlossaryCandidateProjection.js +96 -0
  26. package/dist/analytics/personalGlossaryCandidateProjectionModel.js +1 -0
  27. package/dist/analytics/personalGlossaryRefreshProjection.js +351 -0
  28. package/dist/capabilities/status/instructions.js +1 -1
  29. package/dist/cli/commands/personalGlossaryCandidateReads.js +12 -1
  30. package/dist/cli/commands/prime/briefOrientation.js +1 -1
  31. package/dist/cli/commands/prime/collectOrientationState.js +0 -7
  32. package/dist/cli/commands/prime/orientationOutput.js +3 -9
  33. package/dist/cli/commands/report.js +98 -8
  34. package/dist/cli/commands/upgrade.js +30 -0
  35. package/dist/cli/dispatch/index.js +7 -0
  36. package/dist/cli/dispatch/lifecycle.js +20 -0
  37. package/dist/cli/help.js +10 -3
  38. package/dist/cli/orientation/attention.js +1 -4
  39. package/dist/cli/productV1Eol.js +55 -0
  40. package/dist/cli/startupCompletenessContract.js +0 -1
  41. package/dist/cli/stateQuery.js +1 -1
  42. package/dist/registries/activationTuples.js +11 -2
  43. package/dist/registries/glossaryCandidateProjectionAuthority.js +154 -6
  44. package/dist/registries/glossaryCandidateProjectionContract.js +4 -0
  45. package/dist/registries/glossaryEntryContract.js +3 -3
  46. package/dist/registries/packagePublication.js +2 -2
  47. package/dist/runtime/nativeResourceCleanup.js +1 -0
  48. package/dist/upgrade/legacyAgentCleanup.js +1 -1
  49. package/dist/upgrade/migrateArtifactsV2ToV3.js +1 -27
  50. package/dist/upgrade/nextMajorDoctor.js +0 -21
  51. package/dist/upgrade/productV1Reset.js +515 -0
  52. package/dist/upgrade/productV1ResetAuthority.js +139 -0
  53. package/dist/upgrade/projectIntegration.js +4 -6
  54. package/dist/upgrade/upgradeOrchestrator.js +4 -12
  55. package/dist/validate/{v1LegacyCruft.js → glossaryVariantGuard.js} +3 -38
  56. package/package.json +2 -2
  57. package/dist/cli/commands/prime/v1Migration.js +0 -38
@@ -12,13 +12,61 @@ function sameStrings(actual, expected) {
12
12
  function nonEmpty(value) {
13
13
  return typeof value === "string" && value.trim().length > 0;
14
14
  }
15
+ const EXPLICIT_ABSTENTION_KEYS = [
16
+ "attributed_quotation",
17
+ "ambiguous_reference",
18
+ "conflicting_meaning",
19
+ "empty_meaning",
20
+ "empty_term",
21
+ "example_context",
22
+ "hypothetical_definition",
23
+ "malformed_span",
24
+ "meaning_bound_exceeded",
25
+ "negated_definition",
26
+ "indirect_question",
27
+ "future_definition",
28
+ "project_only_scope",
29
+ "question_definition",
30
+ "retracted_definition",
31
+ "sarcasm_marker",
32
+ "stale_anchor",
33
+ "structural_fragment",
34
+ "term_bound_exceeded",
35
+ "unsafe_syntax",
36
+ "uncertain_scope",
37
+ "unresolved_anchor",
38
+ "provenance_incomplete",
39
+ "user_authorship_required",
40
+ ];
41
+ const RECURRING_ABSTENTION_KEYS = [
42
+ "agent_only_evidence",
43
+ "copied_content",
44
+ "provenance_missing",
45
+ "insufficient_independent_origins",
46
+ "insufficient_projects",
47
+ "insufficient_sessions",
48
+ "conversation_evidence_incomplete",
49
+ "conversation_evidence_bound_exceeded",
50
+ "project_only_scope",
51
+ "noise_term",
52
+ "too_many_qualifying_origins",
53
+ "user_authorship_required",
54
+ ];
15
55
  /** Validate the authority-owned bounds for the internal candidate projection. */
16
56
  export function validatePersonalCandidateProjectionAuthority(authority) {
17
57
  const mining = mapping(authority.personal_mining_authority);
18
58
  const projection = mapping(mining?.candidate_projection);
59
+ const refreshProduction = mapping(projection?.refresh_production);
60
+ const refreshProjection = mapping(refreshProduction?.projection);
61
+ const refreshConcurrency = mapping(refreshProduction?.concurrency);
62
+ const refreshContender = mapping(refreshConcurrency?.contender);
63
+ const partialFailure = mapping(refreshProduction?.partial_failure);
64
+ const safeReplacement = mapping(refreshProduction?.safe_replacement);
19
65
  const selection = mapping(projection?.selection);
20
66
  const sourceFamilies = mapping(selection?.source_families);
21
67
  const projectIdentity = mapping(selection?.project_identity);
68
+ const miningSummary = mapping(projection?.mining_summary);
69
+ const summaryReconciliation = mapping(miningSummary?.reconciliation);
22
70
  const excerpts = mapping(projection?.excerpts);
23
71
  const excerptCompatibility = mapping(excerpts?.compatibility);
24
72
  const retention = mapping(projection?.retention);
@@ -35,6 +83,109 @@ export function validatePersonalCandidateProjectionAuthority(authority) {
35
83
  const privacy = mapping(mining?.privacy);
36
84
  const contentExclusion = mapping(privacy?.content_exclusion);
37
85
  const storageFilesystem = mapping(mapping(privacy?.storage)?.filesystem);
86
+ const malformedProjectionReplacementException = mapping(storageFilesystem?.malformed_candidate_projection_replacement_exception);
87
+ const errors = [];
88
+ if (refreshProduction?.status !== "active" ||
89
+ refreshProduction?.runtime !==
90
+ "packages/cli/src/analytics/personalGlossaryRefreshProjection.ts#produceCurrentPersonalGlossaryProjection" ||
91
+ refreshProduction?.trigger !== "explicit_consented_evidence_refresh_success" ||
92
+ refreshProjection?.count !== "exactly_one" ||
93
+ refreshProjection?.generation_binding !== "exact_published_evidence_generation" ||
94
+ refreshProjection?.policy_binding !== "exact_personal_mining_policy_version" ||
95
+ !nonEmpty(refreshProduction?.rule)) {
96
+ errors.push("personal_mining_authority refresh production must require one projection bound to the exact evidence generation and mining policy");
97
+ }
98
+ if (refreshConcurrency?.serialization !== "profile_local_exclusive_refresh_commit" ||
99
+ refreshConcurrency?.lock_lifetime !==
100
+ "before_evidence_publication_through_projection_binding_verification" ||
101
+ refreshContender?.refresh_outcome !== "failure" ||
102
+ refreshContender?.process_exit !== "nonzero" ||
103
+ refreshContender?.local_history_read !== false ||
104
+ refreshContender?.tier_write !== false ||
105
+ refreshContender?.projection_status !== "failed" ||
106
+ refreshContender?.projection_write !== false ||
107
+ refreshContender?.evidence_status !== "current_generation_remains_readable" ||
108
+ refreshContender?.recovery !== "npx -y agentera@next report refresh --consent local-history") {
109
+ errors.push("personal_mining_authority refresh production must serialize evidence and projection commit and fail contenders without writes");
110
+ }
111
+ if (partialFailure?.refresh_outcome !== "failure" ||
112
+ partialFailure?.process_exit !== "nonzero" ||
113
+ partialFailure?.evidence_status !== "published" ||
114
+ partialFailure?.projection_status !== "failed" ||
115
+ partialFailure?.tier_write_reporting !== "evidence_published_projection_not_written" ||
116
+ partialFailure?.current_generation !== "published_evidence_remains_current") {
117
+ errors.push("personal_mining_authority refresh production must report evidence and projection outcomes separately and preserve published evidence on projection failure");
118
+ }
119
+ if (safeReplacement?.authorization !== "explicit_consented_refresh_only" ||
120
+ safeReplacement?.target !== "exact_configured_candidate_projection_file" ||
121
+ safeReplacement?.precondition !== "existing_owned_regular_file_is_malformed" ||
122
+ safeReplacement?.operation !== "atomic_regular_file_replacement" ||
123
+ !sameStrings(safeReplacement?.reject, [
124
+ "symlink",
125
+ "non_regular_file",
126
+ "configured_path_mismatch",
127
+ "path_escape",
128
+ ]) ||
129
+ safeReplacement?.filesystem_exception !==
130
+ "personal_mining_authority.privacy.storage.filesystem.malformed_candidate_projection_replacement_exception" ||
131
+ !sameStrings(safeReplacement?.replaceable_state, ["candidate_projection"]) ||
132
+ !sameStrings(safeReplacement?.preserved_state, [
133
+ "current_evidence_generation",
134
+ "review_records",
135
+ "personal_profile",
136
+ "project_state",
137
+ "project_glossary",
138
+ ])) {
139
+ errors.push("personal_mining_authority refresh replacement must target only the exact owned regular projection and preserve evidence, review, profile, and project state");
140
+ }
141
+ if (malformedProjectionReplacementException?.scope !==
142
+ "malformed_candidate_projection_replacement_only" ||
143
+ malformedProjectionReplacementException?.authorization !== "explicit_consented_refresh_only" ||
144
+ malformedProjectionReplacementException?.precondition !==
145
+ "existing_owned_regular_file_is_malformed" ||
146
+ malformedProjectionReplacementException?.target !==
147
+ "exact_configured_candidate_projection_file" ||
148
+ malformedProjectionReplacementException?.inspection !==
149
+ "lstat_exact_target_without_following_symlinks" ||
150
+ malformedProjectionReplacementException?.required_type !== "regular_file" ||
151
+ !sameStrings(malformedProjectionReplacementException?.reject, [
152
+ "symlink",
153
+ "non_regular_file",
154
+ "configured_path_mismatch",
155
+ "path_escape",
156
+ ]) ||
157
+ malformedProjectionReplacementException?.operation !== "atomic_regular_file_replacement" ||
158
+ malformedProjectionReplacementException?.outside_scope !== "configured_path_use_as_provided") {
159
+ errors.push("personal_mining_authority filesystem exception must confine malformed projection replacement to the exact configured regular file with no-follow inspection");
160
+ }
161
+ if (miningSummary?.schema_version !== "agentera.personalGlossaryMiningSummary.v1" ||
162
+ miningSummary?.location !== "report.mining_summary" ||
163
+ !sameStrings(miningSummary?.family_fields, [
164
+ "candidate_count",
165
+ "abstention_count",
166
+ "abstentions_by_reason",
167
+ ]) ||
168
+ !sameStrings(miningSummary?.explicit_abstention_keys, EXPLICIT_ABSTENTION_KEYS) ||
169
+ !sameStrings(miningSummary?.recurring_abstention_keys, RECURRING_ABSTENTION_KEYS) ||
170
+ summaryReconciliation?.fixed_keys !== "all_keys_present_as_nonnegative_integers" ||
171
+ summaryReconciliation?.family_abstentions !== "abstention_count_equals_sum_of_reason_counts" ||
172
+ summaryReconciliation?.total_candidates !==
173
+ "total_equals_explicit_plus_recurring_candidate_counts" ||
174
+ summaryReconciliation?.total_abstentions !==
175
+ "total_equals_explicit_plus_recurring_abstention_counts" ||
176
+ summaryReconciliation?.projection_input !== "report_input_count_equals_total_candidate_count" ||
177
+ !sameStrings(miningSummary?.forbidden_content, [
178
+ "terms",
179
+ "source_ids",
180
+ "evidence_anchors",
181
+ "project_ids",
182
+ "project_keys",
183
+ "paths",
184
+ "excerpts",
185
+ ]) ||
186
+ !nonEmpty(miningSummary?.rule)) {
187
+ errors.push("personal_mining_authority candidate projection must retain reconciled fixed-key aggregate mining counts without sensitive identity or content");
188
+ }
38
189
  if (projection?.status !== "active" ||
39
190
  projection?.runtime !==
40
191
  "packages/cli/src/analytics/personalGlossaryCandidateProjection.ts#projectPersonalGlossaryCandidates" ||
@@ -106,8 +257,7 @@ export function validatePersonalCandidateProjectionAuthority(authority) {
106
257
  currentGeneration?.unavailable_behavior !== "current_generation_unavailable" ||
107
258
  currentGeneration?.stale_projection_behavior !== "projection_stale" ||
108
259
  !nonEmpty(retrieval?.rule) ||
109
- retrievalCommand?.canonical !==
110
- "npx -y agentera@next report personal-glossary-candidates" ||
260
+ retrievalCommand?.canonical !== "npx -y agentera@next report personal-glossary-candidates" ||
111
261
  retrievalCommand?.namespace !== "report" ||
112
262
  retrievalCommand?.format !== "json" ||
113
263
  retrievalCommand?.project_checkout !== "not_required" ||
@@ -189,9 +339,7 @@ export function validatePersonalCandidateProjectionAuthority(authority) {
189
339
  storageFilesystem?.symlink_confinement !== "not_claimed" ||
190
340
  !nonEmpty(storageFilesystem?.rule) ||
191
341
  !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
- ];
342
+ errors.push("personal_mining_authority candidate projection must bound deterministic allocation, private retrieval, content exclusion, safe excerpts, host-filesystem storage, retention, and user-local replay");
195
343
  }
196
- return [];
344
+ return errors;
197
345
  }
@@ -23,6 +23,7 @@ export function personalGlossaryCandidateProjectionContract(pathname = glossaryE
23
23
  const retention = mapping(privacy?.retention);
24
24
  const projectIdentity = mapping(selection?.project_identity);
25
25
  const persistence = mapping(projection?.persistence);
26
+ const miningSummary = mapping(projection?.mining_summary);
26
27
  const families = mapping(selection?.source_families);
27
28
  const sourceFamilies = Object.fromEntries(Object.entries(families ?? {}).flatMap(([family, values]) => Array.isArray(values) && values.every((value) => typeof value === "string")
28
29
  ? [[family, [...values]]]
@@ -53,6 +54,9 @@ export function personalGlossaryCandidateProjectionContract(pathname = glossaryE
53
54
  ? contentExclusion.candidate_reason
54
55
  : "",
55
56
  excerptSensitiveContentAction: typeof contentExclusion?.excerpt_action === "string" ? contentExclusion.excerpt_action : "",
57
+ miningSummarySchemaVersion: typeof miningSummary?.schema_version === "string" ? miningSummary.schema_version : "",
58
+ explicitAbstentionKeys: strings(miningSummary?.explicit_abstention_keys),
59
+ recurringAbstentionKeys: strings(miningSummary?.recurring_abstention_keys),
56
60
  candidateReadCommand: projectGlossaryDevelopmentValue(retrievalCommand?.canonical, "candidate_retrieval.command"),
57
61
  candidateReadSchemaVersion: typeof list?.schema_version === "string" ? list.schema_version : "",
58
62
  candidateReadDefaultLimit: typeof list?.default_limit === "number" ? list.default_limit : 0,
@@ -388,8 +388,8 @@ export function validateGlossaryEntryContract(pathname = glossaryEntryAuthorityP
388
388
  errors.push("project glossary digest and build publication must remain active under the declared consumer boundary");
389
389
  }
390
390
  if (confirmedVariantGuard?.owner !==
391
- "packages/cli/src/validate/v1LegacyCruft.ts#scanPost30CruftViolations" ||
392
- confirmedVariantGuard?.validation_surface !== "packages/cli/test/cli/v1LegacyCruft.test.ts" ||
391
+ "packages/cli/src/validate/glossaryVariantGuard.ts#scanConfirmedVariantViolations" ||
392
+ confirmedVariantGuard?.validation_surface !== "packages/cli/test/cli/glossaryVariantGuard.test.ts" ||
393
393
  confirmedVariantGuard?.loader !==
394
394
  "packages/cli/src/state/write/glossaryPublication.ts#loadProjectGlossaryDocument" ||
395
395
  confirmedVariantGuard?.matching !== "exact_case_sensitive_boundary_aware_literal" ||
@@ -424,7 +424,7 @@ export function validateGlossaryEntryContract(pathname = glossaryEntryAuthorityP
424
424
  "vendor",
425
425
  ]) ||
426
426
  !nonEmpty(confirmedVariantGuard?.exclusion_rule)) {
427
- errors.push("confirmed variant guard must reuse validated project glossary pairs and bounded legacy-cruft exclusions");
427
+ errors.push("confirmed variant guard must reuse validated project glossary pairs and bounded exclusions");
428
428
  }
429
429
  if (proposalValidation?.owner !== "audit" ||
430
430
  proposalValidation?.shared_runtime !==
@@ -52,12 +52,12 @@ export const ACTIVATION_CENSUS_AUTHORITY = deepFreeze({
52
52
  cli: { count: 27, sha256: "986a637f5c11c57ab7a897a01bd291d0811846e5339c3831c715932cf9659ad4" },
53
53
  capability: { count: 12, sha256: "007e1157a892fec54182b1803aeaa442cf8e2e332e6a055c3bd020e2b0731867" },
54
54
  runtime: { count: 81, sha256: "03fe600a3a27f05daf0d1b59c16b00bedc354a13c70ea60be0b457175fdf743c" },
55
- reference: { count: 25, sha256: "2094946cd6e189c6ab3db16dd0725596cec759abcea88d8335b05215b65ccfc2" },
55
+ reference: { count: 26, sha256: "aa1ad513d89b66c9133a8572cef2dce760e76d6ee39d2ffa2d4e312578dcc847" },
56
56
  state: { count: 38, sha256: "7ab0dd6ef1b1b1ce66bd9ea94d1de3d542528233e928a44102e289bf12416681" },
57
57
  package: { count: 67, sha256: "d73cd86fed39057cf9ae73e462a59e842372392b1e88846f2b220378a2ff75cc" },
58
58
  bootstrap: { count: 34, sha256: "71c2038744e2518a6adb722acbb5f9352bddfb5d1c92eeb0e347297ef2ca2f1e" },
59
59
  },
60
- total: { count: 284, sha256: "3f30b26839aec47639f2197c9efda5caf2a73d5afca9fb38ff9a341e18a72b98" },
60
+ total: { count: 285, sha256: "042700a26b34afba57b60eaf4a4529d9e02ce39d8574e6883dfb892eebc64fd5" },
61
61
  });
62
62
  /** Each dimension names the production contract it observes independently. */
63
63
  export const ACTIVATION_EVIDENCE_SOURCES = deepFreeze({
@@ -313,6 +313,7 @@ export function loadNativeResourceCleanupContract(contractPath = path.join(resol
313
313
  configuration: data.configuration_inventory.map((unit) => ({
314
314
  id: unit.id,
315
315
  host: unit.host,
316
+ destination: unit.destination,
316
317
  key: unit.key,
317
318
  })),
318
319
  };
@@ -204,7 +204,7 @@ export function scanLegacyCapabilityAgentPaths(agentsDir) {
204
204
  }
205
205
  return hits.sort();
206
206
  }
207
- /** Scan a tree for reintroduced Swedish-verb agents (v1LegacyCruft-style guard). */
207
+ /** Scan a tree for reintroduced Swedish-verb agents. */
208
208
  export function scanLegacySwedishVerbAgentViolations(root) {
209
209
  const resolved = resolvePath(root);
210
210
  const violations = [];
@@ -19,14 +19,6 @@ import { applyInstalledHooksRetirementItems, planInstalledHooksRetirementItems,
19
19
  * v2→v3 migration phases: artifacts (noop for YAML), runtime rewire, cleanup.
20
20
  */
21
21
  export const MIGRATION_STATUSES = ["pending", "applied", "noop", "blocked", "failed"];
22
- export const V1_ARTIFACT_PAIRS = [
23
- [".agentera/PROGRESS.md", ".agentera/progress.yaml"],
24
- [".agentera/PLAN.md", ".agentera/plan.yaml"],
25
- [".agentera/DECISIONS.md", ".agentera/decisions.yaml"],
26
- [".agentera/HEALTH.md", ".agentera/health.yaml"],
27
- [".agentera/DOCS.md", ".agentera/docs.yaml"],
28
- ["VISION.md", ".agentera/vision.yaml"],
29
- ];
30
22
  const PLAN_ARCHIVE_FILE = /^PLAN-.+\.ya?ml$/i;
31
23
  const PLAN_LIFECYCLE_ACTION = "normalize-plan-lifecycle";
32
24
  function isMapping(value) {
@@ -178,16 +170,6 @@ export function summarizePhase(name, items, message = "") {
178
170
  }
179
171
  return { name, status, summary, items, message };
180
172
  }
181
- export function detectV1ArtifactPairs(project) {
182
- const root = resolvePath(project);
183
- const found = [];
184
- for (const [md, yaml] of V1_ARTIFACT_PAIRS) {
185
- if (isFile(path.join(root, md)) && !isFile(path.join(root, yaml))) {
186
- found.push(md);
187
- }
188
- }
189
- return found;
190
- }
191
173
  function listV2YamlArtifacts(project) {
192
174
  const root = resolvePath(project);
193
175
  const agenteraDir = path.join(root, ".agentera");
@@ -218,21 +200,13 @@ export function planArtifactsPhase(project) {
218
200
  },
219
201
  ]);
220
202
  }
221
- const v1Pairs = detectV1ArtifactPairs(root);
222
- const v1Items = v1Pairs.map((source) => ({
223
- status: "blocked",
224
- action: "manual-v1-handoff",
225
- source,
226
- message: "v1 Markdown state is unsupported; convert it with a v2 CLI before running the v2-to-v3 upgrade",
227
- }));
228
203
  const yamlArtifacts = listV2YamlArtifacts(root);
229
204
  const lifecycleItems = lifecyclePlanArtifacts(root);
230
- if (yamlArtifacts.length === 0 && v1Items.length === 0 && lifecycleItems.length === 0) {
205
+ if (yamlArtifacts.length === 0 && lifecycleItems.length === 0) {
231
206
  return summarizePhase("artifacts", [], "no project artifacts found");
232
207
  }
233
208
  const lifecycleSources = new Set(lifecycleItems.flatMap((item) => item.source ? [item.source] : []));
234
209
  const items = [
235
- ...v1Items,
236
210
  ...yamlArtifacts.filter((source) => !lifecycleSources.has(source)).map((source) => ({
237
211
  status: "noop",
238
212
  action: "preserve",
@@ -7,19 +7,6 @@ import { resolveRunningVersion } from "./versionResolution.js";
7
7
  */
8
8
  export const NEXT_MAJOR_SECTION_HEADER = "Next major";
9
9
  export const NEXT_MAJOR_LINE_CAP = 6;
10
- /** v1 installs predate the channel authority; hardcoded stable-line successor mapping. */
11
- export const V1_NEXT_MAJOR_FALLBACK = {
12
- concept: "forward_successor_line",
13
- currentVersion: "1.x",
14
- currentChannel: "stable",
15
- channel: "stable",
16
- version: "2.x",
17
- announced: true,
18
- npmOnlyAdvisory: "",
19
- guideUrl: "https://github.com/jgabor/agentera/blob/main/UPGRADE.md#recommended-upgrade-v1--v2-stable-channel",
20
- previewCommand: "npx -y agentera@latest upgrade --dry-run",
21
- irreversibleAdvisory: "Forward migration upgrades artifact format from Markdown to YAML; review the preview before applying.",
22
- };
23
10
  function parseNextMajorBlock(raw) {
24
11
  if (raw === null || raw === undefined) {
25
12
  return null;
@@ -120,14 +107,6 @@ export function resolveNextMajorDoctorLines(ctx) {
120
107
  const displayChannel = install?.kind === "v2_managed_app_home" ? "stable" : currentChannel;
121
108
  const runningDistributionMajor = ctx.runningDistributionMajor ??
122
109
  (install?.kind === "v2_managed_app_home" ? 2 : cliDistributionMajor(sourceRoot));
123
- if (runningDistributionMajor === 1) {
124
- const block = V1_NEXT_MAJOR_FALLBACK;
125
- return formatNextMajorDoctorLines({
126
- currentVersion: block.currentVersion,
127
- currentChannel: block.currentChannel,
128
- block,
129
- });
130
- }
131
110
  const authorityBlock = loadChannelNextMajor(sourceRoot, successorChannel);
132
111
  if (!authorityBlock || !authorityBlock.announced) {
133
112
  return null;