nexarch 0.9.26 → 0.9.29
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.
- package/dist/commands/init-agent.js +28 -16
- package/dist/commands/init-project.js +58 -60
- package/dist/commands/setup.js +2 -7
- package/dist/lib/clients.js +4 -7
- package/package.json +1 -1
|
@@ -1129,28 +1129,40 @@ export async function initAgent(args) {
|
|
|
1129
1129
|
}
|
|
1130
1130
|
if (instructionsWriteAllowed) {
|
|
1131
1131
|
agentConfigResults = existingInstructionTargets;
|
|
1132
|
-
|
|
1133
|
-
|
|
1132
|
+
}
|
|
1133
|
+
else if (alreadyConfigured) {
|
|
1134
|
+
agentConfigResults = existingInstructionTargets;
|
|
1135
|
+
}
|
|
1136
|
+
// Inject trust attestation for any file actually written (injected/updated),
|
|
1137
|
+
// plus all targets when instructionsWriteAllowed forces a refresh.
|
|
1138
|
+
// Runs regardless of instructionsWriteAllowed so writes that happened before
|
|
1139
|
+
// the consent check always get a trust block.
|
|
1140
|
+
const attestationTargets = instructionsWriteAllowed
|
|
1141
|
+
? agentConfigResults
|
|
1142
|
+
: existingInstructionTargets.filter((r) => r.status === "injected" || r.status === "updated");
|
|
1143
|
+
if (attestationTargets.length > 0) {
|
|
1144
|
+
trustAttestationAttempted = true;
|
|
1145
|
+
try {
|
|
1134
1146
|
trustAttestation = await requestTrustAttestation(agentId);
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
injectInitProjectReportingContract(r.path);
|
|
1147
|
+
}
|
|
1148
|
+
catch {
|
|
1149
|
+
trustAttestation = { ok: false, reason: "request failed" };
|
|
1150
|
+
}
|
|
1151
|
+
for (const r of attestationTargets) {
|
|
1152
|
+
try {
|
|
1153
|
+
if (trustAttestation.ok) {
|
|
1154
|
+
injectTrustAttestationBlock(r.path, trustAttestation);
|
|
1144
1155
|
}
|
|
1145
|
-
|
|
1146
|
-
|
|
1156
|
+
else {
|
|
1157
|
+
injectTrustAttestationUnavailableBlock(r.path, trustAttestation.reason ?? "unknown");
|
|
1147
1158
|
}
|
|
1159
|
+
injectInitProjectReportingContract(r.path);
|
|
1160
|
+
}
|
|
1161
|
+
catch {
|
|
1162
|
+
// non-fatal
|
|
1148
1163
|
}
|
|
1149
1164
|
}
|
|
1150
1165
|
}
|
|
1151
|
-
else if (alreadyConfigured) {
|
|
1152
|
-
agentConfigResults = existingInstructionTargets;
|
|
1153
|
-
}
|
|
1154
1166
|
}
|
|
1155
1167
|
checks.push({
|
|
1156
1168
|
name: "agent.registration",
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
|
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 (
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
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 (
|
|
1860
|
-
console.log(`
|
|
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:");
|
package/dist/commands/setup.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { requireCredentials
|
|
1
|
+
import { requireCredentials } from "../lib/credentials.js";
|
|
2
2
|
import { detectClientsFromRegistry, writeClientConfig, nexarchServerBlockFromRegistry } from "../lib/clients.js";
|
|
3
3
|
import { fetchAgentRegistryOrThrow } from "../lib/agent-registry.js";
|
|
4
4
|
import { initAgent } from "./init-agent.js";
|
|
5
5
|
import { login } from "./login.js";
|
|
6
|
-
const MCP_HTTP_URL = "https://mcp.nexarch.ai/mcp";
|
|
7
6
|
export async function setup(args) {
|
|
8
7
|
try {
|
|
9
8
|
requireCredentials();
|
|
@@ -44,12 +43,8 @@ export async function setup(args) {
|
|
|
44
43
|
console.log(" nexarch mcp-config --client http");
|
|
45
44
|
}
|
|
46
45
|
else {
|
|
47
|
-
const
|
|
48
|
-
const stdioBlock = nexarchServerBlockFromRegistry(registry);
|
|
46
|
+
const serverBlock = nexarchServerBlockFromRegistry(registry);
|
|
49
47
|
for (const client of clients) {
|
|
50
|
-
const serverBlock = process.platform === "win32" && client.code === "claude-code" && creds
|
|
51
|
-
? { type: "http", url: MCP_HTTP_URL, headers: { Authorization: `Bearer ${creds.token}` } }
|
|
52
|
-
: stdioBlock;
|
|
53
48
|
process.stdout.write(` ${client.name.padEnd(20)} ${client.configPath}\n`);
|
|
54
49
|
process.stdout.write(` ${"".padEnd(20)} `);
|
|
55
50
|
try {
|
package/dist/lib/clients.js
CHANGED
|
@@ -106,15 +106,12 @@ export function nexarchServerBlockFromRegistry(registry) {
|
|
|
106
106
|
if (!first) {
|
|
107
107
|
throw new Error("Nexarch integration registry is missing MCP client profiles.");
|
|
108
108
|
}
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
command: `${first.serverCommand}.cmd`,
|
|
112
|
-
args: first.serverArgs,
|
|
113
|
-
};
|
|
114
|
-
}
|
|
109
|
+
const command = process.platform === "win32" ? `${first.serverCommand}.cmd` : first.serverCommand;
|
|
115
110
|
return {
|
|
116
|
-
|
|
111
|
+
type: "stdio",
|
|
112
|
+
command,
|
|
117
113
|
args: first.serverArgs,
|
|
114
|
+
env: {},
|
|
118
115
|
};
|
|
119
116
|
}
|
|
120
117
|
export function findClientProfile(registry, code) {
|