@yourtechtribe-labs/koncept-cli 0.1.0-alpha.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/LICENSE +21 -0
- package/README.md +65 -0
- package/dist/args.d.ts +7 -0
- package/dist/args.d.ts.map +1 -0
- package/dist/args.js +33 -0
- package/dist/args.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +52 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/link.d.ts +3 -0
- package/dist/commands/link.d.ts.map +1 -0
- package/dist/commands/link.js +48 -0
- package/dist/commands/link.js.map +1 -0
- package/dist/commands/list.d.ts +3 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +30 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/verify.d.ts +3 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +33 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +60 -0
- package/dist/index.js.map +1 -0
- package/package.json +37 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Albert Gil López — yourtechtribe-labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# @yourtechtribe-labs/koncept-cli
|
|
2
|
+
|
|
3
|
+
> CLI for [koncepto](https://github.com/yourtechtribe-labs/koncept-mcp) — initialize, verify, list, and link operations on `.koncept/` semantic concept graphs.
|
|
4
|
+
|
|
5
|
+
**Status**: pre-alpha (`v0.1.0-alpha.1`).
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add -D @yourtechtribe-labs/koncept-cli@alpha
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or run one-off via `npx`:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx -y @yourtechtribe-labs/koncept-cli@alpha <command>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Commands
|
|
20
|
+
|
|
21
|
+
### `koncepto init`
|
|
22
|
+
|
|
23
|
+
Bootstraps `.koncept/concepts/`, `.koncept/index.json`, and `.koncept/README.md` in the current directory.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx koncepto init
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### `koncepto verify`
|
|
30
|
+
|
|
31
|
+
Validates every concept YAML against the schema, checks cross-references, and writes the index. Exits non-zero on any issue (parse error, duplicate id, unresolved related concept, missing participant file).
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx koncepto verify
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### `koncepto list`
|
|
38
|
+
|
|
39
|
+
Tabular listing of every concept in the registry with id, type, status, and name.
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npx koncepto list
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### `koncepto link <id> <file> --role=<r> --purpose=<p>`
|
|
46
|
+
|
|
47
|
+
Adds a participant entry to an existing concept. Idempotent — duplicates are rejected.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npx koncepto link concept-schema src/lib/foo.ts --role=reader --purpose="parses concepts at startup"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Roles: `writer`, `reader`, `tester`, `docs`.
|
|
54
|
+
|
|
55
|
+
## Companion package
|
|
56
|
+
|
|
57
|
+
Pair this CLI with [`@yourtechtribe-labs/koncept-mcp-server`](https://www.npmjs.com/package/@yourtechtribe-labs/koncept-mcp-server) to expose your concept graph to AI coding agents (Claude Code, Cursor, etc.) over MCP.
|
|
58
|
+
|
|
59
|
+
## License
|
|
60
|
+
|
|
61
|
+
MIT — see [LICENSE](./LICENSE).
|
|
62
|
+
|
|
63
|
+
## Repository
|
|
64
|
+
|
|
65
|
+
Source, issues, and full docs at [github.com/yourtechtribe-labs/koncept-mcp](https://github.com/yourtechtribe-labs/koncept-mcp).
|
package/dist/args.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAA;CACxC;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CA6BpD"}
|
package/dist/args.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export function parseArgs(argv) {
|
|
2
|
+
const flags = {};
|
|
3
|
+
const positional = [];
|
|
4
|
+
let command = null;
|
|
5
|
+
let i = 0;
|
|
6
|
+
for (; i < argv.length; i++) {
|
|
7
|
+
const tok = argv[i];
|
|
8
|
+
if (tok.startsWith('--')) {
|
|
9
|
+
const eq = tok.indexOf('=');
|
|
10
|
+
if (eq > -1) {
|
|
11
|
+
flags[tok.slice(2, eq)] = tok.slice(eq + 1);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
const key = tok.slice(2);
|
|
15
|
+
const next = argv[i + 1];
|
|
16
|
+
if (next !== undefined && !next.startsWith('--')) {
|
|
17
|
+
flags[key] = next;
|
|
18
|
+
i++;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
flags[key] = true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (command === null)
|
|
27
|
+
command = tok;
|
|
28
|
+
else
|
|
29
|
+
positional.push(tok);
|
|
30
|
+
}
|
|
31
|
+
return { command, positional, flags };
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=args.js.map
|
package/dist/args.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,MAAM,KAAK,GAAqC,EAAE,CAAA;IAClD,MAAM,UAAU,GAAa,EAAE,CAAA;IAC/B,IAAI,OAAO,GAAkB,IAAI,CAAA;IACjC,IAAI,CAAC,GAAG,CAAC,CAAA;IAET,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QACnB,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;YAC3B,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;gBACZ,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;YAC7C,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;gBACxB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;gBACxB,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACjD,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAA;oBACjB,CAAC,EAAE,CAAA;gBACL,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAA;gBACnB,CAAC;YACH,CAAC;YACD,SAAQ;QACV,CAAC;QACD,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,GAAG,GAAG,CAAA;;YAC9B,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC3B,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAA;AACvC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AA4BjD,wBAAsB,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBlE"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { mkdir, writeFile, stat } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
const README_TEMPLATE = `# .koncept/
|
|
4
|
+
|
|
5
|
+
This folder holds the **concept graph** for this project — a curated set of
|
|
6
|
+
semantic anchors (behavioral invariants, architectural decisions, data flows,
|
|
7
|
+
ui patterns, naming conventions) that AI agents and humans can read before
|
|
8
|
+
making changes.
|
|
9
|
+
|
|
10
|
+
## Layout
|
|
11
|
+
|
|
12
|
+
\`\`\`
|
|
13
|
+
.koncept/
|
|
14
|
+
├── concepts/ YAML files — one concept per file
|
|
15
|
+
├── index.json Generated by \`koncepto verify\`. Do not hand-edit.
|
|
16
|
+
└── README.md This file.
|
|
17
|
+
\`\`\`
|
|
18
|
+
|
|
19
|
+
## Workflow
|
|
20
|
+
|
|
21
|
+
1. Create concepts under \`concepts/<id>.yaml\` using the schema (see docs).
|
|
22
|
+
2. Run \`koncepto verify\` to validate parse + cross-refs + paths.
|
|
23
|
+
3. Commit \`.koncept/\` so AI agents and teammates see the graph.
|
|
24
|
+
|
|
25
|
+
Concepts MUST be version-controlled. The index is regenerated, but commit it
|
|
26
|
+
so CI / agents have a fast lookup without re-indexing.
|
|
27
|
+
`;
|
|
28
|
+
export async function runInit(ctx) {
|
|
29
|
+
const root = join(ctx.rootDir, '.koncept');
|
|
30
|
+
const concepts = join(root, 'concepts');
|
|
31
|
+
const indexFile = join(root, 'index.json');
|
|
32
|
+
const readme = join(root, 'README.md');
|
|
33
|
+
await mkdir(concepts, { recursive: true });
|
|
34
|
+
if (!(await fileExists(indexFile))) {
|
|
35
|
+
await writeFile(indexFile, '[]\n', 'utf-8');
|
|
36
|
+
}
|
|
37
|
+
if (!(await fileExists(readme))) {
|
|
38
|
+
await writeFile(readme, README_TEMPLATE, 'utf-8');
|
|
39
|
+
}
|
|
40
|
+
process.stdout.write(`koncepto: initialized ${root}\n`);
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
async function fileExists(path) {
|
|
44
|
+
try {
|
|
45
|
+
await stat(path);
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAGhC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;CAwBvB,CAAA;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAmB;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;IACvC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAA;IAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;IAEtC,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC1C,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;QACnC,MAAM,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7C,CAAC;IACD,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QAChC,MAAM,SAAS,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,CAAC,CAAA;IACnD,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,IAAI,IAAI,CAAC,CAAA;IACvD,OAAO,CAAC,CAAA;AACV,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,IAAY;IACpC,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,IAAI,CAAC,CAAA;QAChB,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../src/commands/link.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAKjD,wBAAsB,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAsDlE"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { parseDocument, isMap, isSeq } from 'yaml';
|
|
3
|
+
import { indexConcepts } from '@yourtechtribe-labs/koncept-core';
|
|
4
|
+
const VALID_ROLES = ['writer', 'reader', 'tester', 'docs'];
|
|
5
|
+
export async function runLink(ctx) {
|
|
6
|
+
const [conceptId, file] = ctx.positional;
|
|
7
|
+
const role = ctx.flags.role;
|
|
8
|
+
const purpose = ctx.flags.purpose;
|
|
9
|
+
if (!conceptId || !file) {
|
|
10
|
+
process.stderr.write('koncepto link: usage: koncepto link <id> <file> --role=<r> --purpose=<p>\n');
|
|
11
|
+
return 2;
|
|
12
|
+
}
|
|
13
|
+
if (typeof role !== 'string' || typeof purpose !== 'string') {
|
|
14
|
+
process.stderr.write('koncepto link: --role and --purpose are required\n');
|
|
15
|
+
return 2;
|
|
16
|
+
}
|
|
17
|
+
if (!VALID_ROLES.includes(role)) {
|
|
18
|
+
process.stderr.write(`koncepto link: invalid role "${role}". Must be one of ${VALID_ROLES.join(', ')}\n`);
|
|
19
|
+
return 2;
|
|
20
|
+
}
|
|
21
|
+
const index = await indexConcepts(ctx.rootDir);
|
|
22
|
+
const entry = index.entries.find((e) => e.id === conceptId);
|
|
23
|
+
if (!entry) {
|
|
24
|
+
process.stderr.write(`koncepto link: concept "${conceptId}" not found\n`);
|
|
25
|
+
return 1;
|
|
26
|
+
}
|
|
27
|
+
const text = await readFile(entry.file, 'utf-8');
|
|
28
|
+
const doc = parseDocument(text);
|
|
29
|
+
const participants = doc.get('participants');
|
|
30
|
+
if (!isSeq(participants)) {
|
|
31
|
+
process.stderr.write(`koncepto link: concept "${conceptId}" has no participants sequence\n`);
|
|
32
|
+
return 1;
|
|
33
|
+
}
|
|
34
|
+
const dup = participants.items.some((item) => isMap(item) && item.get('file') === file && item.get('role') === role);
|
|
35
|
+
if (dup) {
|
|
36
|
+
process.stderr.write(`koncepto link: participant {file: "${file}", role: "${role}"} already exists on "${conceptId}"\n`);
|
|
37
|
+
return 1;
|
|
38
|
+
}
|
|
39
|
+
participants.add({ file, role, purpose });
|
|
40
|
+
doc.set('last_updated', today());
|
|
41
|
+
await writeFile(entry.file, String(doc), 'utf-8');
|
|
42
|
+
process.stdout.write(`koncepto link: added ${role} on ${file} to ${conceptId}\n`);
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
function today() {
|
|
46
|
+
return new Date().toISOString().slice(0, 10);
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=link.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link.js","sourceRoot":"","sources":["../../src/commands/link.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,wBAAsB,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAelE"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { indexConcepts } from '@yourtechtribe-labs/koncept-core';
|
|
2
|
+
export async function runList(ctx) {
|
|
3
|
+
const { entries } = await indexConcepts(ctx.rootDir);
|
|
4
|
+
const filtered = applyFilters(entries, ctx.flags);
|
|
5
|
+
if (filtered.length === 0) {
|
|
6
|
+
process.stdout.write('koncepto list: no concepts match\n');
|
|
7
|
+
return 0;
|
|
8
|
+
}
|
|
9
|
+
for (const e of filtered) {
|
|
10
|
+
process.stdout.write(`${e.id.padEnd(32)} ${e.type.padEnd(24)} ${e.status.padEnd(10)} ${e.name}\n`);
|
|
11
|
+
}
|
|
12
|
+
return 0;
|
|
13
|
+
}
|
|
14
|
+
function applyFilters(entries, flags) {
|
|
15
|
+
let out = entries;
|
|
16
|
+
const type = stringFlag(flags.type);
|
|
17
|
+
if (type)
|
|
18
|
+
out = out.filter((e) => e.type === type);
|
|
19
|
+
const status = stringFlag(flags.status);
|
|
20
|
+
if (status)
|
|
21
|
+
out = out.filter((e) => e.status === status);
|
|
22
|
+
const tag = stringFlag(flags.tag);
|
|
23
|
+
if (tag)
|
|
24
|
+
out = out.filter((e) => e.tags.includes(tag));
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
function stringFlag(v) {
|
|
28
|
+
return typeof v === 'string' ? v : null;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAmB,MAAM,kCAAkC,CAAA;AAGjF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAmB;IAC/C,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IACpD,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,CAAA;IAEjD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAA;QAC1D,OAAO,CAAC,CAAA;IACV,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,CAChF,CAAA;IACH,CAAC;IACD,OAAO,CAAC,CAAA;AACV,CAAC;AAED,SAAS,YAAY,CACnB,OAAqB,EACrB,KAAuC;IAEvC,IAAI,GAAG,GAAG,OAAO,CAAA;IACjB,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACnC,IAAI,IAAI;QAAE,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;IAClD,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IACvC,IAAI,MAAM;QAAE,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAA;IACxD,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACjC,IAAI,GAAG;QAAE,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAA;IACtD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAS,UAAU,CAAC,CAA+B;IACjD,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AACzC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/commands/verify.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,wBAAsB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAoCpE"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { indexConcepts, isIndexClean, writeIndex, } from '@yourtechtribe-labs/koncept-core';
|
|
2
|
+
export async function runVerify(ctx) {
|
|
3
|
+
const result = await indexConcepts(ctx.rootDir);
|
|
4
|
+
await writeIndex(ctx.rootDir, result.entries);
|
|
5
|
+
const quiet = ctx.flags.quiet === true;
|
|
6
|
+
if (!quiet) {
|
|
7
|
+
process.stdout.write(`koncepto verify: ${result.entries.length} concept(s) indexed\n`);
|
|
8
|
+
}
|
|
9
|
+
if (isIndexClean(result)) {
|
|
10
|
+
if (!quiet)
|
|
11
|
+
process.stdout.write('koncepto verify: ✓ all checks passed\n');
|
|
12
|
+
return 0;
|
|
13
|
+
}
|
|
14
|
+
for (const e of result.errors) {
|
|
15
|
+
process.stderr.write(`✗ parse: ${e.filePath}\n`);
|
|
16
|
+
for (const err of e.errors) {
|
|
17
|
+
process.stderr.write(` ${err.type}${err.field ? ` @ ${err.field}` : ''}: ${err.message}\n`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
for (const d of result.duplicateIds) {
|
|
21
|
+
process.stderr.write(`✗ duplicate id "${d.id}" in:\n`);
|
|
22
|
+
for (const f of d.files)
|
|
23
|
+
process.stderr.write(` ${f}\n`);
|
|
24
|
+
}
|
|
25
|
+
for (const u of result.unresolvedRelated) {
|
|
26
|
+
process.stderr.write(`✗ unresolved related: "${u.conceptId}" → "${u.missingRelatedId}"\n`);
|
|
27
|
+
}
|
|
28
|
+
for (const m of result.missingFiles) {
|
|
29
|
+
process.stderr.write(`✗ missing participant file: "${m.conceptId}" → "${m.missingFile}"\n`);
|
|
30
|
+
}
|
|
31
|
+
return 1;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/commands/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,YAAY,EACZ,UAAU,GACX,MAAM,kCAAkC,CAAA;AAGzC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAmB;IACjD,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAC/C,MAAM,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;IAE7C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,CAAA;IACtC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,MAAM,CAAC,OAAO,CAAC,MAAM,uBAAuB,CAAC,CAAA;IACxF,CAAC;IAED,IAAI,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,IAAI,CAAC,KAAK;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAA;QAC1E,OAAO,CAAC,CAAA;IACV,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAC9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAA;QAChD,KAAK,MAAM,GAAG,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;YAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,OAAO,IAAI,CAAC,CAAA;QAChG,CAAC;IACH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAA;QACtD,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7D,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC;QACzC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,0BAA0B,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,gBAAgB,KAAK,CACrE,CAAA;IACH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,gCAAgC,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,WAAW,KAAK,CACtE,CAAA;IACH,CAAC;IAED,OAAO,CAAC,CAAA;AACV,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAyBA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAA;CACxC;AAWD,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBtF"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { parseArgs } from './args.js';
|
|
5
|
+
import { runInit } from './commands/init.js';
|
|
6
|
+
import { runVerify } from './commands/verify.js';
|
|
7
|
+
import { runList } from './commands/list.js';
|
|
8
|
+
import { runLink } from './commands/link.js';
|
|
9
|
+
const VERSION = '0.1.0-alpha.0';
|
|
10
|
+
const HELP = `koncepto ${VERSION}
|
|
11
|
+
|
|
12
|
+
Usage:
|
|
13
|
+
koncepto init Bootstrap .koncept/ in cwd
|
|
14
|
+
koncepto verify Validate concepts and write index.json
|
|
15
|
+
koncepto list [--type] [--tag] List concepts (with optional filters)
|
|
16
|
+
[--status]
|
|
17
|
+
koncepto link <id> <file> Add a participant to an existing concept
|
|
18
|
+
--role=<r> --purpose=<p>
|
|
19
|
+
|
|
20
|
+
Flags:
|
|
21
|
+
--help, --version
|
|
22
|
+
`;
|
|
23
|
+
const COMMANDS = {
|
|
24
|
+
init: runInit,
|
|
25
|
+
verify: runVerify,
|
|
26
|
+
list: runList,
|
|
27
|
+
link: runLink,
|
|
28
|
+
};
|
|
29
|
+
export async function run(argv, cwd = process.cwd()) {
|
|
30
|
+
const { command, positional, flags } = parseArgs(argv);
|
|
31
|
+
if (flags.help || command === 'help') {
|
|
32
|
+
process.stdout.write(HELP);
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
if (flags.version) {
|
|
36
|
+
process.stdout.write(`${VERSION}\n`);
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
if (command === null) {
|
|
40
|
+
process.stdout.write(HELP);
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
const handler = COMMANDS[command];
|
|
44
|
+
if (!handler) {
|
|
45
|
+
process.stderr.write(`koncepto: unknown command "${command}"\n${HELP}`);
|
|
46
|
+
return 64;
|
|
47
|
+
}
|
|
48
|
+
return handler({ rootDir: resolve(cwd), positional, flags });
|
|
49
|
+
}
|
|
50
|
+
const invokedAsScript = process.argv[1] !== undefined &&
|
|
51
|
+
import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
52
|
+
if (invokedAsScript) {
|
|
53
|
+
run(process.argv.slice(2))
|
|
54
|
+
.then((code) => process.exit(code))
|
|
55
|
+
.catch((err) => {
|
|
56
|
+
process.stderr.write(`koncepto: fatal: ${String(err)}\n`);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAE5C,MAAM,OAAO,GAAG,eAAe,CAAA;AAE/B,MAAM,IAAI,GAAG,YAAY,OAAO;;;;;;;;;;;;CAY/B,CAAA;AAUD,MAAM,QAAQ,GAA4B;IACxC,IAAI,EAAE,OAAO;IACb,MAAM,EAAE,SAAS;IACjB,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,OAAO;CACd,CAAA;AAED,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,IAAc,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IACnE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;IAEtD,IAAI,KAAK,CAAC,IAAI,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC1B,OAAO,CAAC,CAAA;IACV,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAA;QACpC,OAAO,CAAC,CAAA;IACV,CAAC;IACD,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC1B,OAAO,CAAC,CAAA;IACV,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;IACjC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,OAAO,MAAM,IAAI,EAAE,CAAC,CAAA;QACvE,OAAO,EAAE,CAAA;IACX,CAAC;IAED,OAAO,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAA;AAC9D,CAAC;AAED,MAAM,eAAe,GACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS;IAC7B,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AAEzD,IAAI,eAAe,EAAE,CAAC;IACpB,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SACvB,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;SAClC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC,CAAC,CAAA;AACN,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yourtechtribe-labs/koncept-cli",
|
|
3
|
+
"version": "0.1.0-alpha.1",
|
|
4
|
+
"description": "CLI for koncepto — init, verify, list, link operations on .koncept/ concept graphs.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"koncepto": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@yourtechtribe-labs/koncept-core": "^0.1.0-alpha.1",
|
|
17
|
+
"glob": "13.0.6",
|
|
18
|
+
"yaml": "2.8.4"
|
|
19
|
+
},
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public",
|
|
22
|
+
"tag": "alpha"
|
|
23
|
+
},
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"homepage": "https://github.com/yourtechtribe-labs/koncept-mcp",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/yourtechtribe-labs/koncept-mcp",
|
|
29
|
+
"directory": "packages/koncept-cli"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc",
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"lint": "echo 'lint stub'",
|
|
35
|
+
"clean": "rm -rf dist"
|
|
36
|
+
}
|
|
37
|
+
}
|