nexarch 0.8.15 → 0.8.16

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.
@@ -8,7 +8,7 @@ import { fetchAgentRegistryOrThrow } from "../lib/agent-registry.js";
8
8
  import { callMcpTool, mcpInitialize, mcpListTools } from "../lib/mcp.js";
9
9
  import { buildVersionAttributes } from "../lib/version-normalization.js";
10
10
  import { requestTrustAttestation } from "../lib/trust.js";
11
- const CLI_VERSION = "0.8.12";
11
+ const CLI_VERSION = "0.8.16";
12
12
  const AGENT_ENTITY_TYPE = "agent";
13
13
  const TECH_COMPONENT_ENTITY_TYPE = "technology_component";
14
14
  function parseFlag(args, flag) {
@@ -288,12 +288,15 @@ After running, confirm \`"ok": true\` in the JSON output. No further action is n
288
288
  return filePath;
289
289
  }
290
290
  function replaceInjectedSection(existing, sectionHeading, sectionBody) {
291
- const headingRegex = new RegExp(`^${sectionHeading.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[\\s\\S]*?(?=^##\\s|\\Z)`, "m");
292
- if (headingRegex.test(existing)) {
293
- const replaced = existing.replace(headingRegex, sectionBody.trim());
294
- return replaced.endsWith("\n") ? replaced : `${replaced}\n`;
295
- }
296
- return existing;
291
+ const escapedHeading = sectionHeading.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
292
+ const blockRegex = new RegExp(`^${escapedHeading}[\\t ]*\\n[\\s\\S]*?(?=^##\\s|$)`, "gm");
293
+ const matches = existing.match(blockRegex);
294
+ if (!matches || matches.length === 0)
295
+ return existing;
296
+ const canonicalBlock = `${sectionBody.trim()}\n`;
297
+ let replaced = existing.replace(blockRegex, "");
298
+ replaced = replaced.replace(/\n{3,}/g, "\n\n").trimEnd();
299
+ return `${replaced}${replaced ? "\n\n" : ""}${canonicalBlock}`;
297
300
  }
298
301
  function injectAgentConfigs(registry) {
299
302
  const templateByCode = new Map(registry.instructionTemplates.map((t) => [t.code, t]));
@@ -323,6 +326,9 @@ function injectAgentConfigs(registry) {
323
326
  writeFileSync(filePath, replaced, "utf8");
324
327
  results.push({ path: filePath, status: "updated" });
325
328
  }
329
+ else if (existing.includes(sectionBody)) {
330
+ results.push({ path: filePath, status: "already_present" });
331
+ }
326
332
  else {
327
333
  const separator = existing.endsWith("\n") ? "" : "\n";
328
334
  writeFileSync(filePath, existing + separator + sectionBody + "\n", "utf8");
@@ -330,12 +336,12 @@ function injectAgentConfigs(registry) {
330
336
  }
331
337
  continue;
332
338
  }
333
- const separator = existing.endsWith("\n") ? "" : "\n";
334
- const next = existing + separator + sectionBody + "\n";
335
- if (next === existing) {
339
+ if (existing.includes(sectionBody)) {
336
340
  results.push({ path: filePath, status: "already_present" });
337
341
  }
338
342
  else {
343
+ const separator = existing.endsWith("\n") ? "" : "\n";
344
+ const next = existing + separator + sectionBody + "\n";
339
345
  writeFileSync(filePath, next, "utf8");
340
346
  results.push({ path: filePath, status: "injected" });
341
347
  }
@@ -360,6 +366,7 @@ function injectTrustAttestationBlock(path, attestation) {
360
366
  `agent_id: ${attestation.payload.agent_id}`,
361
367
  `expires_at: ${expiresAt}`,
362
368
  `verify_url: ${verifyUrl}`,
369
+ `token: ${attestation.token}`,
363
370
  "",
364
371
  ].join("\n");
365
372
  const existing = existsSync(path) ? readFileSync(path, "utf8") : "";
@@ -973,6 +980,7 @@ export async function initAgent(args) {
973
980
  let agentConfigResults = [];
974
981
  let instructionsWriteAllowed = false;
975
982
  let trustAttestation = null;
983
+ let trustAttestationAttempted = false;
976
984
  if (registration.ok) {
977
985
  try {
978
986
  // Save identity so check-in can find the agent key
@@ -998,8 +1006,9 @@ export async function initAgent(args) {
998
1006
  agentConfigResults = injectGenericAgentConfig(registry);
999
1007
  }
1000
1008
  if (agentConfigResults.length > 0) {
1009
+ trustAttestationAttempted = true;
1001
1010
  trustAttestation = await requestTrustAttestation(agentId);
1002
- if (trustAttestation?.ok) {
1011
+ if (trustAttestation.ok) {
1003
1012
  for (const r of agentConfigResults) {
1004
1013
  try {
1005
1014
  injectTrustAttestationBlock(r.path, trustAttestation);
@@ -1038,6 +1047,19 @@ export async function initAgent(args) {
1038
1047
  ? `updated ${agentConfigResults.length} instruction target file(s)`
1039
1048
  : "no runtime instruction target matched this repository (non-fatal; create AGENTS.md/CLAUDE.md or configure a generic target)",
1040
1049
  });
1050
+ checks.push({
1051
+ name: "agent.trust.attestation",
1052
+ ok: !registration.ok || !instructionsWriteAllowed || !trustAttestationAttempted || Boolean(trustAttestation?.ok),
1053
+ detail: !registration.ok
1054
+ ? "skipped (registration failed)"
1055
+ : !instructionsWriteAllowed
1056
+ ? "skipped (consent not granted)"
1057
+ : !trustAttestationAttempted
1058
+ ? "skipped (no instruction target written)"
1059
+ : trustAttestation?.ok
1060
+ ? "minted and injected into instruction file(s)"
1061
+ : `unavailable (${trustAttestation?.reason ?? "unknown"})`,
1062
+ });
1041
1063
  checks.push({
1042
1064
  name: "technology.components",
1043
1065
  ok: techComponents.ok,
@@ -1152,6 +1174,9 @@ export async function initAgent(args) {
1152
1174
  : `https://mcp.nexarch.ai${trustAttestation.verifyUrl}`;
1153
1175
  console.log(` Trust attestation verify URL: ${verifyUrl}`);
1154
1176
  }
1177
+ else if (trustAttestationAttempted) {
1178
+ console.log(` Trust attestation unavailable (${trustAttestation?.reason ?? "unknown"}).`);
1179
+ }
1155
1180
  }
1156
1181
  if (needsIdentityInput) {
1157
1182
  console.log("\nℹ Additional identity details are still needed to complete agent profile enrichment.");
package/dist/lib/trust.js CHANGED
@@ -26,20 +26,22 @@ export async function requestTrustAttestation(agentId) {
26
26
  res.on("data", (c) => chunks.push(c));
27
27
  res.on("end", () => {
28
28
  try {
29
- const parsed = JSON.parse(Buffer.concat(chunks).toString("utf8"));
30
- if (!res.statusCode || res.statusCode >= 400)
31
- return resolve(null);
29
+ const raw = Buffer.concat(chunks).toString("utf8");
30
+ const parsed = JSON.parse(raw);
31
+ if (!res.statusCode || res.statusCode >= 400) {
32
+ return resolve({ ok: false, reason: parsed.error?.code ?? parsed.error?.message ?? `http_${res.statusCode ?? 0}` });
33
+ }
32
34
  resolve(parsed);
33
35
  }
34
36
  catch {
35
- resolve(null);
37
+ resolve({ ok: false, reason: "parse_error" });
36
38
  }
37
39
  });
38
40
  });
39
- req.on("error", () => resolve(null));
41
+ req.on("error", () => resolve({ ok: false, reason: "network_error" }));
40
42
  req.on("timeout", () => {
41
43
  req.destroy();
42
- resolve(null);
44
+ resolve({ ok: false, reason: "timeout" });
43
45
  });
44
46
  req.write(body);
45
47
  req.end();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexarch",
3
- "version": "0.8.15",
3
+ "version": "0.8.16",
4
4
  "description": "Your architecture workspace for AI delivery.",
5
5
  "keywords": [
6
6
  "nexarch",