architectonic 0.0.1 → 0.0.3

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/README.md CHANGED
@@ -1,41 +1,71 @@
1
1
  # architectonic
2
2
 
3
- `architectonic` is a command-line tool for installing and wiring the core layers of an agentic system.
3
+ `architectonic` is a command-line tool for composing the core layers of an agentic system.
4
4
 
5
5
  Those layers currently include:
6
6
 
7
7
  ```text
8
- teleology -- purpose, truth, evidence, governance
9
- identity -- actors, roles, authority, privacy, constraints
10
- project -- source-grounded project operating context
11
- skills -- reusable procedures
8
+ teleology -- purpose, principles, doctrine, governance
9
+ identity -- actors, roles, authority, boundaries
10
+ project -- operating context for a concrete initiative
11
+ skills -- reusable procedures and capabilities
12
12
  ```
13
13
 
14
- The initial `0.0.1` release is intentionally minimal. Its job is to reserve the
15
- package name and establish the top-level command surface for future install,
16
- cascade, and upkeep workflows.
14
+ The initial placeholder releases were intentionally minimal. Starting in
15
+ `0.0.3`, `architectonic add` becomes real: it clones the selected layer
16
+ repositories into a target directory and records them in `architectonic.json`.
17
17
 
18
- ## Planned direction
18
+ ## Command shape
19
19
 
20
- Future versions may support commands such as:
20
+ The primary interaction model is:
21
21
 
22
22
  ```text
23
23
  architectonic add teleology
24
24
  architectonic add identity
25
25
  architectonic add project
26
26
  architectonic add skills
27
+ architectonic add teleology identity skills
27
28
  architectonic doctor
29
+ architectonic list
28
30
  architectonic update
29
31
  ```
30
32
 
33
+ `add` is explicit and leaves room for future verbs such as `doctor`, `list`,
34
+ `update`, and `remove`.
35
+
31
36
  ## Current behavior
32
37
 
33
- For now, the CLI only exposes:
38
+ The primary implemented command is:
39
+
40
+ ```text
41
+ npx architectonic add teleology
42
+ npx architectonic add identity
43
+ npx architectonic add project
44
+ npx architectonic add skills
45
+ npx architectonic add teleology identity skills
46
+ npx architectonic add skills --dir ./vendor
47
+ ```
48
+
49
+ `add` clones from the Architectonic GitHub organization into the current
50
+ directory by default:
34
51
 
35
52
  ```text
36
- npx architectonic
37
- npx architectonic help
53
+ ./teleology
54
+ ./identity
55
+ ./project
56
+ ./skills
57
+ ./architectonic.json
38
58
  ```
39
59
 
40
- The `add` surface is reserved, but the installer logic is not implemented in
41
- `0.0.1` yet.
60
+ `architectonic.json` records what was installed and where it landed.
61
+
62
+ If a target directory already exists, the command stops instead of silently
63
+ overwriting it.
64
+
65
+ ## Run vs install
66
+
67
+ ```text
68
+ npx architectonic ... # run immediately
69
+ npm install architectonic # install as a dependency
70
+ npm install -g architectonic # install globally, then run `architectonic ...`
71
+ ```
@@ -1,42 +1,191 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import { spawnSync } from "node:child_process";
6
+
7
+ const VERSION = "0.0.3";
3
8
  const args = process.argv.slice(2);
4
- const [command, target] = args;
9
+ const [command, ...rest] = args;
10
+ const supported = ["teleology", "identity", "project", "skills"];
11
+ const supportedSet = new Set(supported);
12
+ const repoBase = process.env.ARCHITECTONIC_SOURCE_BASE || "https://github.com/architectonic";
5
13
 
6
14
  function printHelp() {
7
- console.log(`architectonic 0.0.1
15
+ console.log(`architectonic ${VERSION}
8
16
 
9
- CLI for installing and wiring the core layers of an agentic system.
17
+ CLI for composing the core layers of an agentic system.
10
18
 
11
19
  Usage:
12
20
  npx architectonic
13
21
  npx architectonic help
14
22
  npx architectonic add <teleology|identity|project|skills>
23
+ npx architectonic add teleology identity skills
24
+ npx architectonic add skills --dir ./vendor
25
+
26
+ Layers:
27
+ teleology purpose, principles, doctrine, governance
28
+ identity actors, roles, authority, boundaries
29
+ project operating context for a concrete initiative
30
+ skills reusable procedures and capabilities
31
+
32
+ Run vs install:
33
+ npx architectonic ... run immediately
34
+ npm install architectonic install in a project
35
+ npm install -g architectonic install globally
36
+
37
+ What add does:
38
+ Clones the selected layer repositories into the target directory
39
+ and records them in architectonic.json.`);
40
+ }
41
+
42
+ function parseAddArgs(tokens) {
43
+ const targets = [];
44
+ let installDir = process.cwd();
45
+
46
+ for (let index = 0; index < tokens.length; index += 1) {
47
+ const token = tokens[index];
48
+ if (token === "--dir" || token === "--out") {
49
+ const next = tokens[index + 1];
50
+ if (!next) {
51
+ throw new Error(`Missing value for ${token}`);
52
+ }
53
+ installDir = path.resolve(next);
54
+ index += 1;
55
+ continue;
56
+ }
57
+ if (token.startsWith("--dir=")) {
58
+ installDir = path.resolve(token.slice("--dir=".length));
59
+ continue;
60
+ }
61
+ if (token.startsWith("--out=")) {
62
+ installDir = path.resolve(token.slice("--out=".length));
63
+ continue;
64
+ }
65
+ if (token.startsWith("-")) {
66
+ throw new Error(`Unknown option: ${token}`);
67
+ }
68
+ targets.push(token);
69
+ }
70
+
71
+ return { targets, installDir };
72
+ }
73
+
74
+ function ensureGitAvailable() {
75
+ const result = spawnSync("git", ["--version"], { encoding: "utf8" });
76
+ if (result.status !== 0) {
77
+ throw new Error("git is required on PATH for `architectonic add`.");
78
+ }
79
+ }
15
80
 
16
- Status:
17
- 0.0.1 reserves the public CLI name and establishes the command surface.
18
- The add subcommands are placeholders in this initial release.`);
81
+ function repoUrlFor(target) {
82
+ const normalizedBase = repoBase.replace(/\\/g, "/");
83
+ if (/^(?:[A-Za-z]:\/|\/|\.{1,2}\/)/.test(normalizedBase)) {
84
+ return path.resolve(normalizedBase, target);
85
+ }
86
+ return `${normalizedBase}/${target}.git`;
19
87
  }
20
88
 
21
- if (!command || command === "help" || command === "--help" || command === "-h") {
22
- printHelp();
23
- process.exit(0);
89
+ function targetPathFor(installDir, target) {
90
+ return path.join(installDir, target);
24
91
  }
25
92
 
26
- if (command === "add") {
27
- const supported = new Set(["teleology", "identity", "project", "skills"]);
28
- if (!target || !supported.has(target)) {
29
- console.error("Specify one of: teleology, identity, project, skills");
30
- process.exit(1);
93
+ function readManifest(manifestPath) {
94
+ if (!fs.existsSync(manifestPath)) {
95
+ return {
96
+ schema_version: 1,
97
+ installed_at: new Date().toISOString(),
98
+ layers: {},
99
+ };
31
100
  }
32
101
 
33
- console.log(`architectonic add ${target}`);
102
+ return JSON.parse(fs.readFileSync(manifestPath, "utf8"));
103
+ }
104
+
105
+ function writeManifest(manifestPath, manifest) {
106
+ fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
107
+ }
108
+
109
+ function cloneLayer(target, installDir) {
110
+ const repoUrl = repoUrlFor(target);
111
+ const targetPath = targetPathFor(installDir, target);
112
+
113
+ if (fs.existsSync(targetPath)) {
114
+ throw new Error(`Target already exists: ${targetPath}`);
115
+ }
116
+
117
+ const clone = spawnSync("git", ["clone", repoUrl, targetPath], {
118
+ cwd: installDir,
119
+ encoding: "utf8",
120
+ stdio: "pipe",
121
+ });
122
+
123
+ if (clone.status !== 0) {
124
+ const detail = (clone.stderr || clone.stdout || "").trim();
125
+ throw new Error(`Failed to clone ${repoUrl}${detail ? `\n${detail}` : ""}`);
126
+ }
127
+
128
+ return {
129
+ name: target,
130
+ repo: repoUrl,
131
+ path: targetPath,
132
+ };
133
+ }
134
+
135
+ function addCommand(tokens) {
136
+ const { targets, installDir } = parseAddArgs(tokens);
137
+
138
+ if (!targets.length) {
139
+ throw new Error("Specify one or more layers: teleology, identity, project, skills");
140
+ }
141
+
142
+ const invalid = targets.filter((target) => !supportedSet.has(target));
143
+ if (invalid.length) {
144
+ throw new Error(`Unknown layer(s): ${invalid.join(", ")}\nSupported layers: ${supported.join(", ")}`);
145
+ }
146
+
147
+ ensureGitAvailable();
148
+ fs.mkdirSync(installDir, { recursive: true });
149
+
150
+ const installed = [];
151
+ for (const target of targets) {
152
+ console.log(`Adding ${target}...`);
153
+ installed.push(cloneLayer(target, installDir));
154
+ }
155
+
156
+ const manifestPath = path.join(installDir, "architectonic.json");
157
+ const manifest = readManifest(manifestPath);
158
+ manifest.installed_at = new Date().toISOString();
159
+ manifest.source_base = repoBase;
160
+
161
+ for (const item of installed) {
162
+ manifest.layers[item.name] = {
163
+ repo: item.repo,
164
+ path: `./${path.relative(installDir, item.path).replace(/\\/g, "/")}`,
165
+ installed_at: manifest.installed_at,
166
+ };
167
+ }
168
+
169
+ writeManifest(manifestPath, manifest);
170
+
34
171
  console.log("");
35
- console.log("This placeholder release does not install packages yet.");
36
- console.log("It reserves the command contract for future cascade/install behavior.");
37
- process.exit(0);
172
+ console.log(`Installed ${installed.map((item) => item.name).join(", ")} into ${installDir}`);
173
+ console.log(`Wrote ${manifestPath}`);
38
174
  }
39
175
 
40
- console.error(`Unknown command: ${command}`);
41
- console.error("Run `architectonic help` for usage.");
42
- process.exit(1);
176
+ try {
177
+ if (!command || command === "help" || command === "--help" || command === "-h") {
178
+ printHelp();
179
+ process.exit(0);
180
+ }
181
+
182
+ if (command === "add") {
183
+ addCommand(rest);
184
+ process.exit(0);
185
+ }
186
+
187
+ throw new Error(`Unknown command: ${command}\nRun \`architectonic help\` for usage.`);
188
+ } catch (error) {
189
+ console.error(error.message);
190
+ process.exit(1);
191
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "architectonic",
3
- "version": "0.0.1",
4
- "description": "CLI for installing and wiring agentic system layers such as teleology, identity, project, and skills.",
3
+ "version": "0.0.3",
4
+ "description": "CLI for composing agentic system layers such as teleology, identity, project, and skills.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "bin": {