@intutic/sync-daemon 1.6.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.
Files changed (147) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +73 -0
  3. package/dist/brainIndexer.d.ts +51 -0
  4. package/dist/brainIndexer.d.ts.map +1 -0
  5. package/dist/brainIndexer.js +148 -0
  6. package/dist/brainIndexer.js.map +1 -0
  7. package/dist/configReader.d.ts +46 -0
  8. package/dist/configReader.d.ts.map +1 -0
  9. package/dist/configReader.js +133 -0
  10. package/dist/configReader.js.map +1 -0
  11. package/dist/configWriter.d.ts +53 -0
  12. package/dist/configWriter.d.ts.map +1 -0
  13. package/dist/configWriter.js +503 -0
  14. package/dist/configWriter.js.map +1 -0
  15. package/dist/harness/aiderConfigMerger.d.ts +27 -0
  16. package/dist/harness/aiderConfigMerger.d.ts.map +1 -0
  17. package/dist/harness/aiderConfigMerger.js +139 -0
  18. package/dist/harness/aiderConfigMerger.js.map +1 -0
  19. package/dist/harness/antigravityHooks.d.ts +43 -0
  20. package/dist/harness/antigravityHooks.d.ts.map +1 -0
  21. package/dist/harness/antigravityHooks.js +193 -0
  22. package/dist/harness/antigravityHooks.js.map +1 -0
  23. package/dist/harness/claudeCodeHooks.d.ts +59 -0
  24. package/dist/harness/claudeCodeHooks.d.ts.map +1 -0
  25. package/dist/harness/claudeCodeHooks.js +414 -0
  26. package/dist/harness/claudeCodeHooks.js.map +1 -0
  27. package/dist/harness/claudeDesktopHooks.d.ts +30 -0
  28. package/dist/harness/claudeDesktopHooks.d.ts.map +1 -0
  29. package/dist/harness/claudeDesktopHooks.js +267 -0
  30. package/dist/harness/claudeDesktopHooks.js.map +1 -0
  31. package/dist/harness/clineHooks.d.ts +23 -0
  32. package/dist/harness/clineHooks.d.ts.map +1 -0
  33. package/dist/harness/clineHooks.js +169 -0
  34. package/dist/harness/clineHooks.js.map +1 -0
  35. package/dist/harness/continueHooks.d.ts +33 -0
  36. package/dist/harness/continueHooks.d.ts.map +1 -0
  37. package/dist/harness/continueHooks.js +124 -0
  38. package/dist/harness/continueHooks.js.map +1 -0
  39. package/dist/harness/cursorHooks.d.ts +27 -0
  40. package/dist/harness/cursorHooks.d.ts.map +1 -0
  41. package/dist/harness/cursorHooks.js +221 -0
  42. package/dist/harness/cursorHooks.js.map +1 -0
  43. package/dist/harness/cursorHooksJson.d.ts +29 -0
  44. package/dist/harness/cursorHooksJson.d.ts.map +1 -0
  45. package/dist/harness/cursorHooksJson.js +130 -0
  46. package/dist/harness/cursorHooksJson.js.map +1 -0
  47. package/dist/harness/gooseHardener.d.ts +39 -0
  48. package/dist/harness/gooseHardener.d.ts.map +1 -0
  49. package/dist/harness/gooseHardener.js +152 -0
  50. package/dist/harness/gooseHardener.js.map +1 -0
  51. package/dist/harness/gooseHooks.d.ts +24 -0
  52. package/dist/harness/gooseHooks.d.ts.map +1 -0
  53. package/dist/harness/gooseHooks.js +175 -0
  54. package/dist/harness/gooseHooks.js.map +1 -0
  55. package/dist/harness/gooseHooksWriter.d.ts +27 -0
  56. package/dist/harness/gooseHooksWriter.d.ts.map +1 -0
  57. package/dist/harness/gooseHooksWriter.js +147 -0
  58. package/dist/harness/gooseHooksWriter.js.map +1 -0
  59. package/dist/harness/hermesHooks.d.ts +31 -0
  60. package/dist/harness/hermesHooks.d.ts.map +1 -0
  61. package/dist/harness/hermesHooks.js +245 -0
  62. package/dist/harness/hermesHooks.js.map +1 -0
  63. package/dist/harness/mcpAutoWrite.d.ts +35 -0
  64. package/dist/harness/mcpAutoWrite.d.ts.map +1 -0
  65. package/dist/harness/mcpAutoWrite.js +334 -0
  66. package/dist/harness/mcpAutoWrite.js.map +1 -0
  67. package/dist/harness/n8nHooks.d.ts +28 -0
  68. package/dist/harness/n8nHooks.d.ts.map +1 -0
  69. package/dist/harness/n8nHooks.js +205 -0
  70. package/dist/harness/n8nHooks.js.map +1 -0
  71. package/dist/harness/openWebuiHooks.d.ts +31 -0
  72. package/dist/harness/openWebuiHooks.d.ts.map +1 -0
  73. package/dist/harness/openWebuiHooks.js +166 -0
  74. package/dist/harness/openWebuiHooks.js.map +1 -0
  75. package/dist/harness/openclawHooks.d.ts +34 -0
  76. package/dist/harness/openclawHooks.d.ts.map +1 -0
  77. package/dist/harness/openclawHooks.js +296 -0
  78. package/dist/harness/openclawHooks.js.map +1 -0
  79. package/dist/harness/openhandsHooks.d.ts +24 -0
  80. package/dist/harness/openhandsHooks.d.ts.map +1 -0
  81. package/dist/harness/openhandsHooks.js +178 -0
  82. package/dist/harness/openhandsHooks.js.map +1 -0
  83. package/dist/harness/openhandsHooksWriter.d.ts +23 -0
  84. package/dist/harness/openhandsHooksWriter.d.ts.map +1 -0
  85. package/dist/harness/openhandsHooksWriter.js +146 -0
  86. package/dist/harness/openhandsHooksWriter.js.map +1 -0
  87. package/dist/harness/piHooks.d.ts +32 -0
  88. package/dist/harness/piHooks.d.ts.map +1 -0
  89. package/dist/harness/piHooks.js +257 -0
  90. package/dist/harness/piHooks.js.map +1 -0
  91. package/dist/harness/rooCodeHooks.d.ts +31 -0
  92. package/dist/harness/rooCodeHooks.d.ts.map +1 -0
  93. package/dist/harness/rooCodeHooks.js +300 -0
  94. package/dist/harness/rooCodeHooks.js.map +1 -0
  95. package/dist/harness/windsurfHooks.d.ts +27 -0
  96. package/dist/harness/windsurfHooks.d.ts.map +1 -0
  97. package/dist/harness/windsurfHooks.js +202 -0
  98. package/dist/harness/windsurfHooks.js.map +1 -0
  99. package/dist/hashReporter.d.ts +33 -0
  100. package/dist/hashReporter.d.ts.map +1 -0
  101. package/dist/hashReporter.js +69 -0
  102. package/dist/hashReporter.js.map +1 -0
  103. package/dist/index.d.ts +43 -0
  104. package/dist/index.d.ts.map +1 -0
  105. package/dist/index.js +43 -0
  106. package/dist/index.js.map +1 -0
  107. package/dist/integrityStore.d.ts +43 -0
  108. package/dist/integrityStore.d.ts.map +1 -0
  109. package/dist/integrityStore.js +94 -0
  110. package/dist/integrityStore.js.map +1 -0
  111. package/dist/lib/complianceProbes.d.ts +39 -0
  112. package/dist/lib/complianceProbes.d.ts.map +1 -0
  113. package/dist/lib/complianceProbes.js +115 -0
  114. package/dist/lib/complianceProbes.js.map +1 -0
  115. package/dist/lib/processPoller.d.ts +2 -0
  116. package/dist/lib/processPoller.d.ts.map +1 -0
  117. package/dist/lib/processPoller.js +87 -0
  118. package/dist/lib/processPoller.js.map +1 -0
  119. package/dist/lib/runtimeEnv.d.ts +49 -0
  120. package/dist/lib/runtimeEnv.d.ts.map +1 -0
  121. package/dist/lib/runtimeEnv.js +70 -0
  122. package/dist/lib/runtimeEnv.js.map +1 -0
  123. package/dist/skillWriter.d.ts +24 -0
  124. package/dist/skillWriter.d.ts.map +1 -0
  125. package/dist/skillWriter.js +112 -0
  126. package/dist/skillWriter.js.map +1 -0
  127. package/dist/syncLoop.d.ts +70 -0
  128. package/dist/syncLoop.d.ts.map +1 -0
  129. package/dist/syncLoop.js +546 -0
  130. package/dist/syncLoop.js.map +1 -0
  131. package/dist/trajectoryMonitor.d.ts +126 -0
  132. package/dist/trajectoryMonitor.d.ts.map +1 -0
  133. package/dist/trajectoryMonitor.js +291 -0
  134. package/dist/trajectoryMonitor.js.map +1 -0
  135. package/dist/watcher/driftWatcher.d.ts +25 -0
  136. package/dist/watcher/driftWatcher.d.ts.map +1 -0
  137. package/dist/watcher/driftWatcher.js +72 -0
  138. package/dist/watcher/driftWatcher.js.map +1 -0
  139. package/dist/watcher/settingsGuard.d.ts +32 -0
  140. package/dist/watcher/settingsGuard.d.ts.map +1 -0
  141. package/dist/watcher/settingsGuard.js +250 -0
  142. package/dist/watcher/settingsGuard.js.map +1 -0
  143. package/dist/wsClient.d.ts +49 -0
  144. package/dist/wsClient.d.ts.map +1 -0
  145. package/dist/wsClient.js +149 -0
  146. package/dist/wsClient.js.map +1 -0
  147. package/package.json +96 -0
@@ -0,0 +1,70 @@
1
+ /**
2
+ * runtimeEnv.ts — Runtime credential file writer.
3
+ *
4
+ * Writes `~/.intutic/env/runtime.env` on every sync cycle so that generated
5
+ * hook scripts can source it at invocation time instead of having credentials
6
+ * baked in at generation time. This means:
7
+ *
8
+ * 1. Key rotation is instant — next tool call picks up the new key.
9
+ * 2. The key is never embedded in a hook script file on disk.
10
+ * 3. The file is chmod 0600 (owner read/write only).
11
+ *
12
+ * Format (POSIX sh source-compatible):
13
+ *
14
+ * INTUTIC_HOST=https://api.intutic.ai
15
+ * INTUTIC_API_KEY=sk-live-...
16
+ * INTUTIC_WORKSPACE_ID=ws_...
17
+ *
18
+ * LLD #14 — Dual-path hook telemetry (WS-A1)
19
+ *
20
+ * @module
21
+ */
22
+ import * as fs from 'node:fs/promises';
23
+ import * as path from 'node:path';
24
+ import * as os from 'node:os';
25
+ import { createLogger } from '@intutic/logger';
26
+ const log = createLogger('sync-runtime-env');
27
+ /** Default path to the runtime env file sourced by all generated hook scripts. */
28
+ export const DEFAULT_RUNTIME_ENV_PATH = path.join(os.homedir(), '.intutic', 'env', 'runtime.env');
29
+ /**
30
+ * Write runtime credentials to `~/.intutic/env/runtime.env`.
31
+ *
32
+ * Uses atomic rename (.tmp -> final) so hook scripts never read a partial
33
+ * file. Sets permissions to 0o600 (owner read/write only).
34
+ *
35
+ * Safe to call on every sync cycle — idempotent, fast (single write).
36
+ */
37
+ export async function writeRuntimeEnv(opts) {
38
+ const envPath = opts.envPath ?? DEFAULT_RUNTIME_ENV_PATH;
39
+ const envDir = path.dirname(envPath);
40
+ await fs.mkdir(envDir, { recursive: true });
41
+ // Sanitise values: strip newlines to prevent injection into the env file
42
+ const host = (opts.controlPlaneUrl ?? '').replace(/[\r\n]/g, '');
43
+ const key = (opts.apiKey ?? '').replace(/[\r\n]/g, '');
44
+ const wsId = (opts.workspaceId ?? '').replace(/[\r\n]/g, '');
45
+ const content = [
46
+ `# Intutic hook runtime credentials — auto-generated. DO NOT EDIT.`,
47
+ `# Sourced by ~/.intutic/hooks/*.sh and parsed by ~/.intutic/hooks/*.js at invocation time.`,
48
+ `# To rotate your API key: update via the Intutic control plane — daemon refreshes this file automatically.`,
49
+ `# WS-5: INTUTIC_MCP_FAIL_OPEN (Q1), INTUTIC_MCP_PROXY_MODE (Q2), INTUTIC_BYPASS_TIER (Q3) are written on every sync.`,
50
+ `INTUTIC_HOST=${host}`,
51
+ `INTUTIC_API_KEY=${key}`,
52
+ `INTUTIC_WORKSPACE_ID=${wsId}`,
53
+ `INTUTIC_MCP_FAIL_OPEN=${(opts.mcpProxyFailBehavior ?? 'open') !== 'closed' ? 'true' : 'false'}`,
54
+ `INTUTIC_MCP_PROXY_MODE=${opts.mcpProxyMode ?? 'per-session'}`,
55
+ `INTUTIC_BYPASS_TIER=${opts.bypassEnforcementTier ?? 'rewrite'}`,
56
+ ``,
57
+ `# LLM proxy routing (uncomment when Intutic Rust proxy is running on port 8080)`,
58
+ `# GOOSE_BASE_URL=http://127.0.0.1:8080`,
59
+ `# OPENAI_BASE_URL=http://127.0.0.1:8080`,
60
+ `# ANTHROPIC_BASE_URL=http://127.0.0.1:8080`,
61
+ `# LLM_BASE_URL=http://127.0.0.1:8080`,
62
+ ``,
63
+ ].join('\n');
64
+ const tmpPath = envPath + '.tmp';
65
+ await fs.writeFile(tmpPath, content, { encoding: 'utf-8' });
66
+ await fs.chmod(tmpPath, 0o600);
67
+ await fs.rename(tmpPath, envPath);
68
+ log.debug({ action: 'runtime_env_written', path: envPath }, 'Runtime env file refreshed');
69
+ }
70
+ //# sourceMappingURL=runtimeEnv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtimeEnv.js","sourceRoot":"","sources":["../../src/lib/runtimeEnv.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAA;AACtC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AACjC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAA;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAE9C,MAAM,GAAG,GAAG,YAAY,CAAC,kBAAkB,CAAC,CAAA;AAE5C,kFAAkF;AAClF,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,CAAC,CAAA;AAmBjG;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAuB;IAC3D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,wBAAwB,CAAA;IACxD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAEpC,MAAM,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAE3C,yEAAyE;IACzE,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;IAChE,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;IACtD,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;IAE5D,MAAM,OAAO,GAAG;QACd,mEAAmE;QACnE,4FAA4F;QAC5F,4GAA4G;QAC5G,sHAAsH;QACtH,gBAAgB,IAAI,EAAE;QACtB,mBAAmB,GAAG,EAAE;QACxB,wBAAwB,IAAI,EAAE;QAC9B,yBAAyB,CAAC,IAAI,CAAC,oBAAoB,IAAI,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE;QAChG,0BAA0B,IAAI,CAAC,YAAY,IAAI,aAAa,EAAE;QAC9D,uBAAuB,IAAI,CAAC,qBAAqB,IAAI,SAAS,EAAE;QAChE,EAAE;QACF,iFAAiF;QACjF,wCAAwC;QACxC,yCAAyC;QACzC,4CAA4C;QAC5C,sCAAsC;QACtC,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEZ,MAAM,OAAO,GAAG,OAAO,GAAG,MAAM,CAAA;IAChC,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAA;IAC3D,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IAC9B,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAEjC,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,qBAAqB,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,4BAA4B,CAAC,CAAA;AAC3F,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * skillWriter.ts — Write bundled agent skills into the workspace.
3
+ *
4
+ * Unlike SOP files, skills are static documentation for the agent: they are
5
+ * written only when absent (write-if-missing), never overwrite user edits,
6
+ * and are deliberately not tracked by the drift watcher / IntegrityStore.
7
+ *
8
+ * The skill content is embedded as a constant because the daemon runs
9
+ * outside the monorepo. The canonical source is
10
+ * `.agents/skills/intutic-rule-author/SKILL.md` in the open-core repo; a
11
+ * test asserts the two stay identical.
12
+ *
13
+ * @module
14
+ */
15
+ /** Workspace-relative path the rule-author skill is written to. */
16
+ export declare const RULE_AUTHOR_SKILL_PATH: string;
17
+ /** Embedded copy of .agents/skills/intutic-rule-author/SKILL.md (canonical). */
18
+ export declare const RULE_AUTHOR_SKILL = "---\nname: intutic-rule-author\ndescription: Convert natural-language business rules into compiled WASM governance policies enforced by the local Intutic proxy \u2014 author, compile, dry-run, and install rules without a control plane.\n---\n\n# \uD83D\uDCDC Rule Author \u2014 Business Rules as Enforced WASM Policies\n\nUse this skill whenever the user states a rule that AI agent traffic must obey \u2014 \"block any agent call that touches the prod database\", \"kill requests once the session budget drops below $1\", \"never allow shell tool calls containing rm -rf\". You convert the rule into an AssemblyScript policy, compile it to WebAssembly, dry-run it against mock contexts, and install it into the local Intutic proxy. The proxy hot-loads it within ~5 seconds and enforces it on every intercepted LLM request.\n\n## 1. The contract your rule sees\n\nThe proxy calls `evaluate(offset, len)` with a JSON-serialized `RequestContext`:\n\n```jsonc\n{\n \"session_id\": \"sess_x\", \"workspace_id\": \"ws_x\", \"virtual_key_prefix\": \"vk_x\",\n \"model\": \"claude-3-5-sonnet\",\n \"tools\": [{ \"name\": \"bash\", \"description\": \"run shell commands\" }],\n \"tool_calls\": [{ \"id\": \"t1\", \"name\": \"bash\", \"arguments\": {} }],\n \"estimated_input_tokens\": 1200,\n \"budget_remaining_usd\": 4.25,\n \"risk_tier\": \"Low\",\n \"dlp_findings\": [{ \"category\": \"secret\", \"pattern_name\": \"aws_key\", \"action\": \"block\", \"offset\": 0, \"length\": 20 }],\n \"tool_sequence\": [\"read_file\", \"bash\"]\n}\n```\n\n`risk_tier` is one of `Low | Medium | High | Critical`. Return an `i32` verdict: `0` = ALLOW, `1` = BLOCK, `2` = REDACT (treated as block).\n\n## 2. Author\n\nStart from the `@intutic/wasm-sdk` template (`packages/wasm-sdk/` in the open-core repo). Add one function per business rule and call it from `runRules()` in `assembly/index.ts`.\n\nSandbox constraints \u2014 violating them silently disables the rule (the proxy **fails open**):\n\n- 5 ms wall-clock budget, 1,000,000 fuel, 16 MB memory.\n- Keep logic simple: no unbounded loops over `arguments`, no recursion, no I/O (none exists in the sandbox).\n- Host imports are limited to `env.log_info`, `env.trace`, `env.abort`, `env.seed`, and the `onnx_rules.runOnnxInference` stub.\n\n## 3. Compile\n\n```bash\nintutic policy compile --src assembly/index.ts --out build/rule.wasm\n```\n\nRequires AssemblyScript in the project: `pnpm add -D assemblyscript assemblyscript-json`.\n\n## 4. Dry-run \u2014 required before install\n\nAuthor BOTH mock contexts and verify both outcomes before installing:\n\n```bash\nintutic policy test --wasm build/rule.wasm --mock should-block.json\nintutic policy test --wasm build/rule.wasm --mock should-allow.json\n```\n\nThe first must report BLOCK, the second ALLOW. A rule that blocks everything is as broken as one that blocks nothing.\n\n## 5. Install\n\n```bash\nintutic policy install --wasm build/rule.wasm --name block-prod-db --priority 50\nintutic policy list-local\n```\n\nRules install to `~/.intutic/wasm/` as `NN_name.wasm` (lower `NN` runs first; default 100). The proxy picks up changes within ~5 s on the next request \u2014 no restart needed.\n\n## 6. Guardrails\n\n- **Never embed secrets** (API keys, tokens, passwords) in rule sources or mock contexts \u2014 `intutic skill audit` flags them.\n- **Local rules cannot weaken central rules.** Verdicts merge most-restrictive-wins: a KILL from any rule \u2014 local or centrally synced \u2014 ends the request. \"Allow-override\" rules are no-ops by design; do not author them.\n- Keep rule sources (`assembly/*.ts`, mock JSON files) in version control alongside the workspace.\n";
19
+ /**
20
+ * Write bundled skills into the workspace, skipping any that already exist.
21
+ * Returns the paths written (empty when everything was already present).
22
+ */
23
+ export declare function writeBundledSkills(workspaceRoot: string): Promise<string[]>;
24
+ //# sourceMappingURL=skillWriter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillWriter.d.ts","sourceRoot":"","sources":["../src/skillWriter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,mEAAmE;AACnE,eAAO,MAAM,sBAAsB,QAKlC,CAAA;AAED,gFAAgF;AAChF,eAAO,MAAM,iBAAiB,wmHAwE7B,CAAA;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAejF"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * skillWriter.ts — Write bundled agent skills into the workspace.
3
+ *
4
+ * Unlike SOP files, skills are static documentation for the agent: they are
5
+ * written only when absent (write-if-missing), never overwrite user edits,
6
+ * and are deliberately not tracked by the drift watcher / IntegrityStore.
7
+ *
8
+ * The skill content is embedded as a constant because the daemon runs
9
+ * outside the monorepo. The canonical source is
10
+ * `.agents/skills/intutic-rule-author/SKILL.md` in the open-core repo; a
11
+ * test asserts the two stay identical.
12
+ *
13
+ * @module
14
+ */
15
+ import * as node_fs from 'node:fs/promises';
16
+ import * as node_path from 'node:path';
17
+ /** Workspace-relative path the rule-author skill is written to. */
18
+ export const RULE_AUTHOR_SKILL_PATH = node_path.join('.agents', 'skills', 'intutic-rule-author', 'SKILL.md');
19
+ /** Embedded copy of .agents/skills/intutic-rule-author/SKILL.md (canonical). */
20
+ export const RULE_AUTHOR_SKILL = `---
21
+ name: intutic-rule-author
22
+ description: Convert natural-language business rules into compiled WASM governance policies enforced by the local Intutic proxy — author, compile, dry-run, and install rules without a control plane.
23
+ ---
24
+
25
+ # 📜 Rule Author — Business Rules as Enforced WASM Policies
26
+
27
+ Use this skill whenever the user states a rule that AI agent traffic must obey — "block any agent call that touches the prod database", "kill requests once the session budget drops below $1", "never allow shell tool calls containing rm -rf". You convert the rule into an AssemblyScript policy, compile it to WebAssembly, dry-run it against mock contexts, and install it into the local Intutic proxy. The proxy hot-loads it within ~5 seconds and enforces it on every intercepted LLM request.
28
+
29
+ ## 1. The contract your rule sees
30
+
31
+ The proxy calls \`evaluate(offset, len)\` with a JSON-serialized \`RequestContext\`:
32
+
33
+ \`\`\`jsonc
34
+ {
35
+ "session_id": "sess_x", "workspace_id": "ws_x", "virtual_key_prefix": "vk_x",
36
+ "model": "claude-3-5-sonnet",
37
+ "tools": [{ "name": "bash", "description": "run shell commands" }],
38
+ "tool_calls": [{ "id": "t1", "name": "bash", "arguments": {} }],
39
+ "estimated_input_tokens": 1200,
40
+ "budget_remaining_usd": 4.25,
41
+ "risk_tier": "Low",
42
+ "dlp_findings": [{ "category": "secret", "pattern_name": "aws_key", "action": "block", "offset": 0, "length": 20 }],
43
+ "tool_sequence": ["read_file", "bash"]
44
+ }
45
+ \`\`\`
46
+
47
+ \`risk_tier\` is one of \`Low | Medium | High | Critical\`. Return an \`i32\` verdict: \`0\` = ALLOW, \`1\` = BLOCK, \`2\` = REDACT (treated as block).
48
+
49
+ ## 2. Author
50
+
51
+ Start from the \`@intutic/wasm-sdk\` template (\`packages/wasm-sdk/\` in the open-core repo). Add one function per business rule and call it from \`runRules()\` in \`assembly/index.ts\`.
52
+
53
+ Sandbox constraints — violating them silently disables the rule (the proxy **fails open**):
54
+
55
+ - 5 ms wall-clock budget, 1,000,000 fuel, 16 MB memory.
56
+ - Keep logic simple: no unbounded loops over \`arguments\`, no recursion, no I/O (none exists in the sandbox).
57
+ - Host imports are limited to \`env.log_info\`, \`env.trace\`, \`env.abort\`, \`env.seed\`, and the \`onnx_rules.runOnnxInference\` stub.
58
+
59
+ ## 3. Compile
60
+
61
+ \`\`\`bash
62
+ intutic policy compile --src assembly/index.ts --out build/rule.wasm
63
+ \`\`\`
64
+
65
+ Requires AssemblyScript in the project: \`pnpm add -D assemblyscript assemblyscript-json\`.
66
+
67
+ ## 4. Dry-run — required before install
68
+
69
+ Author BOTH mock contexts and verify both outcomes before installing:
70
+
71
+ \`\`\`bash
72
+ intutic policy test --wasm build/rule.wasm --mock should-block.json
73
+ intutic policy test --wasm build/rule.wasm --mock should-allow.json
74
+ \`\`\`
75
+
76
+ The first must report BLOCK, the second ALLOW. A rule that blocks everything is as broken as one that blocks nothing.
77
+
78
+ ## 5. Install
79
+
80
+ \`\`\`bash
81
+ intutic policy install --wasm build/rule.wasm --name block-prod-db --priority 50
82
+ intutic policy list-local
83
+ \`\`\`
84
+
85
+ Rules install to \`~/.intutic/wasm/\` as \`NN_name.wasm\` (lower \`NN\` runs first; default 100). The proxy picks up changes within ~5 s on the next request — no restart needed.
86
+
87
+ ## 6. Guardrails
88
+
89
+ - **Never embed secrets** (API keys, tokens, passwords) in rule sources or mock contexts — \`intutic skill audit\` flags them.
90
+ - **Local rules cannot weaken central rules.** Verdicts merge most-restrictive-wins: a KILL from any rule — local or centrally synced — ends the request. "Allow-override" rules are no-ops by design; do not author them.
91
+ - Keep rule sources (\`assembly/*.ts\`, mock JSON files) in version control alongside the workspace.
92
+ `;
93
+ /**
94
+ * Write bundled skills into the workspace, skipping any that already exist.
95
+ * Returns the paths written (empty when everything was already present).
96
+ */
97
+ export async function writeBundledSkills(workspaceRoot) {
98
+ const written = [];
99
+ const dest = node_path.join(workspaceRoot, RULE_AUTHOR_SKILL_PATH);
100
+ try {
101
+ await node_fs.access(dest);
102
+ return written; // present — never overwrite user edits
103
+ }
104
+ catch {
105
+ // absent → write below
106
+ }
107
+ await node_fs.mkdir(node_path.dirname(dest), { recursive: true });
108
+ await node_fs.writeFile(dest, RULE_AUTHOR_SKILL, 'utf-8');
109
+ written.push(dest);
110
+ return written;
111
+ }
112
+ //# sourceMappingURL=skillWriter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillWriter.js","sourceRoot":"","sources":["../src/skillWriter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,SAAS,MAAM,WAAW,CAAA;AAEtC,mEAAmE;AACnE,MAAM,CAAC,MAAM,sBAAsB,GAAG,SAAS,CAAC,IAAI,CAClD,SAAS,EACT,QAAQ,EACR,qBAAqB,EACrB,UAAU,CACX,CAAA;AAED,gFAAgF;AAChF,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwEhC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,aAAqB;IAC5D,MAAM,OAAO,GAAa,EAAE,CAAA;IAC5B,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,aAAa,EAAE,sBAAsB,CAAC,CAAA;IAElE,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QAC1B,OAAO,OAAO,CAAA,CAAC,uCAAuC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,uBAAuB;IACzB,CAAC;IAED,MAAM,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACjE,MAAM,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,iBAAiB,EAAE,OAAO,CAAC,CAAA;IACzD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAClB,OAAO,OAAO,CAAA;AAChB,CAAC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * syncLoop.ts — Core bidirectional sync loop.
3
+ *
4
+ * The sync loop is the heartbeat of the daemon. Each iteration:
5
+ * 1. Fetches config from the control plane (POST /api/v1/sync/config)
6
+ * 2. If configVersion > local → writes SOP content to harness files
7
+ * 3. Computes SHA-256 hashes of local config files
8
+ * 4. Reports hashes + status back to the control plane
9
+ * 5. Calls the onSync callback with the result
10
+ * 6. Sleeps for pollIntervalMs (AbortSignal-aware)
11
+ * 7. Repeats until signal.aborted
12
+ *
13
+ * Design: never crash on a single iteration failure. Errors are
14
+ * caught per-iteration, logged, and the loop continues.
15
+ *
16
+ * HLD §3.14 — Real-Time State Mirroring
17
+ * LLD #8 — Sync Daemon / CLI
18
+ *
19
+ * @module
20
+ */
21
+ import type { HarnessType, SyncConfigPayload, WorkspaceSettings } from '@intutic/shared-types';
22
+ /** Configuration for the sync loop. */
23
+ export interface SyncLoopOptions {
24
+ /** Control plane base URL (e.g., `https://api.intutic.ai`). */
25
+ controlPlaneUrl: string;
26
+ /** API key for authentication (vk_* or JWT). */
27
+ apiKey: string;
28
+ /** Workspace identifier. */
29
+ workspaceId: string;
30
+ /** Absolute path to the workspace root directory. */
31
+ workspaceRoot: string;
32
+ /** Poll interval in milliseconds (default: 30000). */
33
+ pollIntervalMs?: number;
34
+ /** Enable dev mode (relaxed checks, verbose logging). */
35
+ devMode?: boolean;
36
+ /** Callback invoked after each successful sync iteration. */
37
+ onSync?: (result: SyncResult) => void;
38
+ /** AbortSignal to gracefully stop the loop. */
39
+ signal?: AbortSignal;
40
+ /** Adapter identifier for ContextGraph sync. */
41
+ adapterId?: string;
42
+ }
43
+ /** Result of a single sync iteration. */
44
+ export interface SyncResult {
45
+ /** Config version from the control plane. */
46
+ configVersion: number;
47
+ /** Number of harness config files written. */
48
+ sopsWritten: number;
49
+ /** Number of files with hash drift. */
50
+ driftCount: number;
51
+ /** ISO timestamp of this sync. */
52
+ timestamp: string;
53
+ /** Resolved workspace settings from the control plane. WS-5. */
54
+ settings?: WorkspaceSettings;
55
+ /** All active SOP rules. */
56
+ sops?: SyncConfigPayload['sops'];
57
+ /** Proxy URL. */
58
+ proxyUrl?: string;
59
+ /** Active harnesses. */
60
+ harnesses?: HarnessType[];
61
+ }
62
+ /**
63
+ * Start the sync loop. This function runs indefinitely until the
64
+ * AbortSignal is triggered or the process exits.
65
+ *
66
+ * @param options - Sync loop configuration.
67
+ */
68
+ export declare function startSyncLoop(options: SyncLoopOptions): Promise<void>;
69
+ export declare function syncOfflineTraces(controlPlaneUrl: string, apiKey: string): Promise<void>;
70
+ //# sourceMappingURL=syncLoop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syncLoop.d.ts","sourceRoot":"","sources":["../src/syncLoop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAOH,OAAO,KAAK,EACV,WAAW,EACX,iBAAiB,EAEjB,iBAAiB,EAClB,MAAM,uBAAuB,CAAA;AAe9B,uCAAuC;AACvC,MAAM,WAAW,eAAe;IAC9B,+DAA+D;IAC/D,eAAe,EAAE,MAAM,CAAA;IACvB,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAA;IACd,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,qDAAqD;IACrD,aAAa,EAAE,MAAM,CAAA;IACrB,sDAAsD;IACtD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,yDAAyD;IACzD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAA;IACrC,+CAA+C;IAC/C,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,yCAAyC;AACzC,MAAM,WAAW,UAAU;IACzB,6CAA6C;IAC7C,aAAa,EAAE,MAAM,CAAA;IACrB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAA;IACnB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAA;IACjB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,iBAAiB,CAAA;IAC5B,4BAA4B;IAC5B,IAAI,CAAC,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAA;IAChC,iBAAiB;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,wBAAwB;IACxB,SAAS,CAAC,EAAE,WAAW,EAAE,CAAA;CAC1B;AAQD;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAyN3E;AAkTD,wBAAsB,iBAAiB,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqE9F"}