nexarch 0.9.28 → 0.9.30

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.
@@ -1480,21 +1480,10 @@ export async function initProject(args) {
1480
1480
  if (detectedRepo?.canonicalRepoRef) {
1481
1481
  addRel("depends_on", projectExternalKey, detectedRepo.canonicalRepoRef, 0.95);
1482
1482
  }
1483
- let graphDiff = null;
1483
+ // In refresh mode the raw graph state (fetched above) is emitted alongside scan results
1484
+ // for the agent to compare — no automated stale/removed determination is made.
1484
1485
  if (refreshMode) {
1485
- const newRelKeySet = new Set(relationships.map((r) => `${r.relationshipTypeCode}::${r.fromEntityExternalKey}::${r.toEntityExternalKey}`));
1486
- const currentRelKeySet = new Set(currentOutgoingRels
1487
- .filter((r) => r.fromEntityExternalKey && r.toEntityExternalKey)
1488
- .map((r) => `${r.relationshipTypeCode}::${r.fromEntityExternalKey}::${r.toEntityExternalKey}`));
1489
- const newRelationshipsInDiff = relationships.filter((r) => !currentRelKeySet.has(`${r.relationshipTypeCode}::${r.fromEntityExternalKey}::${r.toEntityExternalKey}`));
1490
- const staleRelationships = currentOutgoingRels.filter((r) => r.fromEntityExternalKey &&
1491
- r.toEntityExternalKey &&
1492
- !newRelKeySet.has(`${r.relationshipTypeCode}::${r.fromEntityExternalKey}::${r.toEntityExternalKey}`));
1493
- const currentSubPackageKeys = new Set(currentPartOfRels.map((r) => r.fromEntityExternalKey).filter((k) => Boolean(k)));
1494
- const newSubPackageKeys = new Set(subPackages.map((sp) => sp.externalKey));
1495
- const removedSubPackageKeys = [...currentSubPackageKeys].filter((k) => !newSubPackageKeys.has(k));
1496
- graphDiff = { newRelationships: newRelationshipsInDiff, staleRelationships, removedSubPackageKeys };
1497
- logProgress("refresh.diff", `newRels=${newRelationshipsInDiff.length}, staleRels=${staleRelationships.length}, removedSubPkgs=${removedSubPackageKeys.length}`);
1486
+ logProgress("refresh.graph-state", `outgoing=${currentOutgoingRels.length}, partOf=${currentPartOfRels.length}`);
1498
1487
  }
1499
1488
  if (!asJson)
1500
1489
  console.log(`\nWriting to graph…`);
@@ -1633,13 +1622,52 @@ export async function initProject(args) {
1633
1622
  });
1634
1623
  return {
1635
1624
  status: "enrichment_required",
1636
- note: "IMPORTANT: Execute ALL pendingSteps before reporting the project as registered. Do not pause or ask for confirmation between steps.",
1625
+ note: refreshMode
1626
+ ? "Execute ALL pendingSteps. In refresh mode, compare graphState vs scanState to identify gaps — do not blindly remove relationships the scanner missed; the scanner cannot detect platforms, integrations, data assets, or application_functions."
1627
+ : "Execute ALL pendingSteps before reporting the project as registered. Do not pause or ask for confirmation between steps.",
1637
1628
  projectEntity: {
1638
1629
  externalKey: projectExternalKey,
1639
1630
  entityType: entityTypeOverride,
1640
1631
  },
1641
1632
  pendingSteps,
1642
1633
  readFiles: readmeHints,
1634
+ ...(refreshMode
1635
+ ? {
1636
+ graphState: {
1637
+ note: "Current relationships recorded in Nexarch for this project.",
1638
+ outgoingRelationships: currentOutgoingRels.map((r) => ({
1639
+ type: r.relationshipTypeCode,
1640
+ from: r.fromEntityExternalKey ?? null,
1641
+ to: r.toEntityExternalKey ?? null,
1642
+ fromName: r.fromEntityName ?? null,
1643
+ toName: r.toEntityName ?? null,
1644
+ status: r.status,
1645
+ })),
1646
+ partOfChildren: currentPartOfRels.map((r) => ({
1647
+ type: r.relationshipTypeCode,
1648
+ from: r.fromEntityExternalKey ?? null,
1649
+ to: r.toEntityExternalKey ?? null,
1650
+ fromName: r.fromEntityName ?? null,
1651
+ toName: r.toEntityName ?? null,
1652
+ status: r.status,
1653
+ })),
1654
+ },
1655
+ scanState: {
1656
+ note: "What the manifest scanner detected this run. The scanner can only detect npm/package.json dependencies — it cannot detect platforms, integrations, data assets, or application_function relationships.",
1657
+ detectedRelationships: relationships.map((r) => ({
1658
+ type: r.relationshipTypeCode,
1659
+ from: r.fromEntityExternalKey,
1660
+ to: r.toEntityExternalKey,
1661
+ })),
1662
+ detectedEntityKeys: entities.map((e) => e.externalKey),
1663
+ },
1664
+ agentGuidance: {
1665
+ compareInstructions: "Compare graphState with scanState. Relationships in graphState but absent from scanState are NOT automatically stale — the scanner only sees npm dependencies. Only retire a relationship if you have read the codebase and confirmed the dependency no longer exists.",
1666
+ scannerBlindSpots: ["platforms (e.g. Vercel, AWS, Neon)", "integrations", "data assets", "application_function entities", "manual relationships added by previous enrichment"],
1667
+ actionRequired: "Review graphState relationships that have no match in scanState. For each one: read the codebase to confirm whether the relationship still applies, then either keep it or retire it with nexarch retire-relationship.",
1668
+ },
1669
+ }
1670
+ : {}),
1643
1671
  classifyPackages: subPackages.map((sp) => {
1644
1672
  const resolvedDeps = sp.depSpecs
1645
1673
  .map((d) => resolvedByInput.get(d.name))
@@ -1675,25 +1703,6 @@ export async function initProject(args) {
1675
1703
  provider: "lucide",
1676
1704
  note: "Use any Lucide icon name (kebab-case); omit when confidence is low.",
1677
1705
  },
1678
- ...(graphDiff
1679
- ? {
1680
- diff: {
1681
- newRelationships: graphDiff.newRelationships.map((r) => ({
1682
- type: r.relationshipTypeCode,
1683
- from: r.fromEntityExternalKey,
1684
- to: r.toEntityExternalKey,
1685
- })),
1686
- staleRelationships: graphDiff.staleRelationships.map((r) => ({
1687
- type: r.relationshipTypeCode,
1688
- from: r.fromEntityExternalKey,
1689
- to: r.toEntityExternalKey,
1690
- fromName: r.fromEntityName ?? null,
1691
- toName: r.toEntityName ?? null,
1692
- })),
1693
- removedSubPackageKeys: graphDiff.removedSubPackageKeys,
1694
- },
1695
- }
1696
- : {}),
1697
1706
  };
1698
1707
  }
1699
1708
  // Build an agent-directed directive block for human/terminal output.
@@ -1702,7 +1711,7 @@ export async function initProject(args) {
1702
1711
  function buildEnrichmentDirective() {
1703
1712
  const lines = [];
1704
1713
  lines.push("─── ENRICHMENT REQUIRED ─────────────────────────────────────────────────");
1705
- lines.push("init-project wrote a skeleton. Complete enrichment NOW — do not ask the");
1714
+ lines.push("init-project wrote a skeleton. Complete enrichment below — do not ask the");
1706
1715
  lines.push("user for permission, do not summarise and pause, just execute the steps.");
1707
1716
  lines.push("Do NOT report the project as registered until enrichment is done.");
1708
1717
  lines.push("");
@@ -1751,7 +1760,7 @@ export async function initProject(args) {
1751
1760
  lines.push(` … and ${unresolvedItems.length - 20} more`);
1752
1761
  }
1753
1762
  lines.push("");
1754
- lines.push("THEN_RUN (execute these steps immediately — do not pause or ask for confirmation):");
1763
+ lines.push("THEN_RUN (execute these steps — do not pause or ask for confirmation):");
1755
1764
  let step = 1;
1756
1765
  lines.push(` ${step++}. nexarch update-entity --key "${projectExternalKey}" --entity-type "${entityTypeOverride}"${entityTypeOverride === "application" ? ' --subtype "<subtype>" --icon "<lucide-icon>"' : ""} --name "..." --description "..."`);
1757
1766
  if (entityTypeOverride === "application") {
@@ -1781,25 +1790,17 @@ export async function initProject(args) {
1781
1790
  lines.push(" apps/* (deployable components) → parent composes → sub-application");
1782
1791
  lines.push(" packages/* (shared libraries) → parent depends_on → library");
1783
1792
  lines.push(" Deps wired from manifests are already pre-wired; do not re-add unless key changed.");
1784
- if (graphDiff) {
1785
- if (graphDiff.staleRelationships.length > 0) {
1786
- lines.push("");
1787
- lines.push(`STALE_RELATIONSHIPS (${graphDiff.staleRelationships.length} in graph but no longer in manifests; review and retire if confirmed removed):`);
1788
- for (const r of graphDiff.staleRelationships) {
1789
- const from = r.fromEntityExternalKey ?? r.fromEntityName ?? "?";
1790
- const to = r.toEntityExternalKey ?? r.toEntityName ?? "?";
1791
- lines.push(` [${r.relationshipTypeCode}] ${from} → ${to}`);
1792
- }
1793
- }
1794
- if (graphDiff.removedSubPackageKeys.length > 0) {
1795
- lines.push("");
1796
- lines.push(`REMOVED_SUB_PACKAGES (${graphDiff.removedSubPackageKeys.length} — previously registered but no longer found in filesystem; retire or reassign):`);
1797
- for (const k of graphDiff.removedSubPackageKeys)
1798
- lines.push(` ${k}`);
1799
- }
1800
- if (graphDiff.staleRelationships.length === 0 && graphDiff.removedSubPackageKeys.length === 0) {
1801
- lines.push("");
1802
- lines.push("DIFF: No stale relationships or removed sub-packages detected.");
1793
+ if (refreshMode && (currentOutgoingRels.length > 0 || currentPartOfRels.length > 0)) {
1794
+ lines.push("");
1795
+ lines.push(`GRAPH_STATE (${currentOutgoingRels.length + currentPartOfRels.length} current relationships in Nexarch — compare against what the scanner detected above):`);
1796
+ lines.push(" The scanner only sees npm dependencies. The following relationships may include platforms,");
1797
+ lines.push(" integrations, data assets, and application_functions that are invisible to the scanner.");
1798
+ lines.push(" Do NOT retire a relationship just because it is absent from the scan read the codebase first.");
1799
+ lines.push(" If you confirm a relationship no longer applies, use: nexarch retire-relationship --id <id>");
1800
+ for (const r of [...currentOutgoingRels, ...currentPartOfRels]) {
1801
+ const from = r.fromEntityExternalKey ?? r.fromEntityName ?? "?";
1802
+ const to = r.toEntityExternalKey ?? r.toEntityName ?? "?";
1803
+ lines.push(` [${r.relationshipTypeCode}] ${from} → ${to} (${r.status})`);
1803
1804
  }
1804
1805
  }
1805
1806
  lines.push("");
@@ -1856,11 +1857,8 @@ export async function initProject(args) {
1856
1857
  if (unresolvedItems.length > 0) {
1857
1858
  console.log(` Candidates : ${unresolvedItems.length} added to reference candidates`);
1858
1859
  }
1859
- if (graphDiff && graphDiff.staleRelationships.length > 0) {
1860
- console.log(` Stale rels : ${graphDiff.staleRelationships.length} in graph but absent from manifests (see STALE_RELATIONSHIPS below)`);
1861
- }
1862
- if (graphDiff && graphDiff.removedSubPackageKeys.length > 0) {
1863
- console.log(` Removed pkgs : ${graphDiff.removedSubPackageKeys.length} sub-packages no longer on filesystem (see REMOVED_SUB_PACKAGES below)`);
1860
+ if (refreshMode && (currentOutgoingRels.length > 0 || currentPartOfRels.length > 0)) {
1861
+ console.log(` Graph state : ${currentOutgoingRels.length + currentPartOfRels.length} existing relationships review against scan (see GRAPH_STATE below)`);
1864
1862
  }
1865
1863
  if (output.entityErrors.length > 0) {
1866
1864
  console.log("\nEntity errors:");
@@ -119,6 +119,7 @@ export function findClientProfile(registry, code) {
119
119
  const aliases = {
120
120
  "continue": "continue-dev",
121
121
  "claude": "claude-code",
122
+ "codex": "codex-cli",
122
123
  };
123
124
  const resolved = aliases[normalized] ?? normalized;
124
125
  return registry.mcpClientProfiles.find((c) => c.code === resolved) ?? null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexarch",
3
- "version": "0.9.28",
3
+ "version": "0.9.30",
4
4
  "description": "Your architecture workspace for AI delivery.",
5
5
  "keywords": [
6
6
  "nexarch",