archctx 0.2.0 → 0.2.1
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/assets/catalog.yaml
CHANGED
package/bin/archctx.mjs
CHANGED
|
@@ -702,7 +702,7 @@ function productVersionManifest() {
|
|
|
702
702
|
}
|
|
703
703
|
};
|
|
704
704
|
}
|
|
705
|
-
var ARCHCONTEXT_PRODUCT_NAME = "archctx", ARCHCONTEXT_PRODUCT_VERSION = "0.2.
|
|
705
|
+
var ARCHCONTEXT_PRODUCT_NAME = "archctx", ARCHCONTEXT_PRODUCT_VERSION = "0.2.1", ARCHCONTEXT_PACKAGE_MANAGER = "bun@1.3.10", ARCHCONTEXT_NODE_RANGE = ">=24 <26", LOCAL_RUNTIME_RPC_SCHEMA_VERSION = "archcontext.runtime-rpc/v1", ARCHCONTEXT_SCHEMA_SET_VERSION = "2026-06-25.al0-ledger";
|
|
706
706
|
// packages/contracts/src/index.ts
|
|
707
707
|
var init_src = __esm(() => {
|
|
708
708
|
init_control_plane_routes();
|
|
@@ -14850,6 +14850,12 @@ function uniqueSorted4(values) {
|
|
|
14850
14850
|
init_src();
|
|
14851
14851
|
import { existsSync as existsSync8, readdirSync as readdirSync6, readFileSync as readFileSync8 } from "node:fs";
|
|
14852
14852
|
import { basename as basename4, resolve as resolve11 } from "node:path";
|
|
14853
|
+
function nativeNodeSource(node) {
|
|
14854
|
+
const value = node.source;
|
|
14855
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
14856
|
+
return;
|
|
14857
|
+
return value;
|
|
14858
|
+
}
|
|
14853
14859
|
var ARCHITECTURE_DOCS_RENDERER_VERSION = "archcontext.docs-renderer/v1";
|
|
14854
14860
|
var ARCHITECTURE_DOCS_GENERATED_BEGIN_PREFIX = "<!-- BEGIN ARCHCONTEXT:generated";
|
|
14855
14861
|
var ARCHITECTURE_DOCS_GENERATED_END_PREFIX = "<!-- END ARCHCONTEXT:generated";
|
|
@@ -15078,23 +15084,10 @@ function mermaidId(id) {
|
|
|
15078
15084
|
function readYamlObjects(dir) {
|
|
15079
15085
|
if (!existsSync8(dir))
|
|
15080
15086
|
return [];
|
|
15081
|
-
return readdirSync6(dir).filter((file) => /\.ya?ml$/.test(file)).sort().map((file) =>
|
|
15082
|
-
|
|
15083
|
-
|
|
15084
|
-
|
|
15085
|
-
for (const line of body.split(/\r?\n/)) {
|
|
15086
|
-
const match = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);
|
|
15087
|
-
if (!match)
|
|
15088
|
-
continue;
|
|
15089
|
-
const [, key, raw] = match;
|
|
15090
|
-
if (raw.startsWith('"') && raw.endsWith('"'))
|
|
15091
|
-
out[key] = JSON.parse(raw);
|
|
15092
|
-
else if (raw === "true" || raw === "false")
|
|
15093
|
-
out[key] = raw === "true";
|
|
15094
|
-
else
|
|
15095
|
-
out[key] = raw;
|
|
15096
|
-
}
|
|
15097
|
-
return out;
|
|
15087
|
+
return readdirSync6(dir).filter((file) => /\.ya?ml$/.test(file)).sort().map((file) => {
|
|
15088
|
+
const path = resolve11(dir, file);
|
|
15089
|
+
return parseJsonOrStableYaml(readFileSync8(path, "utf8"), path);
|
|
15090
|
+
});
|
|
15098
15091
|
}
|
|
15099
15092
|
function escapeMermaid(value) {
|
|
15100
15093
|
return value.replace(/"/g, "'");
|
|
@@ -15441,6 +15434,61 @@ function escapeDsl(value) {
|
|
|
15441
15434
|
function escapeRegExp(value) {
|
|
15442
15435
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
15443
15436
|
}
|
|
15437
|
+
function resolveArchitectureOwnerForPath(nodes, path) {
|
|
15438
|
+
const candidates = [];
|
|
15439
|
+
for (const node of nodes) {
|
|
15440
|
+
const source = nativeNodeSource(node);
|
|
15441
|
+
const include = source?.include ?? [];
|
|
15442
|
+
if (include.length === 0)
|
|
15443
|
+
continue;
|
|
15444
|
+
const excluded = (source?.exclude ?? []).some((pattern) => matchesGlob(path, pattern));
|
|
15445
|
+
if (excluded)
|
|
15446
|
+
continue;
|
|
15447
|
+
const specificity = include.filter((pattern) => matchesGlob(path, pattern)).reduce((max, pattern) => Math.max(max, globLiteralPrefixLength(pattern)), -1);
|
|
15448
|
+
if (specificity >= 0)
|
|
15449
|
+
candidates.push({ node, specificity });
|
|
15450
|
+
}
|
|
15451
|
+
if (candidates.length === 0)
|
|
15452
|
+
return { status: "no-match" };
|
|
15453
|
+
const maxSpecificity = candidates.reduce((max, candidate) => Math.max(max, candidate.specificity), -1);
|
|
15454
|
+
const winners = candidates.filter((candidate) => candidate.specificity === maxSpecificity).map((candidate) => candidate.node);
|
|
15455
|
+
if (winners.length > 1)
|
|
15456
|
+
return { status: "ambiguous", candidates: winners };
|
|
15457
|
+
return { status: "matched", node: winners[0] };
|
|
15458
|
+
}
|
|
15459
|
+
function matchesGlob(path, pattern) {
|
|
15460
|
+
return globToRegExp(pattern).test(path);
|
|
15461
|
+
}
|
|
15462
|
+
function globLiteralPrefixLength(pattern) {
|
|
15463
|
+
const index = pattern.search(/[*?]/);
|
|
15464
|
+
return index === -1 ? pattern.length : index;
|
|
15465
|
+
}
|
|
15466
|
+
function globToRegExp(pattern) {
|
|
15467
|
+
let out = "";
|
|
15468
|
+
let index = 0;
|
|
15469
|
+
while (index < pattern.length) {
|
|
15470
|
+
if (pattern.startsWith("**/", index)) {
|
|
15471
|
+
out += "(?:.*/)?";
|
|
15472
|
+
index += 3;
|
|
15473
|
+
continue;
|
|
15474
|
+
}
|
|
15475
|
+
if (pattern.startsWith("**", index)) {
|
|
15476
|
+
out += ".*";
|
|
15477
|
+
index += 2;
|
|
15478
|
+
continue;
|
|
15479
|
+
}
|
|
15480
|
+
const char = pattern[index];
|
|
15481
|
+
if (char === "*") {
|
|
15482
|
+
out += "[^/]*";
|
|
15483
|
+
} else if (char === "?") {
|
|
15484
|
+
out += "[^/]";
|
|
15485
|
+
} else {
|
|
15486
|
+
out += escapeRegExp(char);
|
|
15487
|
+
}
|
|
15488
|
+
index += 1;
|
|
15489
|
+
}
|
|
15490
|
+
return new RegExp(`^${out}$`);
|
|
15491
|
+
}
|
|
15444
15492
|
|
|
15445
15493
|
// packages/local-runtime/explorer-html/src/index.ts
|
|
15446
15494
|
var STATUS_STYLE = {
|
|
@@ -19494,6 +19542,22 @@ function createDefaultProjectionTargetManifest() {
|
|
|
19494
19542
|
pathTemplate: "docs/architecture/diagrams/architecture.likec4",
|
|
19495
19543
|
ownership: "generated",
|
|
19496
19544
|
format: "likec4"
|
|
19545
|
+
},
|
|
19546
|
+
{
|
|
19547
|
+
id: "projection_rule.agent-context.claude",
|
|
19548
|
+
targetType: "agent-context",
|
|
19549
|
+
scope: { kind: "entity", entityKind: "capability" },
|
|
19550
|
+
pathTemplate: "{primarySourceDir}/CLAUDE.md",
|
|
19551
|
+
ownership: "mixed",
|
|
19552
|
+
format: "markdown"
|
|
19553
|
+
},
|
|
19554
|
+
{
|
|
19555
|
+
id: "projection_rule.agent-context.agents",
|
|
19556
|
+
targetType: "agent-context",
|
|
19557
|
+
scope: { kind: "entity", entityKind: "capability" },
|
|
19558
|
+
pathTemplate: "{primarySourceDir}/AGENTS.md",
|
|
19559
|
+
ownership: "mixed",
|
|
19560
|
+
format: "markdown"
|
|
19497
19561
|
}
|
|
19498
19562
|
]
|
|
19499
19563
|
};
|
|
@@ -28991,6 +29055,7 @@ function writeHtml2(response, statusCode, body) {
|
|
|
28991
29055
|
}
|
|
28992
29056
|
|
|
28993
29057
|
// packages/surfaces/mcp-local/src/index.ts
|
|
29058
|
+
var MCP_PROTOCOL_VERSION = "2025-03-26";
|
|
28994
29059
|
var LOCAL_MCP_TOOLS = [
|
|
28995
29060
|
{
|
|
28996
29061
|
name: "archcontext_prepare_task",
|
|
@@ -29302,9 +29367,17 @@ async function runStdioMcpLoop(input, output, log = (line) => process.stderr.wri
|
|
|
29302
29367
|
log("[archctx-mcp] started");
|
|
29303
29368
|
for await (const line of input) {
|
|
29304
29369
|
const message = JSON.parse(line);
|
|
29370
|
+
if (message.id === undefined)
|
|
29371
|
+
continue;
|
|
29305
29372
|
let result;
|
|
29306
|
-
if (message.method === "
|
|
29373
|
+
if (message.method === "initialize") {
|
|
29374
|
+
result = mcpInitializeResult(message.params?.protocolVersion);
|
|
29375
|
+
} else if (message.method === "ping") {
|
|
29376
|
+
result = {};
|
|
29377
|
+
} else if (message.method === "tools/list") {
|
|
29307
29378
|
result = { tools: server.listTools() };
|
|
29379
|
+
} else if (message.method === "tools/call") {
|
|
29380
|
+
result = await server.callTool(message.params?.name, message.params?.arguments ?? {});
|
|
29308
29381
|
} else if (message.method === "resources/list") {
|
|
29309
29382
|
result = { resources: await server.listResources(message.params?.root) };
|
|
29310
29383
|
} else if (message.method === "resources/read") {
|
|
@@ -29314,11 +29387,28 @@ async function runStdioMcpLoop(input, output, log = (line) => process.stderr.wri
|
|
|
29314
29387
|
contents: content === undefined ? [] : [{ uri, mimeType: "application/json", text: JSON.stringify(content) }]
|
|
29315
29388
|
};
|
|
29316
29389
|
} else {
|
|
29317
|
-
result =
|
|
29390
|
+
result = {
|
|
29391
|
+
content: errorEnvelope("mcp", "AC_SCHEMA_INVALID", `Unknown MCP method: ${message.method}`),
|
|
29392
|
+
dataClassification: "local-metadata"
|
|
29393
|
+
};
|
|
29318
29394
|
}
|
|
29319
29395
|
output(JSON.stringify({ jsonrpc: "2.0", id: message.id, result }));
|
|
29320
29396
|
}
|
|
29321
29397
|
}
|
|
29398
|
+
function mcpInitializeResult(clientProtocolVersion) {
|
|
29399
|
+
const product = productVersionManifest().product;
|
|
29400
|
+
return {
|
|
29401
|
+
protocolVersion: typeof clientProtocolVersion === "string" ? clientProtocolVersion : MCP_PROTOCOL_VERSION,
|
|
29402
|
+
capabilities: {
|
|
29403
|
+
tools: { listChanged: false },
|
|
29404
|
+
resources: { subscribe: false, listChanged: false }
|
|
29405
|
+
},
|
|
29406
|
+
serverInfo: {
|
|
29407
|
+
name: product.name,
|
|
29408
|
+
version: product.version
|
|
29409
|
+
}
|
|
29410
|
+
};
|
|
29411
|
+
}
|
|
29322
29412
|
function isExternalDocumentationResourceUri(uri) {
|
|
29323
29413
|
return /^archcontext:\/\/external-docs\/context7\/sha256:[0-9a-f]{64}$/.test(uri);
|
|
29324
29414
|
}
|
|
@@ -29365,6 +29455,8 @@ if (__require.main == __require.module) {
|
|
|
29365
29455
|
`);
|
|
29366
29456
|
if (result.ok === false)
|
|
29367
29457
|
process.exitCode = 1;
|
|
29458
|
+
if (command === "resolve")
|
|
29459
|
+
process.exitCode = resolveCommandExitCode(result);
|
|
29368
29460
|
}
|
|
29369
29461
|
}
|
|
29370
29462
|
async function* stdinLines() {
|
|
@@ -29621,6 +29713,37 @@ async function runCliUnchecked(command2 = "help", args2 = [], cwd, deps = {}) {
|
|
|
29621
29713
|
revocation: "archctx tunnel --revoke"
|
|
29622
29714
|
}
|
|
29623
29715
|
};
|
|
29716
|
+
case "resolve": {
|
|
29717
|
+
const path = readFlag(args2, "--path");
|
|
29718
|
+
if (!path)
|
|
29719
|
+
return errorEnvelope("resolve", "AC_SCHEMA_INVALID", "resolve requires --path");
|
|
29720
|
+
if (!isRepoRelativePosixPath(path)) {
|
|
29721
|
+
return errorEnvelope("resolve", "AC_SCHEMA_INVALID", "resolve --path must be a repository-relative POSIX path");
|
|
29722
|
+
}
|
|
29723
|
+
const model = loadNativeModelFromArchContext(cwd);
|
|
29724
|
+
const outcome = resolveArchitectureOwnerForPath(model.nodes, path);
|
|
29725
|
+
if (outcome.status === "matched") {
|
|
29726
|
+
const node = outcome.node;
|
|
29727
|
+
return okEnvelope("resolve", {
|
|
29728
|
+
matched: true,
|
|
29729
|
+
ambiguous: false,
|
|
29730
|
+
stableId: node.id,
|
|
29731
|
+
kind: node.kind,
|
|
29732
|
+
name: node.name,
|
|
29733
|
+
...node.source ? { source: node.source } : {},
|
|
29734
|
+
...node.extensions ? { extensions: node.extensions } : {}
|
|
29735
|
+
});
|
|
29736
|
+
}
|
|
29737
|
+
if (outcome.status === "ambiguous") {
|
|
29738
|
+
return okEnvelope("resolve", {
|
|
29739
|
+
matched: false,
|
|
29740
|
+
ambiguous: true,
|
|
29741
|
+
path,
|
|
29742
|
+
candidates: outcome.candidates.map((node) => node.id)
|
|
29743
|
+
});
|
|
29744
|
+
}
|
|
29745
|
+
return okEnvelope("resolve", { matched: false, ambiguous: false, path });
|
|
29746
|
+
}
|
|
29624
29747
|
case "help":
|
|
29625
29748
|
default:
|
|
29626
29749
|
return {
|
|
@@ -29628,8 +29751,8 @@ async function runCliUnchecked(command2 = "help", args2 = [], cwd, deps = {}) {
|
|
|
29628
29751
|
ok: true,
|
|
29629
29752
|
requestId: "help",
|
|
29630
29753
|
data: {
|
|
29631
|
-
commands: ["init", "sync", "validate", "context", "status", "daemon", "repo", "landscape", "ledger", "book", "recommendations", "explore", "prepare", "practices", "checkpoint", "hook", "hooks", "investigate", "agents", "jobs", "audit", "plan", "apply", "review", "complete", "github", "config", "mcp", "install", "uninstall", "doctor", "update", "paths", "privacy-audit", "export", "import", "tunnel"],
|
|
29632
|
-
examples: ["archctx init --name MyApp", "archctx ledger migrate --from-yaml --dry-run", "archctx ledger promote --mode authoritative --preflight --rollback-plan", "archctx book recommendations --open --explain", "archctx recommendations accept --id recommendation.<id> --reason 'Accepted after local readback.'", "archctx recommendations metrics", "archctx practices validate --strict", "archctx practices list --json", "archctx practices waivers", "archctx practices waive --practice-id modularity.no-new-cycle --owner team-architecture --reason 'External migration window requires this edge until cutover.' --review-at 2026-07-10T00:00:00.000Z --expires-at 2026-07-24T00:00:00.000Z --evidence-digest sha256:<64-hex> --subject module.a->module.b", "archctx checkpoint --task-session-id task_cli", "archctx investigate --runner-port codex", "archctx agents status --status queued,running", "archctx agents budget", "archctx hook enqueue --event post-edit --path src/app.ts", "archctx jobs list --status queued", "archctx audit run --reason 'quarterly architecture audit'", "archctx audit run --no-wait", "archctx audit list --status pending", "archctx audit show audit_run.<id>", "archctx audit approve audit_run.<id>", "archctx audit approve audit_run.<id> --confirm-public-repo public:<owner/repo>:<baseSha>:<runId>", "archctx audit approve audit_run.<id> --resume", "archctx hooks install --host codex", "archctx paths", "archctx update --check", "archctx doctor --check-updates", "archctx github connect", "archctx github status", "archctx daemon start", "archctx explore start --foreground", "archctx export likec4", "archctx import structurizr --content '<json>'", "archctx tunnel"]
|
|
29754
|
+
commands: ["init", "sync", "validate", "context", "status", "daemon", "repo", "landscape", "ledger", "book", "recommendations", "explore", "prepare", "practices", "checkpoint", "hook", "hooks", "investigate", "agents", "jobs", "audit", "plan", "apply", "review", "complete", "github", "config", "mcp", "install", "uninstall", "doctor", "update", "paths", "privacy-audit", "export", "import", "resolve", "tunnel"],
|
|
29755
|
+
examples: ["archctx init --name MyApp", "archctx ledger migrate --from-yaml --dry-run", "archctx ledger promote --mode authoritative --preflight --rollback-plan", "archctx book recommendations --open --explain", "archctx recommendations accept --id recommendation.<id> --reason 'Accepted after local readback.'", "archctx recommendations metrics", "archctx practices validate --strict", "archctx practices list --json", "archctx practices waivers", "archctx practices waive --practice-id modularity.no-new-cycle --owner team-architecture --reason 'External migration window requires this edge until cutover.' --review-at 2026-07-10T00:00:00.000Z --expires-at 2026-07-24T00:00:00.000Z --evidence-digest sha256:<64-hex> --subject module.a->module.b", "archctx checkpoint --task-session-id task_cli", "archctx investigate --runner-port codex", "archctx agents status --status queued,running", "archctx agents budget", "archctx hook enqueue --event post-edit --path src/app.ts", "archctx jobs list --status queued", "archctx audit run --reason 'quarterly architecture audit'", "archctx audit run --no-wait", "archctx audit list --status pending", "archctx audit show audit_run.<id>", "archctx audit approve audit_run.<id>", "archctx audit approve audit_run.<id> --confirm-public-repo public:<owner/repo>:<baseSha>:<runId>", "archctx audit approve audit_run.<id> --resume", "archctx hooks install --host codex", "archctx paths", "archctx update --check", "archctx doctor --check-updates", "archctx github connect", "archctx github status", "archctx daemon start", "archctx explore start --foreground", "archctx export likec4", "archctx import structurizr --content '<json>'", "archctx resolve --path packages/core/projection-engine/src/index.ts", "archctx tunnel"]
|
|
29633
29756
|
}
|
|
29634
29757
|
};
|
|
29635
29758
|
}
|
|
@@ -32164,6 +32287,16 @@ function renderResult(result, format) {
|
|
|
32164
32287
|
return `OK ${result.requestId}
|
|
32165
32288
|
${JSON.stringify(result.data, null, 2)}`;
|
|
32166
32289
|
}
|
|
32290
|
+
function resolveCommandExitCode(result) {
|
|
32291
|
+
if (!result || result.ok !== true)
|
|
32292
|
+
return 1;
|
|
32293
|
+
const data = result.data;
|
|
32294
|
+
if (data?.matched === true)
|
|
32295
|
+
return 0;
|
|
32296
|
+
if (data?.ambiguous === true)
|
|
32297
|
+
return 2;
|
|
32298
|
+
return 1;
|
|
32299
|
+
}
|
|
32167
32300
|
function readFlag(args2, flag) {
|
|
32168
32301
|
const index = args2.indexOf(flag);
|
|
32169
32302
|
if (index === -1)
|
|
@@ -32193,5 +32326,6 @@ function readRepeatedFlag(args2, flag) {
|
|
|
32193
32326
|
}
|
|
32194
32327
|
export {
|
|
32195
32328
|
runForegroundDaemon,
|
|
32196
|
-
runCli
|
|
32329
|
+
runCli,
|
|
32330
|
+
resolveCommandExitCode
|
|
32197
32331
|
};
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"targetId": { "type": "string", "pattern": "^projection_target\\.[a-zA-Z0-9_.-]+$" },
|
|
11
11
|
"type": {
|
|
12
12
|
"type": "string",
|
|
13
|
-
"enum": ["architecture-index", "entity-summary", "relation-summary", "decision-index", "architecture-changelog", "diagram-mermaid", "diagram-structurizr", "diagram-likec4"]
|
|
13
|
+
"enum": ["architecture-index", "entity-summary", "relation-summary", "decision-index", "architecture-changelog", "diagram-mermaid", "diagram-structurizr", "diagram-likec4", "agent-context"]
|
|
14
14
|
},
|
|
15
15
|
"scope": {
|
|
16
16
|
"type": "object",
|