nexarch 0.12.28 → 0.12.31
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-project.js +4 -4
- package/dist/commands/setup.js +28 -15
- package/dist/lib/skills.js +172 -25
- package/package.json +1 -1
|
@@ -1877,8 +1877,8 @@ export async function initProject(args) {
|
|
|
1877
1877
|
pendingSteps.push({
|
|
1878
1878
|
step: stepNum++,
|
|
1879
1879
|
action: "describe_project",
|
|
1880
|
-
instruction: `Give the project (repository) entity a short description of what lives in this repo.`,
|
|
1881
|
-
command: `nexarch update-entity --key "${projectEntityKey}" --entity-type "project" --name "
|
|
1880
|
+
instruction: `Give the project (repository) entity a meaningful display name (not the raw directory name "${projectDirName}") and a short description of what lives in this repo.`,
|
|
1881
|
+
command: `nexarch update-entity --key "${projectEntityKey}" --entity-type "project" --name "..." --description "..."`,
|
|
1882
1882
|
});
|
|
1883
1883
|
}
|
|
1884
1884
|
if (!projectConstruct || !isMonorepo) {
|
|
@@ -2149,8 +2149,8 @@ export async function initProject(args) {
|
|
|
2149
2149
|
lines.push("REMAINING STEPS:");
|
|
2150
2150
|
let step = 1;
|
|
2151
2151
|
if (projectConstruct) {
|
|
2152
|
-
lines.push(` ${step++}. nexarch update-entity --key "${projectEntityKey}" --entity-type "project" --name "
|
|
2153
|
-
lines.push(` (short description of what lives in this repository)`);
|
|
2152
|
+
lines.push(` ${step++}. nexarch update-entity --key "${projectEntityKey}" --entity-type "project" --name "..." --description "..."`);
|
|
2153
|
+
lines.push(` (meaningful display name — not the raw directory name "${projectDirName}" — and a short description of what lives in this repository)`);
|
|
2154
2154
|
}
|
|
2155
2155
|
if (!projectConstruct || !isMonorepo) {
|
|
2156
2156
|
lines.push(` ${step++}. nexarch update-entity --key "${projectExternalKey}" --entity-type "${entityTypeOverride}"${entityTypeOverride === "application" ? ' --subtype "<subtype>" --icon "<lucide-icon>"' : ""} --name "..." --description "..."`);
|
package/dist/commands/setup.js
CHANGED
|
@@ -3,7 +3,7 @@ import { requireCredentials } from "../lib/credentials.js";
|
|
|
3
3
|
import { detectClientsFromRegistry, writeClientConfig, nexarchServerBlockFromRegistry } from "../lib/clients.js";
|
|
4
4
|
import { fetchAgentRegistryOrThrow } from "../lib/agent-registry.js";
|
|
5
5
|
import { initAgent } from "./init-agent.js";
|
|
6
|
-
import {
|
|
6
|
+
import { installSkillsForRuntime } from "../lib/skills.js";
|
|
7
7
|
import { login } from "./login.js";
|
|
8
8
|
function argValue(args, flag) {
|
|
9
9
|
const idx = args.indexOf(flag);
|
|
@@ -168,25 +168,38 @@ export async function setup(args) {
|
|
|
168
168
|
initAgentArgs.push("--instruction-runtime-targets", instructionRuntimeTargets.join(","));
|
|
169
169
|
}
|
|
170
170
|
await initAgent(initAgentArgs);
|
|
171
|
-
// Claude Code
|
|
172
|
-
// permanently in the agent's context and loads a
|
|
173
|
-
// moment
|
|
174
|
-
//
|
|
175
|
-
//
|
|
176
|
-
|
|
177
|
-
|
|
171
|
+
// Claude Code and Codex CLI both support Agent Skills: a trigger
|
|
172
|
+
// description that sits permanently in the agent's context and loads a
|
|
173
|
+
// playbook when a matching moment comes up. MCP alone makes the graph
|
|
174
|
+
// available; skills are what make an agent actually consult it — for
|
|
175
|
+
// building, diagramming, working its command queue, and governance
|
|
176
|
+
// review. Both runtimes use the same SKILL.md format, just a different
|
|
177
|
+
// root directory (see RUNTIME_SKILLS_ROOT in lib/skills.ts), so the same
|
|
178
|
+
// content installs to both unmodified. Installed under the same consent
|
|
179
|
+
// as instruction writes — setup already opts into those above.
|
|
180
|
+
const skillRuntimes = [
|
|
181
|
+
{ clientCode: "claude-code", runtime: "claude-code", label: "Claude Code" },
|
|
182
|
+
{ clientCode: "codex-cli", runtime: "codex-cli", label: "Codex CLI" },
|
|
183
|
+
];
|
|
184
|
+
for (const { clientCode, runtime, label } of skillRuntimes) {
|
|
185
|
+
if (!clients.some((client) => client.code === clientCode))
|
|
186
|
+
continue;
|
|
178
187
|
try {
|
|
179
|
-
const
|
|
180
|
-
const
|
|
181
|
-
console.log(`\
|
|
182
|
-
|
|
183
|
-
|
|
188
|
+
const skills = installSkillsForRuntime(registry, runtime);
|
|
189
|
+
const anyChanged = skills.some((s) => s.status !== "already_current");
|
|
190
|
+
console.log(`\n${label} skills:`);
|
|
191
|
+
for (const skill of skills) {
|
|
192
|
+
const verb = skill.status === "installed" ? "installed" : skill.status === "updated" ? "updated" : "already current";
|
|
193
|
+
console.log(` ${verb.padEnd(15)} ${skill.dirName}`);
|
|
194
|
+
}
|
|
195
|
+
if (anyChanged) {
|
|
196
|
+
console.log(` New ${label} sessions will use these to decide when to consult Nexarch.`);
|
|
184
197
|
}
|
|
185
198
|
}
|
|
186
199
|
catch (err) {
|
|
187
200
|
const message = err instanceof Error ? err.message : String(err);
|
|
188
|
-
console.log(`\
|
|
189
|
-
console.log(" Setup is otherwise complete; re-run setup to retry the
|
|
201
|
+
console.log(`\n${label} skill install failed — ${message}`);
|
|
202
|
+
console.log(" Setup is otherwise complete; re-run setup to retry the skills.");
|
|
190
203
|
}
|
|
191
204
|
}
|
|
192
205
|
if (clients.length > 0) {
|
package/dist/lib/skills.js
CHANGED
|
@@ -1,24 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
2
2
|
import { homedir } from "os";
|
|
3
3
|
import { join } from "path";
|
|
4
|
-
|
|
5
|
-
* Claude Code skill installation.
|
|
6
|
-
*
|
|
7
|
-
* MCP makes the architecture graph *available* to an agent; nothing makes the
|
|
8
|
-
* agent *consult* it. Tool descriptions are skimmed once and forgotten, and the
|
|
9
|
-
* injected AGENTS.md block is repo-scoped. A skill closes that gap: its
|
|
10
|
-
* description sits permanently in the agent's context as a trigger, and when a
|
|
11
|
-
* build-shaped moment matches, the full playbook loads.
|
|
12
|
-
*
|
|
13
|
-
* The body is registry-managed (template nexarch_claude_code_skill_v1) so it
|
|
14
|
-
* can be updated by migration like the instruction templates; the baked-in
|
|
15
|
-
* fallback below keeps installs working when the registry predates the
|
|
16
|
-
* template. Installed to the user-level skills directory because agent setup is
|
|
17
|
-
* a per-machine action, like MCP client configuration.
|
|
18
|
-
*/
|
|
19
|
-
export const CLAUDE_SKILL_TEMPLATE_CODE = "nexarch_claude_code_skill_v1";
|
|
20
|
-
export const CLAUDE_SKILL_DIR_NAME = "nexarch-architecture-graph";
|
|
21
|
-
export const FALLBACK_SKILL_BODY = `---
|
|
4
|
+
const ARCHITECTURE_GRAPH_SKILL_BODY = `---
|
|
22
5
|
name: nexarch-architecture-graph
|
|
23
6
|
description: Consult the organisation's Nexarch architecture graph before building anything new, and register what gets built. Use when creating a new service, application, module, integration, API endpoint, or scheduled job; when adding a significant dependency or choosing between libraries; when asked whether a capability, integration, or dataset already exists; or when asked what applications or systems the organisation has. Requires the Nexarch MCP tools (nexarch_*).
|
|
24
7
|
---
|
|
@@ -61,21 +44,185 @@ repository; the graph knows all of them.
|
|
|
61
44
|
- End architectural work with a one-line summary of what was recorded and what
|
|
62
45
|
remains unresolved.
|
|
63
46
|
`;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
47
|
+
const DIAGRAM_VIEWS_SKILL_BODY = `---
|
|
48
|
+
name: nexarch-diagram-views
|
|
49
|
+
description: Create, update, or find an architecture diagram in Nexarch. Use when asked to visualize, diagram, or map the architecture; show a system topology or environment overview; draw how something connects to the rest of the estate; or update an existing diagram's layout or filters. Requires the Nexarch MCP tools (nexarch_*).
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
# Nexarch Diagram Views
|
|
53
|
+
|
|
54
|
+
Diagrams in Nexarch are saved views over the live graph, not static images —
|
|
55
|
+
each one has filters, a layout, and a revision history, and every view is
|
|
56
|
+
shared workspace state, not scratch output.
|
|
57
|
+
|
|
58
|
+
## Before creating one
|
|
59
|
+
|
|
60
|
+
1. \`nexarch_list_diagram_views\` — check whether a view covering this already
|
|
61
|
+
exists (they're grouped by folder). Reuse an existing view over creating a
|
|
62
|
+
near-duplicate; the same reuse-before-build principle applies to diagrams
|
|
63
|
+
as it does to applications.
|
|
64
|
+
2. If one exists but looks stale or wrong, \`nexarch_get_diagram_view\` to see
|
|
65
|
+
its current filters/layout before deciding whether to update it or start
|
|
66
|
+
fresh.
|
|
67
|
+
|
|
68
|
+
## Creating or refreshing a view
|
|
69
|
+
|
|
70
|
+
- Prefer \`nexarch_generate_diagram_view\` over hand-building one: it derives
|
|
71
|
+
nodes and edges straight from graph semantics (\`application_topology\`,
|
|
72
|
+
\`environment_overview\`, or \`edge_to_runtime\`), so it's correct by
|
|
73
|
+
construction and stays correct as the graph changes.
|
|
74
|
+
- Reach for \`nexarch_create_diagram_view\` only when you need a specific,
|
|
75
|
+
hand-picked set of filters that generation doesn't produce.
|
|
76
|
+
- To modify an existing view's filters or layout, \`nexarch_update_diagram_view\`
|
|
77
|
+
is optimistic-locked — always \`nexarch_get_diagram_view\` first to read the
|
|
78
|
+
current \`lockVersion\` and pass it back, or the update will be rejected
|
|
79
|
+
rather than silently overwriting a concurrent edit.
|
|
80
|
+
|
|
81
|
+
## Ground rules
|
|
82
|
+
|
|
83
|
+
- Never write a diagram view no one asked for; a rendered summary in chat is
|
|
84
|
+
enough unless the human wants it saved to the workspace.
|
|
85
|
+
- \`nexarch_list_diagram_revisions\` before assuming a view's current state is
|
|
86
|
+
its only state — check history before concluding something was never
|
|
87
|
+
captured.
|
|
88
|
+
- Confirm which view you updated (name, folder) so the human can find it in
|
|
89
|
+
the workspace, not just in this conversation.
|
|
90
|
+
`;
|
|
91
|
+
const AGENT_WORKQUEUE_SKILL_BODY = `---
|
|
92
|
+
name: nexarch-agent-workqueue
|
|
93
|
+
description: Check for and work through pending Nexarch commands assigned to this agent. Use when the human asks you to check in, look for pending work, process the command queue, or asks whether there's anything waiting for this agent. Requires the Nexarch MCP tools (nexarch_*).
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
# Nexarch Agent Work Queue
|
|
97
|
+
|
|
98
|
+
Nexarch can queue commands for a specific registered agent — review requests,
|
|
99
|
+
scans, follow-ups raised by other agents or humans in the workspace. This
|
|
100
|
+
skill is the check-in → claim → complete loop for working that queue.
|
|
101
|
+
|
|
102
|
+
## Checking in
|
|
103
|
+
|
|
104
|
+
- \`nexarch_check_in\` previews pending commands and draft/proposed
|
|
105
|
+
applications for this agent. It does **not** claim or change anything —
|
|
106
|
+
safe to call any time, including proactively at the start of a session.
|
|
107
|
+
- Report exactly what check-in found. Don't reinterpret "check in" as
|
|
108
|
+
registration (\`init-agent\`) or as a general health check
|
|
109
|
+
(\`nexarch_get_governance_summary\`) — they're different actions.
|
|
110
|
+
- If check-in fails because this agent isn't registered yet, that's a signal
|
|
111
|
+
to register first, not to fall back to a different tool.
|
|
112
|
+
|
|
113
|
+
## Working a command
|
|
114
|
+
|
|
115
|
+
1. Only claim a specific command with \`nexarch_claim_command_by_id\` when the
|
|
116
|
+
human explicitly wants it worked — check-in surfacing a command is not
|
|
117
|
+
itself permission to claim it.
|
|
118
|
+
2. Do the work the command describes.
|
|
119
|
+
3. Close it out: \`nexarch_complete_command\` on success, or
|
|
120
|
+
\`nexarch_fail_command\` with a reason if it couldn't be done. Never leave a
|
|
121
|
+
claimed command unresolved at the end of a session.
|
|
122
|
+
|
|
123
|
+
## Ground rules
|
|
124
|
+
|
|
125
|
+
- \`nexarch_claim_command\` is a legacy alias for \`nexarch_check_in\` — use
|
|
126
|
+
\`nexarch_check_in\` directly, not the alias.
|
|
127
|
+
- One command at a time is fine; don't claim ahead of what you can actually
|
|
128
|
+
finish in this session.
|
|
129
|
+
- Summarize what was claimed, completed, or failed — the human wasn't
|
|
130
|
+
watching the queue directly.
|
|
131
|
+
`;
|
|
132
|
+
const GOVERNANCE_REVIEW_SKILL_BODY = `---
|
|
133
|
+
name: nexarch-governance-review
|
|
134
|
+
description: Check or record compliance, policy audit results, decision conformance, or review a proposed application before activation. Use when asked about compliance or policy status for an app, to run or record a policy audit, whether an architectural decision was actually implemented, or to review/activate an application waiting in the proposed queue. Requires the Nexarch MCP tools (nexarch_*).
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
# Nexarch Governance Review
|
|
138
|
+
|
|
139
|
+
Governance in Nexarch is evidence-backed: controls are assigned to entities,
|
|
140
|
+
audits are recorded (not inferred), and proposed applications wait for
|
|
141
|
+
explicit human activation. This skill covers reading and recording that
|
|
142
|
+
evidence — never invent a compliance status that isn't stored.
|
|
143
|
+
|
|
144
|
+
## Compliance and policy status
|
|
145
|
+
|
|
146
|
+
- Asked about compliance or policy status for an app → \`nexarch_get_policy_audit_results\`
|
|
147
|
+
first. **No stored results means say so** — "no audit has been run" — rather
|
|
148
|
+
than guessing from the code.
|
|
149
|
+
- \`nexarch_get_entity_policy_controls\` to see which controls actually apply
|
|
150
|
+
to a given entity before assessing it against the wrong set.
|
|
151
|
+
- To record a real audit: read the applicable rules from
|
|
152
|
+
\`nexarch_get_applied_policies\`, evaluate the evidence yourself, then
|
|
153
|
+
persist the findings with \`nexarch_submit_policy_audit\`. The tool stores
|
|
154
|
+
results — it does not evaluate anything for you.
|
|
155
|
+
- \`nexarch_submit_decision_conformance\` records whether a repository actually
|
|
156
|
+
implements a \`decision_record\` at a given commit, with evidence. Use this
|
|
157
|
+
when checking whether an architectural decision was followed, not just
|
|
158
|
+
whether it was written down.
|
|
159
|
+
|
|
160
|
+
## Proposed applications
|
|
161
|
+
|
|
162
|
+
- \`nexarch_list_proposed_applications\` — the review queue: apps an agent
|
|
163
|
+
drafted that are waiting on a human.
|
|
164
|
+
- \`nexarch_get_proposed_application\` — full context before recommending
|
|
165
|
+
anything: recommendation provenance, capability gaps, linked policy
|
|
166
|
+
controls, pre-scaffold review requirements.
|
|
167
|
+
- \`nexarch_activate_proposed_application\` moves one to active state. Only
|
|
168
|
+
call this once the human has actually asked for it and the scaffolding is
|
|
169
|
+
real — being listed as proposed is not itself permission to activate.
|
|
170
|
+
|
|
171
|
+
## Ground rules
|
|
172
|
+
|
|
173
|
+
- Findings are evidence, not opinion: cite what \`nexarch_get_policy_audit_results\`
|
|
174
|
+
or \`nexarch_submit_policy_audit\` actually returned rather than paraphrasing
|
|
175
|
+
from memory.
|
|
176
|
+
- Never activate a proposed application on your own judgement alone — surface
|
|
177
|
+
what you found and let the human decide, same as the reuse-before-build
|
|
178
|
+
principle elsewhere in Nexarch.
|
|
179
|
+
`;
|
|
180
|
+
export const SKILLS = [
|
|
181
|
+
{
|
|
182
|
+
templateCode: "nexarch_claude_code_skill_v1",
|
|
183
|
+
dirName: "nexarch-architecture-graph",
|
|
184
|
+
fallbackBody: ARCHITECTURE_GRAPH_SKILL_BODY,
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
templateCode: "nexarch_diagram_views_skill_v1",
|
|
188
|
+
dirName: "nexarch-diagram-views",
|
|
189
|
+
fallbackBody: DIAGRAM_VIEWS_SKILL_BODY,
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
templateCode: "nexarch_agent_workqueue_skill_v1",
|
|
193
|
+
dirName: "nexarch-agent-workqueue",
|
|
194
|
+
fallbackBody: AGENT_WORKQUEUE_SKILL_BODY,
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
templateCode: "nexarch_governance_review_skill_v1",
|
|
198
|
+
dirName: "nexarch-governance-review",
|
|
199
|
+
fallbackBody: GOVERNANCE_REVIEW_SKILL_BODY,
|
|
200
|
+
},
|
|
201
|
+
];
|
|
202
|
+
const RUNTIME_SKILLS_ROOT = {
|
|
203
|
+
"claude-code": [".claude", "skills"],
|
|
204
|
+
"codex-cli": [".agents", "skills"],
|
|
205
|
+
};
|
|
206
|
+
function installSkill(spec, registry, skillsRoot) {
|
|
207
|
+
const template = registry.instructionTemplates.find((t) => t.code === spec.templateCode);
|
|
208
|
+
const body = template ? template.body.trim() + "\n" : spec.fallbackBody;
|
|
67
209
|
const source = template ? "registry" : "fallback";
|
|
68
|
-
const skillDir = join(
|
|
210
|
+
const skillDir = join(skillsRoot, spec.dirName);
|
|
69
211
|
const skillPath = join(skillDir, "SKILL.md");
|
|
70
212
|
if (existsSync(skillPath)) {
|
|
71
213
|
const existing = readFileSync(skillPath, "utf8");
|
|
72
214
|
if (existing === body) {
|
|
73
|
-
return { path: skillPath, status: "already_current", source };
|
|
215
|
+
return { dirName: spec.dirName, path: skillPath, status: "already_current", source };
|
|
74
216
|
}
|
|
75
217
|
writeFileSync(skillPath, body, "utf8");
|
|
76
|
-
return { path: skillPath, status: "updated", source };
|
|
218
|
+
return { dirName: spec.dirName, path: skillPath, status: "updated", source };
|
|
77
219
|
}
|
|
78
220
|
mkdirSync(skillDir, { recursive: true });
|
|
79
221
|
writeFileSync(skillPath, body, "utf8");
|
|
80
|
-
return { path: skillPath, status: "installed", source };
|
|
222
|
+
return { dirName: spec.dirName, path: skillPath, status: "installed", source };
|
|
223
|
+
}
|
|
224
|
+
export function installSkillsForRuntime(registry, runtime, options = {}) {
|
|
225
|
+
const homeDir = options.homeDir ?? homedir();
|
|
226
|
+
const skillsRoot = join(homeDir, ...RUNTIME_SKILLS_ROOT[runtime]);
|
|
227
|
+
return SKILLS.map((spec) => installSkill(spec, registry, skillsRoot));
|
|
81
228
|
}
|