@intutic/cli 0.1.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 +107 -0
- package/dist/cli.d.ts +14 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +92 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/connect.d.ts +18 -0
- package/dist/commands/connect.d.ts.map +1 -0
- package/dist/commands/connect.js +154 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/init.d.ts +13 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +84 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/login.d.ts +14 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +121 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +8 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +13 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/status.d.ts +11 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +55 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/traces.d.ts +32 -0
- package/dist/commands/traces.d.ts.map +1 -0
- package/dist/commands/traces.js +207 -0
- package/dist/commands/traces.js.map +1 -0
- package/dist/commands/whoami.d.ts +12 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +34 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/config/paths.d.ts +30 -0
- package/dist/config/paths.d.ts.map +1 -0
- package/dist/config/paths.js +53 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/config/store.d.ts +25 -0
- package/dist/config/store.d.ts.map +1 -0
- package/dist/config/store.js +69 -0
- package/dist/config/store.js.map +1 -0
- package/dist/harness/aider.d.ts +12 -0
- package/dist/harness/aider.d.ts.map +1 -0
- package/dist/harness/aider.js +62 -0
- package/dist/harness/aider.js.map +1 -0
- package/dist/harness/antigravity.d.ts +12 -0
- package/dist/harness/antigravity.d.ts.map +1 -0
- package/dist/harness/antigravity.js +69 -0
- package/dist/harness/antigravity.js.map +1 -0
- package/dist/harness/base.d.ts +20 -0
- package/dist/harness/base.d.ts.map +1 -0
- package/dist/harness/base.js +73 -0
- package/dist/harness/base.js.map +1 -0
- package/dist/harness/claudeCode.d.ts +2 -0
- package/dist/harness/claudeCode.d.ts.map +1 -0
- package/dist/harness/claudeCode.js +9 -0
- package/dist/harness/claudeCode.js.map +1 -0
- package/dist/harness/codex.d.ts +13 -0
- package/dist/harness/codex.d.ts.map +1 -0
- package/dist/harness/codex.js +74 -0
- package/dist/harness/codex.js.map +1 -0
- package/dist/harness/cursor.d.ts +2 -0
- package/dist/harness/cursor.d.ts.map +1 -0
- package/dist/harness/cursor.js +9 -0
- package/dist/harness/cursor.js.map +1 -0
- package/dist/harness/detector.d.ts +29 -0
- package/dist/harness/detector.d.ts.map +1 -0
- package/dist/harness/detector.js +61 -0
- package/dist/harness/detector.js.map +1 -0
- package/dist/harness/n8n.d.ts +13 -0
- package/dist/harness/n8n.d.ts.map +1 -0
- package/dist/harness/n8n.js +30 -0
- package/dist/harness/n8n.js.map +1 -0
- package/dist/harness/openhands.d.ts +12 -0
- package/dist/harness/openhands.d.ts.map +1 -0
- package/dist/harness/openhands.js +63 -0
- package/dist/harness/openhands.js.map +1 -0
- package/dist/harness/types.d.ts +30 -0
- package/dist/harness/types.d.ts.map +1 -0
- package/dist/harness/types.js +25 -0
- package/dist/harness/types.js.map +1 -0
- package/dist/harness/windsurf.d.ts +2 -0
- package/dist/harness/windsurf.d.ts.map +1 -0
- package/dist/harness/windsurf.js +9 -0
- package/dist/harness/windsurf.js.map +1 -0
- package/dist/lib/api.d.ts +44 -0
- package/dist/lib/api.d.ts.map +1 -0
- package/dist/lib/api.js +55 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/hash.d.ts +11 -0
- package/dist/lib/hash.d.ts.map +1 -0
- package/dist/lib/hash.js +18 -0
- package/dist/lib/hash.js.map +1 -0
- package/dist/lib/logger.d.ts +18 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +33 -0
- package/dist/lib/logger.js.map +1 -0
- package/package.json +31 -0
package/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# @intutic/cli
|
|
2
|
+
|
|
3
|
+
> AI governance control plane for developer workspaces.
|
|
4
|
+
|
|
5
|
+
Intutic intercepts agent-to-LLM traffic, enforces SOPs, detects anomalies, and tracks costs — all without changing how your team codes.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Install globally
|
|
11
|
+
npm install -g @intutic/cli
|
|
12
|
+
|
|
13
|
+
# Or run directly
|
|
14
|
+
npx @intutic/cli init
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**5 minutes to your first governance verdict:**
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
intutic login # Authenticate with control plane
|
|
21
|
+
intutic init # Detect harnesses, configure proxy
|
|
22
|
+
intutic connect # Start sync daemon (background)
|
|
23
|
+
intutic traces list # See governance verdicts
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Commands
|
|
27
|
+
|
|
28
|
+
| Command | Description |
|
|
29
|
+
|---------|-------------|
|
|
30
|
+
| `intutic init` | Initialize workspace — detect harnesses, configure sync |
|
|
31
|
+
| `intutic login` | Authenticate with control plane (`--api-key`, `--dev`) |
|
|
32
|
+
| `intutic logout` | Clear stored credentials |
|
|
33
|
+
| `intutic status` | Show workspace status — auth, harnesses, sync state |
|
|
34
|
+
| `intutic whoami` | Show current authenticated identity |
|
|
35
|
+
| `intutic connect` | Start sync daemon — bidirectional config sync (`--interval`) |
|
|
36
|
+
| `intutic traces list` | List execution traces (`--limit`, `--since`, `--action`, `--model`, `--json`) |
|
|
37
|
+
| `intutic traces inspect <id>` | Show full detail of a single trace |
|
|
38
|
+
|
|
39
|
+
## Supported Harnesses
|
|
40
|
+
|
|
41
|
+
Intutic auto-detects and configures these AI coding harnesses:
|
|
42
|
+
|
|
43
|
+
| Harness | Detection | Config Method |
|
|
44
|
+
|---------|-----------|---------------|
|
|
45
|
+
| **Claude Code** | `~/.claude/` directory | `CLAUDE.md` + `settings.json` |
|
|
46
|
+
| **Cursor** | `~/.cursor/` directory | `.cursorrules` file |
|
|
47
|
+
| **Aider** | `~/.aider/` directory | `.aider.conf.yml` |
|
|
48
|
+
| **Antigravity** | `~/.gemini/` directory | Environment variables |
|
|
49
|
+
| **Codex** | `~/.codex/` directory | `codex.json` config |
|
|
50
|
+
| **n8n** | Running n8n instance | API integration (stub) |
|
|
51
|
+
| **OpenClaw** | `~/.openclaw/` directory | `config.yaml` |
|
|
52
|
+
| **Hermes** | `~/.hermes/` directory | `config.toml` |
|
|
53
|
+
|
|
54
|
+
## Trace Inspection
|
|
55
|
+
|
|
56
|
+
View governance verdicts directly from the terminal:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# List recent traces (last 24h)
|
|
60
|
+
intutic traces list
|
|
61
|
+
|
|
62
|
+
# Filter by enforcement action
|
|
63
|
+
intutic traces list --action KILL
|
|
64
|
+
|
|
65
|
+
# Filter by model and time window
|
|
66
|
+
intutic traces list --model claude-4 --since 7d
|
|
67
|
+
|
|
68
|
+
# JSON output for scripting
|
|
69
|
+
intutic traces list --json | jq '.traces[] | select(.enforcementAction == "HIJACK")'
|
|
70
|
+
|
|
71
|
+
# Inspect a specific trace
|
|
72
|
+
intutic traces inspect tr_abc123
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Configuration
|
|
76
|
+
|
|
77
|
+
Credentials are stored at `~/.intutic/credentials.json` (mode `0600`).
|
|
78
|
+
|
|
79
|
+
### Environment Variables
|
|
80
|
+
|
|
81
|
+
| Variable | Description |
|
|
82
|
+
|----------|-------------|
|
|
83
|
+
| `INTUTIC_API_URL` | Control plane URL (default: `https://api.intutic.ai`) |
|
|
84
|
+
| `INTUTIC_API_KEY` | API key for non-interactive auth (`vk_*` prefix) |
|
|
85
|
+
|
|
86
|
+
### Development Mode
|
|
87
|
+
|
|
88
|
+
Use `--dev` flag to point at local control plane (`http://localhost:3001`):
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
intutic login --dev
|
|
92
|
+
intutic connect --dev
|
|
93
|
+
intutic traces list --dev
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Documentation
|
|
97
|
+
|
|
98
|
+
Full documentation: [docs.intutic.ai](https://docs.intutic.ai)
|
|
99
|
+
|
|
100
|
+
- [Getting Started](https://docs.intutic.ai/guide/getting-started)
|
|
101
|
+
- [Integration Guides](https://docs.intutic.ai/integrations/)
|
|
102
|
+
- [CLI Reference](https://docs.intutic.ai/reference/cli)
|
|
103
|
+
- [API Reference](https://docs.intutic.ai/reference/api)
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
|
|
107
|
+
Proprietary — see [LICENSE](../../LICENSE) for details.
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Intutic CLI — Entry point
|
|
4
|
+
*
|
|
5
|
+
* AI governance control plane for developer workspaces.
|
|
6
|
+
* Provides harness detection, config sync, and workspace management.
|
|
7
|
+
*
|
|
8
|
+
* LLD #8 — Sync Daemon / CLI
|
|
9
|
+
* HLD §3.14 — Real-Time State Mirroring
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;GAUG"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Intutic CLI — Entry point
|
|
4
|
+
*
|
|
5
|
+
* AI governance control plane for developer workspaces.
|
|
6
|
+
* Provides harness detection, config sync, and workspace management.
|
|
7
|
+
*
|
|
8
|
+
* LLD #8 — Sync Daemon / CLI
|
|
9
|
+
* HLD §3.14 — Real-Time State Mirroring
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
import { Command } from 'commander';
|
|
14
|
+
const program = new Command();
|
|
15
|
+
program
|
|
16
|
+
.name('intutic')
|
|
17
|
+
.description('Intutic CLI — AI governance control plane for developer workspaces')
|
|
18
|
+
.version('0.1.0');
|
|
19
|
+
program
|
|
20
|
+
.command('init')
|
|
21
|
+
.description('Initialize workspace — detect harnesses, configure sync')
|
|
22
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
23
|
+
.action(async (opts) => {
|
|
24
|
+
const { runInit } = await import('./commands/init.js');
|
|
25
|
+
await runInit(opts);
|
|
26
|
+
});
|
|
27
|
+
program
|
|
28
|
+
.command('login')
|
|
29
|
+
.description('Authenticate with the Intutic control plane')
|
|
30
|
+
.option('--api-key <key>', 'Authenticate with an API key (vk_*)')
|
|
31
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
32
|
+
.action(async (opts) => {
|
|
33
|
+
const { runLogin } = await import('./commands/login.js');
|
|
34
|
+
await runLogin(opts);
|
|
35
|
+
});
|
|
36
|
+
program
|
|
37
|
+
.command('logout')
|
|
38
|
+
.description('Clear stored credentials')
|
|
39
|
+
.action(async () => {
|
|
40
|
+
const { runLogout } = await import('./commands/logout.js');
|
|
41
|
+
await runLogout();
|
|
42
|
+
});
|
|
43
|
+
program
|
|
44
|
+
.command('status')
|
|
45
|
+
.description('Show workspace status — auth, harnesses, sync state')
|
|
46
|
+
.action(async () => {
|
|
47
|
+
const { runStatus } = await import('./commands/status.js');
|
|
48
|
+
await runStatus();
|
|
49
|
+
});
|
|
50
|
+
program
|
|
51
|
+
.command('whoami')
|
|
52
|
+
.description('Show current authenticated identity')
|
|
53
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
54
|
+
.action(async (opts) => {
|
|
55
|
+
const { runWhoami } = await import('./commands/whoami.js');
|
|
56
|
+
await runWhoami(opts);
|
|
57
|
+
});
|
|
58
|
+
program
|
|
59
|
+
.command('connect')
|
|
60
|
+
.description('Start sync daemon — bidirectional config sync with control plane')
|
|
61
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
62
|
+
.option('--interval <ms>', 'Poll interval in milliseconds', '30000')
|
|
63
|
+
.action(async (opts) => {
|
|
64
|
+
const { runConnect } = await import('./commands/connect.js');
|
|
65
|
+
await runConnect(opts);
|
|
66
|
+
});
|
|
67
|
+
const traces = program
|
|
68
|
+
.command('traces')
|
|
69
|
+
.description('Query execution traces — list, filter, and inspect');
|
|
70
|
+
traces
|
|
71
|
+
.command('list')
|
|
72
|
+
.description('List execution traces for the workspace')
|
|
73
|
+
.option('--limit <n>', 'Number of traces to show (default: 20, max: 100)')
|
|
74
|
+
.option('--since <duration>', 'Time window, e.g. "24h", "7d", "30m" (default: "24h")')
|
|
75
|
+
.option('--action <type>', 'Filter by enforcement action (BYPASS|ENHANCE|HIJACK|KILL)')
|
|
76
|
+
.option('--model <name>', 'Filter by model name')
|
|
77
|
+
.option('--json', 'Output as JSON instead of table')
|
|
78
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
79
|
+
.action(async (opts) => {
|
|
80
|
+
const { runTracesList } = await import('./commands/traces.js');
|
|
81
|
+
await runTracesList(opts);
|
|
82
|
+
});
|
|
83
|
+
traces
|
|
84
|
+
.command('inspect <trace_id>')
|
|
85
|
+
.description('Show full detail of a single trace')
|
|
86
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
87
|
+
.action(async (traceId, opts) => {
|
|
88
|
+
const { runTracesInspect } = await import('./commands/traces.js');
|
|
89
|
+
await runTracesInspect(traceId, opts);
|
|
90
|
+
});
|
|
91
|
+
program.parse();
|
|
92
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `intutic connect` — Start the sync daemon.
|
|
3
|
+
*
|
|
4
|
+
* Runs a 30-second polling loop that:
|
|
5
|
+
* 1. Fetches config from control plane (active SOPs, proxy URL)
|
|
6
|
+
* 2. Writes SOP content to harness config files
|
|
7
|
+
* 3. Computes SHA-256 hashes of written files
|
|
8
|
+
* 4. Reports hashes + status to control plane
|
|
9
|
+
*
|
|
10
|
+
* HLD §3.14 — Real-Time State Mirroring
|
|
11
|
+
* LLD #8 — Sync Daemon / CLI
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
export declare function runConnect(opts: {
|
|
15
|
+
dev?: boolean;
|
|
16
|
+
interval?: string;
|
|
17
|
+
}): Promise<void>;
|
|
18
|
+
//# sourceMappingURL=connect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAcH,wBAAsB,UAAU,CAAC,IAAI,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgK1F"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `intutic connect` — Start the sync daemon.
|
|
3
|
+
*
|
|
4
|
+
* Runs a 30-second polling loop that:
|
|
5
|
+
* 1. Fetches config from control plane (active SOPs, proxy URL)
|
|
6
|
+
* 2. Writes SOP content to harness config files
|
|
7
|
+
* 3. Computes SHA-256 hashes of written files
|
|
8
|
+
* 4. Reports hashes + status to control plane
|
|
9
|
+
*
|
|
10
|
+
* HLD §3.14 — Real-Time State Mirroring
|
|
11
|
+
* LLD #8 — Sync Daemon / CLI
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
import { log } from '../lib/logger.js';
|
|
15
|
+
import { loadCredentials, loadConfig, saveConfig, loadIntegrity, saveIntegrity } from '../config/store.js';
|
|
16
|
+
import { resolveControlPlaneUrl } from '../config/paths.js';
|
|
17
|
+
import { createApiClient } from '../lib/api.js';
|
|
18
|
+
import { getAdapter } from '../harness/detector.js';
|
|
19
|
+
import { newIso } from '@intutic/id';
|
|
20
|
+
import pc from 'picocolors';
|
|
21
|
+
const DEFAULT_POLL_INTERVAL = 30_000;
|
|
22
|
+
export async function runConnect(opts) {
|
|
23
|
+
// 1. Load credentials + config
|
|
24
|
+
const creds = loadCredentials();
|
|
25
|
+
if (!creds) {
|
|
26
|
+
log.error('Not authenticated. Run `intutic login` first.');
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
const config = loadConfig();
|
|
30
|
+
if (!config) {
|
|
31
|
+
log.error('Workspace not initialized. Run `intutic init` first.');
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
const devMode = opts.dev || process.env.INTUTIC_DEV === '1' || config.devMode;
|
|
35
|
+
const controlPlaneUrl = resolveControlPlaneUrl(devMode);
|
|
36
|
+
const pollInterval = opts.interval ? parseInt(opts.interval, 10) : DEFAULT_POLL_INTERVAL;
|
|
37
|
+
const connectedSince = newIso();
|
|
38
|
+
const client = createApiClient(controlPlaneUrl, creds.apiKey);
|
|
39
|
+
log.header('Intutic — Sync Daemon');
|
|
40
|
+
log.field('Workspace', creds.workspaceId);
|
|
41
|
+
log.field('Control Plane', controlPlaneUrl);
|
|
42
|
+
log.field('Poll Interval', `${pollInterval / 1000}s`);
|
|
43
|
+
log.field('Harnesses', config.harnesses.join(', ') || '(none)');
|
|
44
|
+
console.log('');
|
|
45
|
+
log.info('Starting sync loop... (Ctrl+C to stop)');
|
|
46
|
+
console.log('');
|
|
47
|
+
// 2. AbortController for clean shutdown
|
|
48
|
+
const ac = new AbortController();
|
|
49
|
+
const shutdown = () => {
|
|
50
|
+
log.info('Shutting down...');
|
|
51
|
+
ac.abort();
|
|
52
|
+
};
|
|
53
|
+
process.on('SIGINT', shutdown);
|
|
54
|
+
process.on('SIGTERM', shutdown);
|
|
55
|
+
// 3. Sync loop
|
|
56
|
+
let localConfigVersion = config.configVersion;
|
|
57
|
+
while (!ac.signal.aborted) {
|
|
58
|
+
try {
|
|
59
|
+
// a. Fetch config from control plane
|
|
60
|
+
const syncConfig = await client.fetchConfig(creds.workspaceId);
|
|
61
|
+
let sopsWritten = 0;
|
|
62
|
+
// b. If config version is newer, write to harness files
|
|
63
|
+
if (syncConfig.configVersion > localConfigVersion) {
|
|
64
|
+
for (const harnessType of config.harnesses) {
|
|
65
|
+
const adapter = getAdapter(harnessType);
|
|
66
|
+
if (!adapter)
|
|
67
|
+
continue;
|
|
68
|
+
const targetSops = syncConfig.sops.filter((sop) => sop.harnessTargets.includes(harnessType));
|
|
69
|
+
if (targetSops.length === 0)
|
|
70
|
+
continue;
|
|
71
|
+
const written = await adapter.writeConfig(config.workspaceRoot, targetSops, syncConfig.proxyUrl);
|
|
72
|
+
if (written) {
|
|
73
|
+
sopsWritten += targetSops.length;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
localConfigVersion = syncConfig.configVersion;
|
|
77
|
+
saveConfig({ ...config, configVersion: localConfigVersion });
|
|
78
|
+
}
|
|
79
|
+
// c. Compute file hashes + update integrity store
|
|
80
|
+
const fileHashes = [];
|
|
81
|
+
const canonicalHashes = {};
|
|
82
|
+
// Build canonical hash map from synced SOPs
|
|
83
|
+
const integrity = loadIntegrity(config.workspaceRoot);
|
|
84
|
+
if (integrity) {
|
|
85
|
+
Object.assign(canonicalHashes, integrity.files);
|
|
86
|
+
}
|
|
87
|
+
for (const harnessType of config.harnesses) {
|
|
88
|
+
const adapter = getAdapter(harnessType);
|
|
89
|
+
if (!adapter || !adapter.configFileName)
|
|
90
|
+
continue;
|
|
91
|
+
const currentHash = await adapter.readCurrentHash(config.workspaceRoot);
|
|
92
|
+
if (!currentHash)
|
|
93
|
+
continue;
|
|
94
|
+
const canonical = canonicalHashes[adapter.configFileName] ?? currentHash;
|
|
95
|
+
fileHashes.push({
|
|
96
|
+
filePath: adapter.configFileName,
|
|
97
|
+
localHash: currentHash,
|
|
98
|
+
canonicalHash: canonical,
|
|
99
|
+
drifted: currentHash !== canonical,
|
|
100
|
+
});
|
|
101
|
+
// Update canonical hash to current
|
|
102
|
+
canonicalHashes[adapter.configFileName] = currentHash;
|
|
103
|
+
}
|
|
104
|
+
// Save integrity store
|
|
105
|
+
saveIntegrity(config.workspaceRoot, {
|
|
106
|
+
lastSyncAt: newIso(),
|
|
107
|
+
configVersion: localConfigVersion,
|
|
108
|
+
files: canonicalHashes,
|
|
109
|
+
});
|
|
110
|
+
// d. Report hashes to control plane
|
|
111
|
+
let driftCount = 0;
|
|
112
|
+
if (fileHashes.length > 0) {
|
|
113
|
+
const hashReport = await client.reportHashes({
|
|
114
|
+
workspaceId: creds.workspaceId,
|
|
115
|
+
harnessType: config.harnesses[0],
|
|
116
|
+
files: fileHashes,
|
|
117
|
+
reportedAt: newIso(),
|
|
118
|
+
});
|
|
119
|
+
driftCount = hashReport.driftCount;
|
|
120
|
+
}
|
|
121
|
+
// e. Report status
|
|
122
|
+
await client.reportStatus({
|
|
123
|
+
workspaceId: creds.workspaceId,
|
|
124
|
+
configVersion: localConfigVersion,
|
|
125
|
+
connectedSince,
|
|
126
|
+
lastSyncAt: newIso(),
|
|
127
|
+
harnesses: config.harnesses.map((h) => ({
|
|
128
|
+
type: h,
|
|
129
|
+
configPath: getAdapter(h)?.configFileName ?? '',
|
|
130
|
+
detected: true,
|
|
131
|
+
lastWriteAt: sopsWritten > 0 ? newIso() : null,
|
|
132
|
+
})),
|
|
133
|
+
});
|
|
134
|
+
// f. Log result
|
|
135
|
+
const driftLabel = driftCount > 0 ? pc.yellow(` — ${driftCount} drift(s)`) : '';
|
|
136
|
+
log.dim(`[sync] Config v${localConfigVersion} — ${sopsWritten} SOPs synced${driftLabel} — next check in ${pollInterval / 1000}s`);
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
// Per-iteration error — log and continue
|
|
140
|
+
log.error(`Sync failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
141
|
+
log.dim('Will retry next interval...');
|
|
142
|
+
}
|
|
143
|
+
// g. Sleep until next poll (or abort)
|
|
144
|
+
await new Promise((resolve) => {
|
|
145
|
+
const timer = setTimeout(resolve, pollInterval);
|
|
146
|
+
ac.signal.addEventListener('abort', () => {
|
|
147
|
+
clearTimeout(timer);
|
|
148
|
+
resolve();
|
|
149
|
+
}, { once: true });
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
log.success('Sync daemon stopped.');
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=connect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `intutic init` — Initialize workspace.
|
|
3
|
+
*
|
|
4
|
+
* Detects workspace root, auto-detects harnesses, validates
|
|
5
|
+
* credentials, and writes local config.
|
|
6
|
+
*
|
|
7
|
+
* LLD #8 — Sync Daemon / CLI
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
export declare function runInit(opts: {
|
|
11
|
+
dev?: boolean;
|
|
12
|
+
}): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA2BH,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDpE"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `intutic init` — Initialize workspace.
|
|
3
|
+
*
|
|
4
|
+
* Detects workspace root, auto-detects harnesses, validates
|
|
5
|
+
* credentials, and writes local config.
|
|
6
|
+
*
|
|
7
|
+
* LLD #8 — Sync Daemon / CLI
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync } from 'node:fs';
|
|
11
|
+
import { join, resolve, dirname } from 'node:path';
|
|
12
|
+
import { log } from '../lib/logger.js';
|
|
13
|
+
import { loadCredentials, saveConfig } from '../config/store.js';
|
|
14
|
+
import { detectHarnesses } from '../harness/detector.js';
|
|
15
|
+
import pc from 'picocolors';
|
|
16
|
+
/**
|
|
17
|
+
* Walk up from cwd looking for .git/ or package.json to find workspace root.
|
|
18
|
+
*/
|
|
19
|
+
function findWorkspaceRoot() {
|
|
20
|
+
let dir = process.cwd();
|
|
21
|
+
const root = resolve('/');
|
|
22
|
+
while (dir !== root) {
|
|
23
|
+
if (existsSync(join(dir, '.git')) || existsSync(join(dir, 'package.json'))) {
|
|
24
|
+
return dir;
|
|
25
|
+
}
|
|
26
|
+
const parent = dirname(dir);
|
|
27
|
+
if (parent === dir)
|
|
28
|
+
break;
|
|
29
|
+
dir = parent;
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
export async function runInit(opts) {
|
|
34
|
+
log.header('Intutic — Workspace Initialization');
|
|
35
|
+
// 1. Find workspace root
|
|
36
|
+
const workspaceRoot = findWorkspaceRoot();
|
|
37
|
+
if (!workspaceRoot) {
|
|
38
|
+
log.error('Could not find workspace root (no .git/ or package.json found)');
|
|
39
|
+
log.dim('Run this command from within a project directory.');
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
log.success(`Workspace root: ${workspaceRoot}`);
|
|
43
|
+
// 2. Detect harnesses
|
|
44
|
+
log.info('Detecting AI harnesses...');
|
|
45
|
+
const harnesses = await detectHarnesses(workspaceRoot);
|
|
46
|
+
const detected = harnesses.filter((h) => h.detected);
|
|
47
|
+
const notDetected = harnesses.filter((h) => !h.detected);
|
|
48
|
+
console.log('');
|
|
49
|
+
for (const h of detected) {
|
|
50
|
+
console.log(` ${pc.green('✔')} ${pc.bold(h.type)} ${pc.dim(`→ ${h.configPath}`)}`);
|
|
51
|
+
}
|
|
52
|
+
for (const h of notDetected) {
|
|
53
|
+
console.log(` ${pc.dim('○')} ${pc.dim(h.type)} ${pc.dim('(not detected)')}`);
|
|
54
|
+
}
|
|
55
|
+
console.log('');
|
|
56
|
+
if (detected.length === 0) {
|
|
57
|
+
log.warn('No harnesses detected. Intutic will still work via proxy redirect.');
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
log.success(`Detected ${detected.length} harness${detected.length > 1 ? 'es' : ''}`);
|
|
61
|
+
}
|
|
62
|
+
// 3. Check credentials
|
|
63
|
+
const creds = loadCredentials();
|
|
64
|
+
if (!creds) {
|
|
65
|
+
log.warn('Not authenticated. Run `intutic login` to connect to the control plane.');
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
log.success(`Authenticated as ${creds.email}`);
|
|
69
|
+
}
|
|
70
|
+
// 4. Write config
|
|
71
|
+
const devMode = opts.dev || process.env.INTUTIC_DEV === '1';
|
|
72
|
+
saveConfig({
|
|
73
|
+
workspaceRoot,
|
|
74
|
+
harnesses: detected.map((h) => h.type),
|
|
75
|
+
configVersion: 0,
|
|
76
|
+
devMode,
|
|
77
|
+
});
|
|
78
|
+
log.success('Workspace initialized.');
|
|
79
|
+
if (devMode) {
|
|
80
|
+
log.dim('Dev mode: using local control plane (http://localhost:3001)');
|
|
81
|
+
}
|
|
82
|
+
log.dim('Run `intutic connect` to start syncing governance rules.');
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `intutic login` — Authenticate with the control plane.
|
|
3
|
+
*
|
|
4
|
+
* Supports API key (--api-key vk_...) or email+password.
|
|
5
|
+
* Stores credentials at ~/.intutic/credentials.json (mode 0o600).
|
|
6
|
+
*
|
|
7
|
+
* LLD #8 — Sync Daemon / CLI
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
export declare function runLogin(opts: {
|
|
11
|
+
apiKey?: string;
|
|
12
|
+
dev?: boolean;
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=login.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAsDH,wBAAsB,QAAQ,CAAC,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6DtF"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `intutic login` — Authenticate with the control plane.
|
|
3
|
+
*
|
|
4
|
+
* Supports API key (--api-key vk_...) or email+password.
|
|
5
|
+
* Stores credentials at ~/.intutic/credentials.json (mode 0o600).
|
|
6
|
+
*
|
|
7
|
+
* LLD #8 — Sync Daemon / CLI
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import { log } from '../lib/logger.js';
|
|
11
|
+
import { saveCredentials } from '../config/store.js';
|
|
12
|
+
import { resolveControlPlaneUrl } from '../config/paths.js';
|
|
13
|
+
import { createApiClient } from '../lib/api.js';
|
|
14
|
+
import { newIso } from '@intutic/id';
|
|
15
|
+
import { createInterface } from 'node:readline';
|
|
16
|
+
/**
|
|
17
|
+
* Simple readline prompt (no external deps).
|
|
18
|
+
* For password input, uses muted output.
|
|
19
|
+
*/
|
|
20
|
+
async function prompt(question, hidden = false) {
|
|
21
|
+
const rl = createInterface({
|
|
22
|
+
input: process.stdin,
|
|
23
|
+
output: process.stdout,
|
|
24
|
+
});
|
|
25
|
+
return new Promise((resolve) => {
|
|
26
|
+
if (hidden && process.stdin.isTTY) {
|
|
27
|
+
// Mute output for password entry
|
|
28
|
+
process.stdout.write(question);
|
|
29
|
+
let input = '';
|
|
30
|
+
process.stdin.setRawMode(true);
|
|
31
|
+
process.stdin.resume();
|
|
32
|
+
process.stdin.on('data', (char) => {
|
|
33
|
+
const c = char.toString();
|
|
34
|
+
if (c === '\n' || c === '\r') {
|
|
35
|
+
process.stdin.setRawMode(false);
|
|
36
|
+
process.stdin.pause();
|
|
37
|
+
console.log('');
|
|
38
|
+
rl.close();
|
|
39
|
+
resolve(input);
|
|
40
|
+
}
|
|
41
|
+
else if (c === '\u0003') {
|
|
42
|
+
// Ctrl+C
|
|
43
|
+
process.exit(0);
|
|
44
|
+
}
|
|
45
|
+
else if (c === '\u007f') {
|
|
46
|
+
// Backspace
|
|
47
|
+
input = input.slice(0, -1);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
input += c;
|
|
51
|
+
process.stdout.write('*');
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
rl.question(question, (answer) => {
|
|
57
|
+
rl.close();
|
|
58
|
+
resolve(answer);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
export async function runLogin(opts) {
|
|
64
|
+
log.header('Intutic — Authentication');
|
|
65
|
+
const controlPlaneUrl = resolveControlPlaneUrl(opts.dev);
|
|
66
|
+
log.dim(`Control plane: ${controlPlaneUrl}`);
|
|
67
|
+
if (opts.apiKey) {
|
|
68
|
+
// API key flow
|
|
69
|
+
if (!opts.apiKey.startsWith('vk_')) {
|
|
70
|
+
log.error('API key must start with "vk_"');
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
log.info('Validating API key...');
|
|
74
|
+
const client = createApiClient(controlPlaneUrl, opts.apiKey);
|
|
75
|
+
try {
|
|
76
|
+
const me = await client.getMe();
|
|
77
|
+
saveCredentials({
|
|
78
|
+
apiKey: opts.apiKey,
|
|
79
|
+
workspaceId: me.workspaceId,
|
|
80
|
+
controlPlaneUrl,
|
|
81
|
+
email: me.email,
|
|
82
|
+
storedAt: newIso(),
|
|
83
|
+
});
|
|
84
|
+
log.success(`Authenticated as ${me.email}`);
|
|
85
|
+
log.field('Workspace', me.workspaceId);
|
|
86
|
+
log.field('Role', me.role);
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
log.error(`API key validation failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// Email + password flow
|
|
95
|
+
const email = await prompt('Email: ');
|
|
96
|
+
const password = await prompt('Password: ', true);
|
|
97
|
+
if (!email || !password) {
|
|
98
|
+
log.error('Email and password are required.');
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
log.info('Authenticating...');
|
|
102
|
+
const client = createApiClient(controlPlaneUrl, ''); // No token yet
|
|
103
|
+
try {
|
|
104
|
+
const result = await client.login(email, password);
|
|
105
|
+
saveCredentials({
|
|
106
|
+
apiKey: result.accessToken,
|
|
107
|
+
workspaceId: result.workspaceId,
|
|
108
|
+
controlPlaneUrl,
|
|
109
|
+
email: result.email,
|
|
110
|
+
storedAt: newIso(),
|
|
111
|
+
});
|
|
112
|
+
log.success(`Authenticated as ${result.email}`);
|
|
113
|
+
log.field('Workspace', result.workspaceId);
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
log.error(`Login failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=login.js.map
|