@kntic/kntic 0.6.0 → 0.7.0

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,93 +1,162 @@
1
- # Control
1
+ # @kntic/kntic
2
2
 
3
+ KNTIC CLI — bootstrap and manage KNTIC AI-orchestrated projects.
3
4
 
5
+ ## Requirements
4
6
 
5
- ## Getting started
7
+ - **Node.js** >= 18.0.0
8
+ - **Docker** (with `docker compose` v2) — required for `kntic start` / `kntic stop`
9
+ - **GNU screen** _(optional)_ — needed for `kntic start --screen`
10
+ - **Git** _(optional)_ — enables auto-detection of `GIT_HOST`, `GIT_REPO_PATH`, and `GITLAB_TOKEN` during `kntic init`
6
11
 
7
- To make it easy for you to get started with GitLab, here's a list of recommended next steps.
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install -g @kntic/kntic
16
+ ```
17
+
18
+ ## Preflight Checks
8
19
 
9
- Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
20
+ When running `kntic init`, the CLI performs automatic preflight checks before downloading the bootstrap archive. All checks are **warnings only** they never block execution.
10
21
 
11
- ## Add your files
22
+ | Check | Condition | Warning |
23
+ |-------|-----------|---------|
24
+ | **Platform** | `process.platform !== "linux"` | `⚠ Non-Linux detected (<platform>) — KNTIC is designed for Linux, other platforms may have issues` |
25
+ | **Docker** | `docker` binary not found in `$PATH` | `⚠ docker not found — required for \`kntic start\`` |
26
+ | **Screen** | `screen` binary not found in `$PATH` | `⚠ screen not found — optional, needed for \`kntic start --screen\`` |
12
27
 
13
- * [Create](https://docs.gitlab.com/user/project/repository/web_editor/#create-a-file) or [upload](https://docs.gitlab.com/user/project/repository/web_editor/#upload-a-file) files
14
- * [Add files using the command line](https://docs.gitlab.com/topics/git/add_files/#add-files-to-a-git-repository) or push an existing Git repository with the following command:
28
+ ## Commands
15
29
 
30
+ ### `kntic usage`
31
+
32
+ List all available sub-commands.
33
+
34
+ ```bash
35
+ kntic usage
16
36
  ```
17
- cd existing_repo
18
- git remote add origin https://gitlab.kommune7.wien/kntic-ai/orchestrator/control.git
19
- git branch -M main
20
- git push -uf origin main
37
+
38
+ ---
39
+
40
+ ### `kntic init`
41
+
42
+ Download and extract the KNTIC bootstrap template into the current directory. Sets up the `.kntic/` directory structure, `kntic.yml`, and `.kntic.env`.
43
+
44
+ ```bash
45
+ kntic init [--quick | --interactive | -i]
21
46
  ```
22
47
 
23
- ## Integrate with your tools
48
+ | Option | Description |
49
+ |--------|-------------|
50
+ | `--quick` | **Default.** Non-interactive mode. Auto-detects `GIT_HOST` and `GIT_REPO_PATH` from the git origin remote (SSH and HTTPS). Extracts `GITLAB_TOKEN` from HTTPS credentials if available (`glpat-*` tokens). |
51
+ | `--interactive`, `-i` | Walks through all `.kntic.env` values interactively, prompting for each variable. Auto-detected values are pre-filled as defaults. Skips `KNTIC_VERSION` and already-detected `GITLAB_TOKEN`. |
24
52
 
25
- * [Set up project integrations](https://gitlab.kommune7.wien/kntic-ai/orchestrator/control/-/settings/integrations)
53
+ **What it does:**
26
54
 
27
- ## Collaborate with your team
55
+ 1. Runs [preflight checks](#preflight-checks)
56
+ 2. Fetches version metadata from the bootstrap artifact URL
57
+ 3. Downloads and extracts the bootstrap archive (merges `.gitignore` if one already exists)
58
+ 4. Appends `KNTIC_VERSION=<version>` to `.kntic.env`
59
+ 5. Auto-detects git remote information and fills `GIT_HOST`, `GIT_REPO_PATH`, and `GITLAB_TOKEN`
60
+ 6. _(Interactive mode only)_ Prompts for remaining `.kntic.env` values
28
61
 
29
- * [Invite team members and collaborators](https://docs.gitlab.com/user/project/members/)
30
- * [Create a new merge request](https://docs.gitlab.com/user/project/merge_requests/creating_merge_requests/)
31
- * [Automatically close issues from merge requests](https://docs.gitlab.com/user/project/issues/managing_issues/#closing-issues-automatically)
32
- * [Enable merge request approvals](https://docs.gitlab.com/user/project/merge_requests/approvals/)
33
- * [Set auto-merge](https://docs.gitlab.com/user/project/merge_requests/auto_merge/)
62
+ ---
34
63
 
35
- ## Test and Deploy
64
+ ### `kntic start`
36
65
 
37
- Use the built-in continuous integration in GitLab.
66
+ Build and start KNTIC services via Docker Compose.
38
67
 
39
- * [Get started with GitLab CI/CD](https://docs.gitlab.com/ci/quick_start/)
40
- * [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/user/application_security/sast/)
41
- * [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/topics/autodevops/requirements/)
42
- * [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/user/clusters/agent/)
43
- * [Set up protected environments](https://docs.gitlab.com/ci/environments/protected_environments/)
68
+ ```bash
69
+ kntic start [--screen]
70
+ ```
44
71
 
45
- ***
72
+ | Option | Description |
73
+ |--------|-------------|
74
+ | `--screen` | Wrap the Docker Compose process in a GNU `screen` session. The session name is read from `KNTIC_PRJ_PREFIX` in `.kntic.env`, falling back to the current directory name. Skipped if already inside a screen session or if `screen` is not available. |
46
75
 
47
- # Editing this README
76
+ Runs:
77
+ ```bash
78
+ docker compose -f kntic.yml --env-file .kntic.env up --build
79
+ ```
48
80
 
49
- When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
81
+ ---
50
82
 
51
- ## Suggestions for a good README
83
+ ### `kntic stop`
52
84
 
53
- Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
85
+ Stop KNTIC services via Docker Compose.
54
86
 
55
- ## Name
56
- Choose a self-explaining name for your project.
87
+ ```bash
88
+ kntic stop
89
+ ```
57
90
 
58
- ## Description
59
- Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
91
+ Runs:
92
+ ```bash
93
+ docker compose -f kntic.yml --env-file .kntic.env stop
94
+ ```
60
95
 
61
- ## Badges
62
- On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
96
+ ---
63
97
 
64
- ## Visuals
65
- Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
98
+ ### `kntic update`
66
99
 
67
- ## Installation
68
- Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
100
+ Download the latest KNTIC bootstrap archive and update managed files.
101
+
102
+ ```bash
103
+ kntic update [--lib-only] [--compose]
104
+ ```
105
+
106
+ | Option | Description |
107
+ |--------|-------------|
108
+ | `--lib-only` | Update only `.kntic/lib/` (skip ADRs, hooks, and weights). |
109
+ | `--compose` | Also replace `kntic.yml` from the bootstrap template. Creates a backup at `kntic.yml.bak` before overwriting. |
110
+
111
+ **Default update scope** (without `--lib-only`):
69
112
 
70
- ## Usage
71
- Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
113
+ | Path | Strategy |
114
+ |------|----------|
115
+ | `.kntic/lib/` | **Replaced** — cleared and re-extracted |
116
+ | `.kntic/adrs/` | **Replaced** — cleared and re-extracted |
117
+ | `.kntic/hooks/gia/internal/` | **Updated** — existing files overwritten, new files added, unlisted files preserved |
118
+ | `.kntic/hooks/gia/specific/` | **Bootstrap only** — extracted only if the directory does not already exist (user customizations are never overwritten) |
119
+ | `.kntic/gia/weights.json` | **Replaced** if present in the archive |
120
+ | `.kntic.env` | **Merged** — new variables from the template are appended with their comments; existing values are never overwritten |
121
+ | `KNTIC_VERSION` | Updated in `.kntic.env` to the latest version |
72
122
 
73
- ## Support
74
- Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
123
+ ## Environment Variables
75
124
 
76
- ## Roadmap
77
- If you have ideas for releases in the future, it is a good idea to list them in the README.
125
+ The `.kntic.env` file contains project configuration:
78
126
 
79
- ## Contributing
80
- State if you are open to contributions and what your requirements are for accepting them.
127
+ | Variable | Description |
128
+ |----------|-------------|
129
+ | `ANTHROPIC_API_KEY` | API key for Anthropic (used by the orchestrator engine) |
130
+ | `UID` | Host user ID for container user mapping |
131
+ | `GID` | Host group ID for container user mapping |
132
+ | `GITLAB_TOKEN` | GitLab personal access token (`glpat-*`) |
133
+ | `GIT_HOST` | Git server hostname (auto-detected from origin remote) |
134
+ | `GIT_REPO_PATH` | Repository path on the git server (auto-detected from origin remote) |
135
+ | `KNTIC_VERSION` | Bootstrap version (set automatically by `kntic init` / `kntic update`) |
136
+ | `KNTIC_PRJ_PREFIX` | Project prefix used for screen session naming in `kntic start --screen` |
81
137
 
82
- For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
138
+ ## Services
83
139
 
84
- You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
140
+ Defined in `kntic.yml`:
85
141
 
86
- ## Authors and acknowledgment
87
- Show your appreciation to those who have contributed to the project.
142
+ | Service | Container | Image | Port |
143
+ |---------|-----------|-------|------|
144
+ | **Dashboard** | `control-dashboard` | `kntic/dashboard:latest` | `8002` |
145
+ | **Orchestrator** | `control-engine` | `nexus.kommune7.wien/kntic/kntic-engine:latest` | — |
146
+
147
+ Both services run as `${UID}:${GID}` (non-root) and use `.kntic.env` for environment configuration.
148
+
149
+ ## Testing
150
+
151
+ ```bash
152
+ npm test
153
+ ```
154
+
155
+ Runs tests using the Node.js built-in test runner:
156
+ ```bash
157
+ node --test src/**/*.test.js
158
+ ```
88
159
 
89
160
  ## License
90
- For open source projects, say how it is licensed.
91
161
 
92
- ## Project status
93
- If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
162
+ [MIT](LICENSE)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kntic/kntic",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "author": "Thomas Robak <contact@kntic.ai> (https://kntic.ai)",
5
5
  "description": "KNTIC CLI — bootstrap and manage KNTIC projects",
6
6
  "main": "src/index.js",
@@ -270,7 +270,46 @@ function interactiveEnvSetup(envPath) {
270
270
  });
271
271
  }
272
272
 
273
+ /**
274
+ * Run preflight checks before downloading the bootstrap archive.
275
+ * All checks are warnings only — they never throw or exit.
276
+ * Returns an array of warning strings (empty if all checks pass).
277
+ */
278
+ function preflightChecks() {
279
+ const warnings = [];
280
+
281
+ // 1. Linux platform check
282
+ if (process.platform !== "linux") {
283
+ warnings.push(
284
+ `⚠ Non-Linux detected (${process.platform}) — KNTIC is designed for Linux, other platforms may have issues`
285
+ );
286
+ }
287
+
288
+ // 2. docker binary check
289
+ try {
290
+ execSync("which docker", { stdio: "ignore" });
291
+ } catch {
292
+ warnings.push("⚠ docker not found — required for `kntic start`");
293
+ }
294
+
295
+ // 3. screen binary check
296
+ try {
297
+ execSync("which screen", { stdio: "ignore" });
298
+ } catch {
299
+ warnings.push("⚠ screen not found — optional, needed for `kntic start --screen`");
300
+ }
301
+
302
+ for (const w of warnings) {
303
+ console.log(w);
304
+ }
305
+
306
+ return warnings;
307
+ }
308
+
273
309
  async function init(options = {}) {
310
+ // Run preflight checks before anything else
311
+ preflightChecks();
312
+
274
313
  // Resolve current version from the artifact metadata file
275
314
  const artifactFilename = await fetchText(BOOTSTRAP_ARTIFACT_URL);
276
315
  const version = extractVersion(artifactFilename);
@@ -317,3 +356,4 @@ module.exports.extractArchive = extractArchive;
317
356
  module.exports.extractVersion = extractVersion;
318
357
  module.exports.parseGitRemote = parseGitRemote;
319
358
  module.exports.fillEnvValues = fillEnvValues;
359
+ module.exports.preflightChecks = preflightChecks;
@@ -7,7 +7,7 @@ const path = require("path");
7
7
  const os = require("os");
8
8
  const { execSync } = require("child_process");
9
9
 
10
- const { extractArchive, extractVersion, parseGitRemote, fillEnvValues } = require("./init");
10
+ const { extractArchive, extractVersion, parseGitRemote, fillEnvValues, preflightChecks } = require("./init");
11
11
 
12
12
  /**
13
13
  * Helper — create a tar.gz archive in `tmpDir` containing the given files.
@@ -28,6 +28,68 @@ function createTarball(tmpDir, files) {
28
28
  return tarball;
29
29
  }
30
30
 
31
+ describe("preflightChecks", () => {
32
+ let originalPlatform;
33
+ let logMessages;
34
+ let originalLog;
35
+
36
+ beforeEach(() => {
37
+ originalPlatform = Object.getOwnPropertyDescriptor(process, "platform");
38
+ originalLog = console.log;
39
+ logMessages = [];
40
+ console.log = (...args) => logMessages.push(args.join(" "));
41
+ });
42
+
43
+ afterEach(() => {
44
+ Object.defineProperty(process, "platform", originalPlatform);
45
+ console.log = originalLog;
46
+ });
47
+
48
+ it("warns when platform is not linux", () => {
49
+ Object.defineProperty(process, "platform", { value: "darwin", configurable: true });
50
+ const warnings = preflightChecks();
51
+ const platformWarning = warnings.find((w) => w.includes("Non-Linux detected"));
52
+ assert.ok(platformWarning, "should warn about non-linux platform");
53
+ assert.ok(platformWarning.includes("darwin"));
54
+ });
55
+
56
+ it("does not warn about platform on linux", () => {
57
+ Object.defineProperty(process, "platform", { value: "linux", configurable: true });
58
+ const warnings = preflightChecks();
59
+ const platformWarning = warnings.find((w) => w.includes("Non-Linux detected"));
60
+ assert.equal(platformWarning, undefined, "should not warn on linux");
61
+ });
62
+
63
+ it("warns when docker is not found", () => {
64
+ // We test by checking the function handles missing binaries.
65
+ // On the test system docker may or may not exist, so we check the structure.
66
+ const warnings = preflightChecks();
67
+ // Each warning should be a string
68
+ for (const w of warnings) {
69
+ assert.equal(typeof w, "string");
70
+ }
71
+ });
72
+
73
+ it("each warning is independent (all checks run)", () => {
74
+ Object.defineProperty(process, "platform", { value: "win32", configurable: true });
75
+ const warnings = preflightChecks();
76
+ // Platform warning must be present regardless of binary check results
77
+ const platformWarning = warnings.find((w) => w.includes("Non-Linux detected"));
78
+ assert.ok(platformWarning, "platform warning must be present");
79
+ assert.ok(platformWarning.includes("win32"));
80
+ // All warnings are logged to console
81
+ assert.equal(logMessages.length, warnings.length, "all warnings must be logged");
82
+ });
83
+
84
+ it("prints warnings to console.log", () => {
85
+ Object.defineProperty(process, "platform", { value: "freebsd", configurable: true });
86
+ const warnings = preflightChecks();
87
+ // At least the platform warning should be logged
88
+ const platformLog = logMessages.find((m) => m.includes("Non-Linux detected"));
89
+ assert.ok(platformLog, "platform warning must be printed via console.log");
90
+ });
91
+ });
92
+
31
93
  describe("extractArchive", () => {
32
94
  let tmpDir;
33
95
  let destDir;