@webpresso/agent-kit 3.1.30 → 3.2.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.

Potentially problematic release.


This version of @webpresso/agent-kit might be problematic. Click here for more details.

Files changed (257) hide show
  1. package/README.md +53 -15
  2. package/bin/_run.js +179 -19
  3. package/catalog/AGENTS.md.tpl +3 -3
  4. package/catalog/agent/agents/implementer.md +45 -0
  5. package/catalog/agent/rules/parallel-orchestration-quota.md +100 -0
  6. package/catalog/agent/rules/pre-implementation.md +28 -1
  7. package/catalog/agent/rules/supported-agent-clis.md +9 -0
  8. package/catalog/agent/rules/typescript-version.md +50 -0
  9. package/catalog/agent/skills/codex/SKILL.md +25 -1
  10. package/catalog/agent/skills/verify/SKILL.md +4 -2
  11. package/catalog/docs/templates/blueprint.md +1 -1
  12. package/dist/esm/audit/agents.js +1 -0
  13. package/dist/esm/audit/blueprint-lifecycle-sql.d.ts +12 -0
  14. package/dist/esm/audit/blueprint-lifecycle-sql.js +23 -2
  15. package/dist/esm/audit/blueprint-pr-coverage.js +4 -0
  16. package/dist/esm/audit/ci-guardrails-wiring.d.ts +22 -0
  17. package/dist/esm/audit/ci-guardrails-wiring.js +90 -0
  18. package/dist/esm/audit/ci-test-perf.js +30 -0
  19. package/dist/esm/audit/command-surface.js +4 -2
  20. package/dist/esm/audit/host-substitution-risk.d.ts +2 -0
  21. package/dist/esm/audit/host-substitution-risk.js +256 -0
  22. package/dist/esm/audit/registry.d.ts +4 -4
  23. package/dist/esm/audit/registry.js +8 -1
  24. package/dist/esm/audit/toolchain-isolation.js +1 -2
  25. package/dist/esm/audit/typescript-version.d.ts +2 -0
  26. package/dist/esm/audit/typescript-version.js +123 -0
  27. package/dist/esm/blueprint/core/parser.js +43 -1
  28. package/dist/esm/blueprint/core/validation/criteria.d.ts +14 -0
  29. package/dist/esm/blueprint/core/validation/criteria.js +41 -2
  30. package/dist/esm/blueprint/core/validation/state.js +25 -14
  31. package/dist/esm/blueprint/db/migrations/run.js +4 -2
  32. package/dist/esm/blueprint/lifecycle/audit.d.ts +20 -0
  33. package/dist/esm/blueprint/lifecycle/audit.js +65 -10
  34. package/dist/esm/blueprint/lifecycle/canonicalize.d.ts +6 -0
  35. package/dist/esm/blueprint/lifecycle/canonicalize.js +135 -0
  36. package/dist/esm/blueprint/lifecycle/local.d.ts +2 -1
  37. package/dist/esm/blueprint/lifecycle/local.js +19 -3
  38. package/dist/esm/blueprint/lifecycle/review-provenance.js +36 -11
  39. package/dist/esm/blueprint/service/BlueprintCreationService.d.ts +1 -0
  40. package/dist/esm/blueprint/service/BlueprintCreationService.js +53 -4
  41. package/dist/esm/blueprint/service/blueprint-tech-debt-links.js +16 -2
  42. package/dist/esm/blueprint/trust/command-runner.d.ts +26 -0
  43. package/dist/esm/blueprint/trust/command-runner.js +148 -0
  44. package/dist/esm/blueprint/trust/gates.d.ts +7 -0
  45. package/dist/esm/blueprint/trust/gates.js +20 -0
  46. package/dist/esm/blueprint/trust/promotion.d.ts +8 -0
  47. package/dist/esm/blueprint/trust/promotion.js +62 -112
  48. package/dist/esm/blueprint/trust/scaffold.d.ts +19 -0
  49. package/dist/esm/blueprint/trust/scaffold.js +64 -0
  50. package/dist/esm/blueprint/trust/validator.d.ts +1 -0
  51. package/dist/esm/blueprint/trust/validator.js +7 -1
  52. package/dist/esm/blueprint/utils/archive.js +27 -5
  53. package/dist/esm/blueprint/utils/document-paths.d.ts +18 -0
  54. package/dist/esm/blueprint/utils/document-paths.js +45 -12
  55. package/dist/esm/build/cli-mcp-parity.js +10 -0
  56. package/dist/esm/cli/bundle/commands/blueprint.d.ts +1 -0
  57. package/dist/esm/cli/bundle/commands/blueprint.js +1 -0
  58. package/dist/esm/cli/cli.d.ts +1 -1
  59. package/dist/esm/cli/cli.js +34 -0
  60. package/dist/esm/cli/commands/agent-launch.d.ts +6 -1
  61. package/dist/esm/cli/commands/agent-launch.js +82 -4
  62. package/dist/esm/cli/commands/audit-core.d.ts +1 -1
  63. package/dist/esm/cli/commands/audit-core.js +8 -1
  64. package/dist/esm/cli/commands/audit.js +17 -5
  65. package/dist/esm/cli/commands/blueprint/execution.js +18 -6
  66. package/dist/esm/cli/commands/blueprint/mutations.js +59 -40
  67. package/dist/esm/cli/commands/blueprint/router-dispatch.d.ts +2 -1
  68. package/dist/esm/cli/commands/blueprint/router-dispatch.js +20 -1
  69. package/dist/esm/cli/commands/blueprint/router-output.d.ts +21 -0
  70. package/dist/esm/cli/commands/blueprint/router-output.js +48 -17
  71. package/dist/esm/cli/commands/blueprint/router.d.ts +7 -0
  72. package/dist/esm/cli/commands/blueprint/router.js +13 -1
  73. package/dist/esm/cli/commands/ci-preflight.d.ts +13 -2
  74. package/dist/esm/cli/commands/ci-preflight.js +6 -3
  75. package/dist/esm/cli/commands/compile.js +5 -31
  76. package/dist/esm/cli/commands/dash/delivery-status.d.ts +1 -0
  77. package/dist/esm/cli/commands/dash/delivery-status.js +11 -4
  78. package/dist/esm/cli/commands/doctor.js +5 -0
  79. package/dist/esm/cli/commands/hook.d.ts +5 -0
  80. package/dist/esm/cli/commands/hook.js +15 -9
  81. package/dist/esm/cli/commands/init/config.js +2 -2
  82. package/dist/esm/cli/commands/init/convergence-apply.d.ts +24 -0
  83. package/dist/esm/cli/commands/init/convergence-apply.js +221 -0
  84. package/dist/esm/cli/commands/init/convergence-state.d.ts +13 -0
  85. package/dist/esm/cli/commands/init/convergence-state.js +54 -0
  86. package/dist/esm/cli/commands/init/convergence.d.ts +23 -0
  87. package/dist/esm/cli/commands/init/convergence.js +57 -0
  88. package/dist/esm/cli/commands/init/git-convergence.d.ts +19 -0
  89. package/dist/esm/cli/commands/init/git-convergence.js +168 -0
  90. package/dist/esm/cli/commands/init/gitignore-patcher.js +2 -0
  91. package/dist/esm/cli/commands/init/grok-privacy-smoke.d.ts +52 -0
  92. package/dist/esm/cli/commands/init/grok-privacy-smoke.js +91 -0
  93. package/dist/esm/cli/commands/init/host-native-proof.d.ts +18 -0
  94. package/dist/esm/cli/commands/init/host-native-proof.js +88 -0
  95. package/dist/esm/cli/commands/init/host-visibility.d.ts +2 -2
  96. package/dist/esm/cli/commands/init/host-visibility.js +94 -5
  97. package/dist/esm/cli/commands/init/index.d.ts +1 -0
  98. package/dist/esm/cli/commands/init/index.js +326 -173
  99. package/dist/esm/cli/commands/init/mcp-spec.d.ts +57 -0
  100. package/dist/esm/cli/commands/init/mcp-spec.js +273 -0
  101. package/dist/esm/cli/commands/init/merge.d.ts +1 -0
  102. package/dist/esm/cli/commands/init/merge.js +30 -1
  103. package/dist/esm/cli/commands/init/plugin-cache-prune.d.ts +0 -3
  104. package/dist/esm/cli/commands/init/plugin-cache-prune.js +0 -1
  105. package/dist/esm/cli/commands/init/scaffold-agents-md.d.ts +1 -1
  106. package/dist/esm/cli/commands/init/scaffold-agents-md.js +9 -3
  107. package/dist/esm/cli/commands/init/scaffold-base-kit.d.ts +11 -0
  108. package/dist/esm/cli/commands/init/scaffold-base-kit.js +56 -1
  109. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/grok.d.ts +14 -8
  110. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/grok.js +41 -24
  111. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/index.d.ts +2 -0
  112. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/index.js +51 -23
  113. package/dist/esm/cli/commands/init/scaffolders/codex-mcp/index.d.ts +12 -31
  114. package/dist/esm/cli/commands/init/scaffolders/codex-mcp/index.js +288 -202
  115. package/dist/esm/cli/commands/init/scaffolders/file-transaction.d.ts +7 -0
  116. package/dist/esm/cli/commands/init/scaffolders/file-transaction.js +58 -0
  117. package/dist/esm/cli/commands/init/scaffolders/grok-mcp/index.d.ts +38 -0
  118. package/dist/esm/cli/commands/init/scaffolders/grok-mcp/index.js +73 -0
  119. package/dist/esm/cli/commands/init/scaffolders/opencode-plugin/index.d.ts +21 -0
  120. package/dist/esm/cli/commands/init/scaffolders/opencode-plugin/index.js +559 -63
  121. package/dist/esm/cli/commands/init/untracked-collision.d.ts +14 -0
  122. package/dist/esm/cli/commands/init/untracked-collision.js +42 -0
  123. package/dist/esm/cli/commands/opencode-rotate.d.ts +49 -0
  124. package/dist/esm/cli/commands/opencode-rotate.js +135 -0
  125. package/dist/esm/cli/commands/public-readiness.d.ts +11 -0
  126. package/dist/esm/cli/commands/public-readiness.js +42 -0
  127. package/dist/esm/cli/commands/review.d.ts +35 -3
  128. package/dist/esm/cli/commands/review.js +729 -209
  129. package/dist/esm/cli/commands/run-wait.d.ts +2 -0
  130. package/dist/esm/cli/commands/run-wait.js +122 -0
  131. package/dist/esm/cli/commands/setup-help.js +1 -1
  132. package/dist/esm/cli/commands/setup-repair-help.js +1 -1
  133. package/dist/esm/cli/commands/worktree/router-dispatch.js +13 -8
  134. package/dist/esm/cli/direct-provider-launch.js +9 -5
  135. package/dist/esm/cli/optional-tool-freshness.d.ts +27 -0
  136. package/dist/esm/cli/optional-tool-freshness.js +219 -9
  137. package/dist/esm/daemon/domains/git-actions.d.ts +29 -0
  138. package/dist/esm/daemon/domains/git-actions.js +136 -0
  139. package/dist/esm/daemon/domains/run-registry-interop.d.ts +16 -0
  140. package/dist/esm/daemon/domains/run-registry-interop.js +45 -0
  141. package/dist/esm/daemon/domains/sessions-search.d.ts +11 -0
  142. package/dist/esm/daemon/domains/sessions-search.js +29 -0
  143. package/dist/esm/daemon/handlers/blueprints-handlers.d.ts +5 -0
  144. package/dist/esm/daemon/handlers/blueprints-handlers.js +36 -0
  145. package/dist/esm/daemon/handlers/deploy-handlers.d.ts +6 -0
  146. package/dist/esm/daemon/handlers/deploy-handlers.js +5 -0
  147. package/dist/esm/daemon/handlers/fleet-handlers.d.ts +15 -0
  148. package/dist/esm/daemon/handlers/fleet-handlers.js +91 -0
  149. package/dist/esm/daemon/handlers/git-handlers.d.ts +6 -0
  150. package/dist/esm/daemon/handlers/git-handlers.js +27 -0
  151. package/dist/esm/daemon/handlers/product.d.ts +7 -0
  152. package/dist/esm/daemon/handlers/product.js +10 -119
  153. package/dist/esm/daemon/handlers/sessions-handlers.d.ts +12 -0
  154. package/dist/esm/daemon/handlers/sessions-handlers.js +31 -0
  155. package/dist/esm/daemon/handlers/shared.d.ts +5 -0
  156. package/dist/esm/daemon/handlers/shared.js +16 -0
  157. package/dist/esm/daemon/methods.d.ts +8 -1
  158. package/dist/esm/daemon/methods.js +7 -0
  159. package/dist/esm/daemon/protocol/contract.d.ts +43 -0
  160. package/dist/esm/daemon/protocol/contract.js +26 -0
  161. package/dist/esm/daemon/protocol/index.d.ts +1 -1
  162. package/dist/esm/daemon/protocol/index.js +1 -1
  163. package/dist/esm/hooks/__conformance__/matrix.d.ts +6 -0
  164. package/dist/esm/hooks/__conformance__/matrix.js +137 -0
  165. package/dist/esm/hooks/conformance/batch.js +5 -0
  166. package/dist/esm/hooks/doctor.d.ts +3 -3
  167. package/dist/esm/hooks/doctor.js +30 -15
  168. package/dist/esm/hooks/permission-request/index.js +9 -3
  169. package/dist/esm/hooks/permission-request/policy.d.ts +9 -0
  170. package/dist/esm/hooks/permission-request/policy.js +13 -0
  171. package/dist/esm/hooks/pretool-guard/dev-routing.d.ts +9 -0
  172. package/dist/esm/hooks/pretool-guard/dev-routing.js +41 -5
  173. package/dist/esm/hooks/pretool-guard/logger.d.ts +7 -0
  174. package/dist/esm/hooks/pretool-guard/logger.js +16 -0
  175. package/dist/esm/hooks/pretool-guard/runner.d.ts +6 -0
  176. package/dist/esm/hooks/pretool-guard/runner.js +68 -16
  177. package/dist/esm/hooks/pretool-guard/validators/blueprint.js +30 -10
  178. package/dist/esm/hooks/pretool-guard/validators/forbidden-commands.js +54 -0
  179. package/dist/esm/hooks/pretool-guard/validators/index.d.ts +7 -0
  180. package/dist/esm/hooks/pretool-guard/validators/index.js +21 -0
  181. package/dist/esm/hooks/pretool-guard/validators/path-contract.d.ts +19 -0
  182. package/dist/esm/hooks/pretool-guard/validators/path-contract.js +25 -8
  183. package/dist/esm/hooks/shared/guard-outcome.d.ts +149 -0
  184. package/dist/esm/hooks/shared/guard-outcome.js +215 -0
  185. package/dist/esm/hooks/shared/hook-bootstrap.d.ts +26 -0
  186. package/dist/esm/hooks/shared/hook-bootstrap.js +64 -1
  187. package/dist/esm/hooks/shared/types.d.ts +8 -5
  188. package/dist/esm/hooks/shared/types.js +23 -8
  189. package/dist/esm/hooks/stop/qa-changed-files.d.ts +11 -0
  190. package/dist/esm/hooks/stop/qa-changed-files.js +74 -0
  191. package/dist/esm/mcp/blueprint/_shared/lifecycle.js +14 -1
  192. package/dist/esm/mcp/blueprint/handlers/document-mutations.js +78 -4
  193. package/dist/esm/mcp/blueprint/handlers/review-log.js +8 -1
  194. package/dist/esm/mcp/blueprint/handlers/task-advance.js +113 -54
  195. package/dist/esm/mcp/blueprint/handlers/task-verify.js +39 -19
  196. package/dist/esm/mcp/blueprint/registration.js +3 -2
  197. package/dist/esm/mcp/server.d.ts +1 -0
  198. package/dist/esm/mcp/server.js +27 -0
  199. package/dist/esm/mcp/tools/_names.d.ts +1 -1
  200. package/dist/esm/mcp/tools/_names.js +5 -0
  201. package/dist/esm/mcp/tools/_registry.js +10 -0
  202. package/dist/esm/mcp/tools/_shared/audit-kinds.d.ts +1 -1
  203. package/dist/esm/mcp/tools/_shared/result.js +44 -1
  204. package/dist/esm/mcp/tools/audit.d.ts +4 -1
  205. package/dist/esm/mcp/tools/audit.js +30 -0
  206. package/dist/esm/mcp/tools/audits.d.ts +3 -0
  207. package/dist/esm/mcp/tools/ci-preflight.d.ts +50 -0
  208. package/dist/esm/mcp/tools/ci-preflight.js +183 -0
  209. package/dist/esm/mcp/tools/pr-upsert.js +39 -1
  210. package/dist/esm/mcp/tools/review-run.d.ts +28 -0
  211. package/dist/esm/mcp/tools/review-run.js +216 -0
  212. package/dist/esm/mcp/tools/run-wait.d.ts +86 -0
  213. package/dist/esm/mcp/tools/run-wait.js +593 -0
  214. package/dist/esm/mcp/tools/session-id.d.ts +3 -0
  215. package/dist/esm/mcp/tools/session-id.js +45 -0
  216. package/dist/esm/mcp/tools/session-info.d.ts +3 -0
  217. package/dist/esm/mcp/tools/session-info.js +49 -0
  218. package/dist/esm/output-transforms/audit.d.ts +23 -0
  219. package/dist/esm/output-transforms/audit.js +47 -0
  220. package/dist/esm/output-transforms/index.js +2 -0
  221. package/dist/esm/review/authority.js +13 -5
  222. package/dist/esm/review/availability.d.ts +22 -0
  223. package/dist/esm/review/availability.js +107 -20
  224. package/dist/esm/review/delivery-verifier.d.ts +27 -0
  225. package/dist/esm/review/delivery-verifier.js +115 -0
  226. package/dist/esm/review/events.d.ts +3 -2
  227. package/dist/esm/review/events.js +23 -3
  228. package/dist/esm/review/execution/adapters.js +26 -9
  229. package/dist/esm/review/execution/output-policy.d.ts +2 -0
  230. package/dist/esm/review/execution/output-policy.js +12 -0
  231. package/dist/esm/review/execution/review-checkout.js +87 -6
  232. package/dist/esm/review/execution/supervisor.js +5 -0
  233. package/dist/esm/review/execution/types.d.ts +8 -0
  234. package/dist/esm/review/opencode-account.d.ts +24 -0
  235. package/dist/esm/review/opencode-account.js +68 -0
  236. package/dist/esm/review/opencode-auth.d.ts +33 -0
  237. package/dist/esm/review/opencode-auth.js +79 -0
  238. package/dist/esm/review/subject.d.ts +12 -0
  239. package/dist/esm/review/subject.js +74 -22
  240. package/dist/esm/runtime/opencode-account-materializer.d.ts +34 -0
  241. package/dist/esm/runtime/opencode-account-materializer.js +33 -0
  242. package/dist/esm/status/snapshot.js +30 -19
  243. package/dist/esm/test/duration-sequencer.d.ts +20 -0
  244. package/dist/esm/test/duration-sequencer.js +54 -0
  245. package/dist/esm/test/shard-durations.json +922 -0
  246. package/dist/esm/test/worker-budget.d.ts +6 -0
  247. package/dist/esm/test/worker-budget.js +59 -1
  248. package/dist/esm/test-helpers/global-setup.d.ts +1 -1
  249. package/dist/esm/test-helpers/global-setup.js +68 -24
  250. package/dist/esm/ultragoal/service.d.ts +7 -0
  251. package/dist/esm/ultragoal/service.js +42 -2
  252. package/dist/esm/utils/write-json-file.js +3 -1
  253. package/dist/esm/worktrees/codex-project-trust.d.ts +15 -0
  254. package/dist/esm/worktrees/codex-project-trust.js +56 -0
  255. package/dist/esm/worktrees/registry.d.ts +8 -0
  256. package/dist/esm/worktrees/registry.js +18 -3
  257. package/package.json +16 -13
@@ -0,0 +1,57 @@
1
+ import { isAbsolute, relative, resolve, sep } from "node:path";
2
+ export const CONVERGE_SCOPES = ["repo-committed", "repo-ignored"];
3
+ function normalizeGitPath(value) {
4
+ return value.replaceAll("\\", "/").replace(/^\.\//u, "");
5
+ }
6
+ function assertInsideRepo(repoRoot, targetPath) {
7
+ const relativePath = relative(repoRoot, targetPath);
8
+ if (relativePath.length === 0 ||
9
+ relativePath === ".." ||
10
+ relativePath.startsWith(`..${sep}`) ||
11
+ isAbsolute(relativePath)) {
12
+ throw new Error(`Convergence target must be a file inside the repository: ${targetPath}`);
13
+ }
14
+ return normalizeGitPath(relativePath);
15
+ }
16
+ export function createConvergeUnit(input) {
17
+ if (!isAbsolute(input.repoRoot)) {
18
+ throw new Error(`Convergence repo root must be absolute: ${input.repoRoot}`);
19
+ }
20
+ if (!isAbsolute(input.targetPath)) {
21
+ throw new Error(`Convergence target must be absolute: ${input.targetPath}`);
22
+ }
23
+ if (!CONVERGE_SCOPES.includes(input.scope)) {
24
+ throw new Error(`Unsupported convergence scope: ${input.scope}`);
25
+ }
26
+ const repoRoot = resolve(input.repoRoot);
27
+ const targetPath = resolve(input.targetPath);
28
+ const derivedGitPath = assertInsideRepo(repoRoot, targetPath);
29
+ const gitPath = normalizeGitPath(input.gitPath);
30
+ if (gitPath.length === 0 || isAbsolute(gitPath) || gitPath !== derivedGitPath) {
31
+ throw new Error(`Convergence git path must match its repo-anchored target: expected ${derivedGitPath}, received ${input.gitPath}`);
32
+ }
33
+ return {
34
+ repoRoot,
35
+ targetPath,
36
+ gitPath,
37
+ action: input.action,
38
+ scope: input.scope,
39
+ reason: input.reason,
40
+ };
41
+ }
42
+ export function convergeUnitFromTarget(repoRoot, targetPath, input) {
43
+ const anchoredRoot = resolve(repoRoot);
44
+ const anchoredTarget = resolve(targetPath);
45
+ return createConvergeUnit({
46
+ ...input,
47
+ repoRoot: anchoredRoot,
48
+ targetPath: anchoredTarget,
49
+ gitPath: assertInsideRepo(anchoredRoot, anchoredTarget),
50
+ });
51
+ }
52
+ /** Applied units are the sole authority for authored commit scope. */
53
+ export function deriveCommitAllowlist(appliedUnits) {
54
+ return [
55
+ ...new Set(appliedUnits.filter((unit) => unit.scope === "repo-committed").map((unit) => unit.gitPath)),
56
+ ].sort();
57
+ }
@@ -0,0 +1,19 @@
1
+ export type GitConvergenceStatus = "ready" | "fast-forwarded" | "not-git" | "unborn" | "detached" | "dirty" | "diverged" | "failed";
2
+ export interface GitConvergenceResult {
3
+ readonly status: GitConvergenceStatus;
4
+ readonly ok: boolean;
5
+ readonly repoRoot: string;
6
+ readonly head?: string;
7
+ readonly upstream?: string;
8
+ readonly shouldReplan: boolean;
9
+ readonly canCommit: boolean;
10
+ readonly warnings: readonly string[];
11
+ readonly error?: string;
12
+ }
13
+ export interface PrepareGitConvergenceOptions {
14
+ readonly repoRoot: string;
15
+ readonly isCi?: boolean;
16
+ readonly fetchTimeoutMs?: number;
17
+ readonly gitCommand?: string;
18
+ }
19
+ export declare function prepareRepositoryForConvergence(options: PrepareGitConvergenceOptions): GitConvergenceResult;
@@ -0,0 +1,168 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { resolve } from "node:path";
3
+ const DEFAULT_GIT_TIMEOUT_MS = 5_000;
4
+ const GIT_MAX_BUFFER = 1024 * 1024;
5
+ function git(repoRoot, args, timeoutMs, command = "git") {
6
+ const result = spawnSync(command, [...args], {
7
+ cwd: repoRoot,
8
+ encoding: "utf8",
9
+ timeout: timeoutMs,
10
+ maxBuffer: GIT_MAX_BUFFER,
11
+ stdio: ["ignore", "pipe", "pipe"],
12
+ });
13
+ return {
14
+ ok: result.status === 0 && !result.error,
15
+ stdout: result.stdout.trim(),
16
+ stderr: result.stderr.trim(),
17
+ timedOut: result.error !== undefined && "code" in result.error && result.error.code === "ETIMEDOUT",
18
+ };
19
+ }
20
+ function failed(repoRoot, status, error) {
21
+ return {
22
+ status,
23
+ ok: false,
24
+ repoRoot,
25
+ shouldReplan: false,
26
+ canCommit: false,
27
+ warnings: [],
28
+ error,
29
+ };
30
+ }
31
+ function parseAheadBehindCounts(stdout) {
32
+ const parts = stdout.trim().split(/\s+/u);
33
+ if (parts.length !== 2)
34
+ return null;
35
+ if (!parts.every((part) => /^\d+$/u.test(part)))
36
+ return null;
37
+ const [ahead, behind] = parts.map((part) => Number.parseInt(part, 10));
38
+ if (ahead === undefined ||
39
+ behind === undefined ||
40
+ !Number.isSafeInteger(ahead) ||
41
+ !Number.isSafeInteger(behind) ||
42
+ ahead < 0 ||
43
+ behind < 0) {
44
+ return null;
45
+ }
46
+ return { ahead, behind };
47
+ }
48
+ export function prepareRepositoryForConvergence(options) {
49
+ const repoRoot = resolve(options.repoRoot);
50
+ const timeoutMs = options.fetchTimeoutMs ?? DEFAULT_GIT_TIMEOUT_MS;
51
+ const gitCommand = options.gitCommand ?? "git";
52
+ const runGit = (args) => git(repoRoot, args, timeoutMs, gitCommand);
53
+ const inside = runGit(["rev-parse", "--is-inside-work-tree"]);
54
+ if (!inside.ok || inside.stdout !== "true") {
55
+ return failed(repoRoot, "not-git", "Repository convergence requires a Git worktree.");
56
+ }
57
+ const headResult = runGit(["rev-parse", "--verify", "HEAD"]);
58
+ if (!headResult.ok) {
59
+ return failed(repoRoot, "unborn", "Repository convergence requires an existing HEAD commit.");
60
+ }
61
+ const head = headResult.stdout;
62
+ const branch = runGit(["symbolic-ref", "--quiet", "--short", "HEAD"]);
63
+ const detached = !branch.ok;
64
+ if (detached && !options.isCi) {
65
+ return failed(repoRoot, "detached", "Repository convergence refuses a detached HEAD.");
66
+ }
67
+ const trackedStatus = runGit(["status", "--porcelain=v1", "--untracked-files=no"]);
68
+ if (!trackedStatus.ok) {
69
+ return failed(repoRoot, "failed", trackedStatus.stderr || "Unable to inspect Git status.");
70
+ }
71
+ if (trackedStatus.stdout.length > 0) {
72
+ return failed(repoRoot, "dirty", "Repository convergence requires a clean tracked index and worktree.");
73
+ }
74
+ const warnings = [];
75
+ if (detached) {
76
+ warnings.push("Detached HEAD accepted in CI; skipped upstream update and authored commit.");
77
+ return {
78
+ status: "ready",
79
+ ok: true,
80
+ repoRoot,
81
+ head,
82
+ shouldReplan: false,
83
+ canCommit: false,
84
+ warnings,
85
+ };
86
+ }
87
+ const upstreamResult = runGit(["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"]);
88
+ if (!upstreamResult.ok) {
89
+ warnings.push("No upstream is configured; skipped fetch and fast-forward.");
90
+ return {
91
+ status: "ready",
92
+ ok: true,
93
+ repoRoot,
94
+ head,
95
+ shouldReplan: false,
96
+ canCommit: !options.isCi,
97
+ warnings,
98
+ };
99
+ }
100
+ const upstream = upstreamResult.stdout;
101
+ const remoteSeparator = upstream.indexOf("/");
102
+ const remote = remoteSeparator === -1 ? upstream : upstream.slice(0, remoteSeparator);
103
+ const fetch = runGit(["fetch", "--quiet", "--no-tags", remote]);
104
+ if (!fetch.ok) {
105
+ warnings.push(fetch.timedOut
106
+ ? `Upstream fetch timed out after ${timeoutMs}ms; continuing from local refs.`
107
+ : `Upstream fetch unavailable; continuing from local refs${fetch.stderr ? `: ${fetch.stderr}` : "."}`);
108
+ }
109
+ const counts = runGit(["rev-list", "--left-right", "--count", `HEAD...${upstream}`]);
110
+ if (!counts.ok) {
111
+ return {
112
+ ...failed(repoRoot, "failed", counts.stderr || "Unable to compare HEAD with upstream."),
113
+ head,
114
+ upstream,
115
+ warnings,
116
+ };
117
+ }
118
+ const parsedCounts = parseAheadBehindCounts(counts.stdout);
119
+ if (!parsedCounts) {
120
+ return {
121
+ ...failed(repoRoot, "failed", `Unable to parse HEAD/upstream divergence counts from git rev-list output: ${JSON.stringify(counts.stdout)}.`),
122
+ head,
123
+ upstream,
124
+ warnings,
125
+ };
126
+ }
127
+ const { ahead, behind } = parsedCounts;
128
+ if (ahead > 0 && behind > 0) {
129
+ return {
130
+ ...failed(repoRoot, "diverged", `HEAD has diverged from ${upstream}; reconcile it manually.`),
131
+ head,
132
+ upstream,
133
+ warnings,
134
+ };
135
+ }
136
+ if (behind > 0) {
137
+ const merge = runGit(["merge", "--ff-only", upstream]);
138
+ if (!merge.ok) {
139
+ return {
140
+ ...failed(repoRoot, "failed", merge.stderr || `Unable to fast-forward from ${upstream}.`),
141
+ head,
142
+ upstream,
143
+ warnings,
144
+ };
145
+ }
146
+ const nextHead = runGit(["rev-parse", "--verify", "HEAD"]);
147
+ return {
148
+ status: "fast-forwarded",
149
+ ok: true,
150
+ repoRoot,
151
+ head: nextHead.ok ? nextHead.stdout : undefined,
152
+ upstream,
153
+ shouldReplan: true,
154
+ canCommit: !options.isCi,
155
+ warnings,
156
+ };
157
+ }
158
+ return {
159
+ status: "ready",
160
+ ok: true,
161
+ repoRoot,
162
+ head,
163
+ upstream,
164
+ shouldReplan: false,
165
+ canCommit: !options.isCi,
166
+ warnings,
167
+ };
168
+ }
@@ -55,8 +55,10 @@ export const GENERATED_PATHS_BLOCK = {
55
55
  ".runtime/",
56
56
  ".opencode/",
57
57
  ".codex/",
58
+ ".grok/",
58
59
  "_worktrees/",
59
60
  ".webpresso/hooks-manifest.json",
61
+ ".webpresso/converged.json",
60
62
  ".claude/settings.json",
61
63
  ".claude/settings.local.json",
62
64
  ".claude/agents/",
@@ -0,0 +1,52 @@
1
+ export interface GrokPrivacyFlow {
2
+ readonly hostname: string;
3
+ readonly method: string;
4
+ readonly requestCount: number;
5
+ readonly requestBytes: number;
6
+ readonly responseBytes: number;
7
+ }
8
+ export interface GrokPrivacyBaseline {
9
+ readonly schemaVersion: 1;
10
+ readonly cliVersion: string;
11
+ readonly authMode: "local-session";
12
+ readonly transportVarianceBytes: number;
13
+ readonly maxAggregateRequestBytes: number;
14
+ readonly flows: readonly {
15
+ readonly hostname: string;
16
+ readonly method: string;
17
+ readonly maxRequestCount: number;
18
+ readonly maxRequestBytes: number;
19
+ }[];
20
+ }
21
+ export interface GrokPrivacyEvidence {
22
+ readonly schemaVersion: 1;
23
+ readonly host: "grok";
24
+ readonly cliVersion: string;
25
+ readonly authMode: "local-session";
26
+ readonly reviewedSha: string;
27
+ readonly traceSha256: string;
28
+ readonly sentinelObserved: false;
29
+ readonly native: {
30
+ readonly hooksTrusted: true;
31
+ readonly hookDenial: true;
32
+ readonly inspect: true;
33
+ readonly mcpList: true;
34
+ readonly mcpDoctor: true;
35
+ readonly localInference: true;
36
+ };
37
+ readonly flows: readonly GrokPrivacyFlow[];
38
+ }
39
+ export declare function buildGrokPrivacyEvidence(input: {
40
+ baseline: GrokPrivacyBaseline;
41
+ cliVersion: string;
42
+ reviewedSha: string;
43
+ sentinelObserved: boolean;
44
+ hooksTrusted: boolean;
45
+ hookDenialPassed: boolean;
46
+ inspectPassed: boolean;
47
+ mcpListPassed: boolean;
48
+ mcpDoctorPassed: boolean;
49
+ localInferencePassed: boolean;
50
+ flows: readonly GrokPrivacyFlow[];
51
+ }): GrokPrivacyEvidence;
52
+ export declare function serializeGrokPrivacyEvidence(evidence: GrokPrivacyEvidence): string;
@@ -0,0 +1,91 @@
1
+ import { createHash } from "node:crypto";
2
+ const EVIDENCE_KEYS = [
3
+ "schemaVersion",
4
+ "host",
5
+ "cliVersion",
6
+ "authMode",
7
+ "reviewedSha",
8
+ "traceSha256",
9
+ "sentinelObserved",
10
+ "native",
11
+ "flows",
12
+ ];
13
+ function normalizedFlows(flows) {
14
+ return [...flows]
15
+ .map((flow) => ({
16
+ hostname: flow.hostname.toLowerCase(),
17
+ method: flow.method.toUpperCase(),
18
+ requestCount: flow.requestCount,
19
+ requestBytes: flow.requestBytes,
20
+ responseBytes: flow.responseBytes,
21
+ }))
22
+ .sort((a, b) => `${a.hostname}\0${a.method}`.localeCompare(`${b.hostname}\0${b.method}`));
23
+ }
24
+ export function buildGrokPrivacyEvidence(input) {
25
+ const { baseline } = input;
26
+ if (input.cliVersion !== baseline.cliVersion) {
27
+ throw new Error(`Grok privacy proof requires pinned CLI ${baseline.cliVersion}; observed ${input.cliVersion}`);
28
+ }
29
+ if (!/^[a-f0-9]{40}$/u.test(input.reviewedSha)) {
30
+ throw new Error("Grok privacy proof requires a full reviewed git SHA");
31
+ }
32
+ if (input.sentinelObserved) {
33
+ throw new Error("Grok privacy proof detected the fixture sentinel in an outbound request");
34
+ }
35
+ if (!input.hooksTrusted ||
36
+ !input.hookDenialPassed ||
37
+ !input.inspectPassed ||
38
+ !input.mcpListPassed ||
39
+ !input.mcpDoctorPassed ||
40
+ !input.localInferencePassed) {
41
+ throw new Error("Grok privacy proof requires trusted hooks and passing native discovery");
42
+ }
43
+ const flows = normalizedFlows(input.flows);
44
+ const allowed = new Map(baseline.flows.map((flow) => [
45
+ `${flow.hostname.toLowerCase()}\0${flow.method.toUpperCase()}`,
46
+ flow,
47
+ ]));
48
+ for (const flow of flows) {
49
+ const expected = allowed.get(`${flow.hostname}\0${flow.method}`);
50
+ if (!expected) {
51
+ throw new Error(`Grok privacy proof observed unapproved flow ${flow.method} ${flow.hostname}`);
52
+ }
53
+ if (flow.requestCount > expected.maxRequestCount) {
54
+ throw new Error(`Grok privacy proof exceeded request count for ${flow.hostname}`);
55
+ }
56
+ if (flow.requestBytes > expected.maxRequestBytes + baseline.transportVarianceBytes) {
57
+ throw new Error(`Grok privacy proof exceeded request bytes for ${flow.hostname}`);
58
+ }
59
+ }
60
+ const aggregateRequestBytes = flows.reduce((total, flow) => total + flow.requestBytes, 0);
61
+ if (aggregateRequestBytes > baseline.maxAggregateRequestBytes + baseline.transportVarianceBytes) {
62
+ throw new Error("Grok privacy proof exceeded aggregate request bytes");
63
+ }
64
+ const trace = JSON.stringify(flows);
65
+ return {
66
+ schemaVersion: 1,
67
+ host: "grok",
68
+ cliVersion: input.cliVersion,
69
+ authMode: "local-session",
70
+ reviewedSha: input.reviewedSha,
71
+ traceSha256: createHash("sha256").update(trace).digest("hex"),
72
+ sentinelObserved: false,
73
+ native: {
74
+ hooksTrusted: true,
75
+ hookDenial: true,
76
+ inspect: true,
77
+ mcpList: true,
78
+ mcpDoctor: true,
79
+ localInference: true,
80
+ },
81
+ flows,
82
+ };
83
+ }
84
+ export function serializeGrokPrivacyEvidence(evidence) {
85
+ const keys = Object.keys(evidence);
86
+ if (keys.length !== EVIDENCE_KEYS.length ||
87
+ keys.some((key) => !EVIDENCE_KEYS.includes(key))) {
88
+ throw new Error("Grok privacy evidence contains an unknown field");
89
+ }
90
+ return `${JSON.stringify(evidence, null, 2)}\n`;
91
+ }
@@ -0,0 +1,18 @@
1
+ export declare const CLAUDE_NATIVE_PROOF_TOOL = "mcp__plugin_agent-kit_webpresso__wp_session_stats";
2
+ type JsonRecord = Record<string, unknown>;
3
+ export interface ClaudeNativeProofRecord {
4
+ readonly host: "claude";
5
+ readonly cliVersion: string;
6
+ readonly toolName: typeof CLAUDE_NATIVE_PROOF_TOOL;
7
+ readonly emptyArguments: true;
8
+ readonly success: true;
9
+ readonly elapsedMs: number;
10
+ readonly terminalEventSha256: string;
11
+ }
12
+ export declare function parseJsonLines(raw: string): JsonRecord[];
13
+ export declare function verifyClaudeNativeProof(events: readonly JsonRecord[], input: {
14
+ cliVersion: string;
15
+ elapsedMs: number;
16
+ }): ClaudeNativeProofRecord;
17
+ export declare function serializeClaudeNativeProof(record: ClaudeNativeProofRecord): string;
18
+ export {};
@@ -0,0 +1,88 @@
1
+ import { createHash } from "node:crypto";
2
+ export const CLAUDE_NATIVE_PROOF_TOOL = "mcp__plugin_agent-kit_webpresso__wp_session_stats";
3
+ function isRecord(value) {
4
+ return typeof value === "object" && value !== null && !Array.isArray(value);
5
+ }
6
+ export function parseJsonLines(raw) {
7
+ return raw
8
+ .split(/\r?\n/u)
9
+ .filter((line) => line.trim() !== "")
10
+ .map((line) => {
11
+ const parsed = JSON.parse(line);
12
+ if (!isRecord(parsed))
13
+ throw new Error("Claude stream event must be a JSON object");
14
+ return parsed;
15
+ });
16
+ }
17
+ export function verifyClaudeNativeProof(events, input) {
18
+ const init = events.find((event) => event["type"] === "system" && event["subtype"] === "init");
19
+ if (!init)
20
+ throw new Error("Claude native proof missing system/init");
21
+ const pluginErrors = init["plugin_errors"];
22
+ if (Array.isArray(pluginErrors) && pluginErrors.length > 0) {
23
+ throw new Error("Claude native proof reported plugin load errors");
24
+ }
25
+ const plugins = Array.isArray(init["plugins"]) ? init["plugins"] : [];
26
+ const pluginNames = plugins
27
+ .map((plugin) => (isRecord(plugin) ? plugin["name"] : undefined))
28
+ .filter((name) => typeof name === "string");
29
+ if (pluginNames.length !== 1 || pluginNames[0] !== "agent-kit") {
30
+ throw new Error(`Claude native proof expected only agent-kit plugin; observed ${JSON.stringify(pluginNames)}`);
31
+ }
32
+ const tools = Array.isArray(init["tools"])
33
+ ? init["tools"].filter((tool) => typeof tool === "string")
34
+ : [];
35
+ if (tools.length !== 1 || tools[0] !== CLAUDE_NATIVE_PROOF_TOOL) {
36
+ throw new Error(`Claude native proof expected exactly ${CLAUDE_NATIVE_PROOF_TOOL}; observed tools=${JSON.stringify(tools)} mcp_servers=${JSON.stringify(init["mcp_servers"] ?? [])}`);
37
+ }
38
+ const mcpServers = Array.isArray(init["mcp_servers"]) ? init["mcp_servers"] : [];
39
+ const expectedServers = mcpServers.filter((server) => isRecord(server) &&
40
+ server["name"] === "plugin:agent-kit:webpresso" &&
41
+ server["status"] === "connected");
42
+ if (expectedServers.length !== 1) {
43
+ throw new Error(`Claude native proof expected one connected Agent Kit MCP server; observed ${JSON.stringify(mcpServers)}`);
44
+ }
45
+ const toolUses = events.flatMap((event) => {
46
+ const message = isRecord(event["message"]) ? event["message"] : null;
47
+ const content = message && Array.isArray(message["content"]) ? message["content"] : [];
48
+ return content.filter((block) => isRecord(block) && block["type"] === "tool_use");
49
+ });
50
+ if (toolUses.length !== 1) {
51
+ throw new Error(`Claude native proof expected exactly one tool use; observed ${toolUses.length}`);
52
+ }
53
+ const toolUse = toolUses[0];
54
+ if (toolUse["name"] !== CLAUDE_NATIVE_PROOF_TOOL) {
55
+ throw new Error(`Claude native proof observed unexpected tool: ${String(toolUse["name"])}`);
56
+ }
57
+ if (!isRecord(toolUse["input"]) || Object.keys(toolUse["input"]).length !== 0) {
58
+ throw new Error("Claude native proof tool arguments must be an empty object");
59
+ }
60
+ const terminal = events.findLast((event) => event["type"] === "result");
61
+ if (!terminal || terminal["subtype"] !== "success" || terminal["is_error"] === true) {
62
+ throw new Error("Claude native proof missing successful terminal result");
63
+ }
64
+ return {
65
+ host: "claude",
66
+ cliVersion: input.cliVersion,
67
+ toolName: CLAUDE_NATIVE_PROOF_TOOL,
68
+ emptyArguments: true,
69
+ success: true,
70
+ elapsedMs: Math.max(0, Math.min(Math.round(input.elapsedMs), 300_000)),
71
+ terminalEventSha256: createHash("sha256").update(JSON.stringify(terminal)).digest("hex"),
72
+ };
73
+ }
74
+ export function serializeClaudeNativeProof(record) {
75
+ const allowedKeys = [
76
+ "host",
77
+ "cliVersion",
78
+ "toolName",
79
+ "emptyArguments",
80
+ "success",
81
+ "elapsedMs",
82
+ "terminalEventSha256",
83
+ ];
84
+ if (Object.keys(record).some((key) => !allowedKeys.includes(key))) {
85
+ throw new Error("Claude native proof record contains an unknown field");
86
+ }
87
+ return `${JSON.stringify(record, null, 2)}\n`;
88
+ }
@@ -1,4 +1,4 @@
1
- export declare const AGENT_HOSTS: readonly ["codex", "claude", "opencode"];
1
+ export declare const AGENT_HOSTS: readonly ["codex", "claude", "opencode", "grok"];
2
2
  export type AgentHost = (typeof AGENT_HOSTS)[number];
3
3
  export declare const REQUIRED_CORE_CAPABILITIES: readonly ["verify", "fix", "investigate", "ai-deslop", "plan-refine", "ralplan", "best-practice-research", "testing-philosophy", "tph", "claude", "codex", "grok", "opencode-go", "plan-eng-review", "plan-ceo-review", "plan-design-review", "plan-devex-review", "browse", "devex-review", "design-review", "hooks-doctor", "tech-debt", "lore-protocol", "deep-interview", "deep-research", "autoresearch", "ultragoal", "autopilot", "team"];
4
4
  export declare const VISIBILITY_STATUSES: readonly ["visible-now", "visible-after-restart", "not-visible"];
@@ -21,7 +21,7 @@ export interface HostVisibilityAudit {
21
21
  readonly requiredCapabilities: readonly string[];
22
22
  readonly results: readonly HostSkillVisibility[];
23
23
  }
24
- export declare const SETUP_SURFACE_HOSTS: readonly ["claude", "codex", "opencode"];
24
+ export declare const SETUP_SURFACE_HOSTS: readonly ["claude", "codex", "opencode", "grok"];
25
25
  export type SetupSurfaceHost = (typeof SETUP_SURFACE_HOSTS)[number];
26
26
  export type SetupSurfaceArtifactStatus = "installed" | "missing" | "deferred";
27
27
  export type SetupSurfaceActiveStatus = "managed" | "not-installed";
@@ -6,10 +6,10 @@ import { SHARED_FAVORITE_SKILLS } from "./scaffold-agent.js";
6
6
  import { CLAUDE_DEV_ADAPTER_RELATIVE_PATH } from "./scaffolders/claude-plugin/index.js";
7
7
  import { CODEX_DEV_ADAPTER_RELATIVE_PATH } from "./scaffolders/codex-plugin/index.js";
8
8
  import { OPENCODE_PLUGIN_PACKAGE } from "./scaffolders/opencode-plugin/index.js";
9
- export const AGENT_HOSTS = ["codex", "claude", "opencode"];
9
+ export const AGENT_HOSTS = ["codex", "claude", "opencode", "grok"];
10
10
  export const REQUIRED_CORE_CAPABILITIES = SHARED_FAVORITE_SKILLS;
11
11
  export const VISIBILITY_STATUSES = ["visible-now", "visible-after-restart", "not-visible"];
12
- export const SETUP_SURFACE_HOSTS = ["claude", "codex", "opencode"];
12
+ export const SETUP_SURFACE_HOSTS = ["claude", "codex", "opencode", "grok"];
13
13
  export function parseAgentHosts(value) {
14
14
  if (value?.trim() === "none")
15
15
  return [];
@@ -103,6 +103,18 @@ export function hostSkillRoots(repoRoot, host, homeDir = homedir()) {
103
103
  ],
104
104
  global: [],
105
105
  };
106
+ case "grok":
107
+ // Grok reads AGENTS.md/CLAUDE.md natively for instructions; skills are
108
+ // shared from the Claude/agents surfaces plus a native `.grok/skills`.
109
+ return {
110
+ project: [
111
+ join(repoRoot, ".grok", "skills"),
112
+ join(repoRoot, ".claude", "skills"),
113
+ join(repoRoot, ".agents", "skills"),
114
+ ],
115
+ user: [join(homeDir, ".grok", "skills"), join(homeDir, ".claude", "skills")],
116
+ global: [],
117
+ };
106
118
  }
107
119
  }
108
120
  export function auditHostSkillVisibility(input) {
@@ -164,11 +176,13 @@ function allExist(repoRoot, relativePaths) {
164
176
  return relativePaths.every((relativePath) => existsSync(join(repoRoot, relativePath)));
165
177
  }
166
178
  function hasOpenCodePluginRegistration(repoRoot) {
167
- const configPath = join(repoRoot, "opencode.json");
179
+ const configPath = existsSync(join(repoRoot, "opencode.json"))
180
+ ? join(repoRoot, "opencode.json")
181
+ : join(repoRoot, "opencode.jsonc");
168
182
  if (!existsSync(configPath))
169
183
  return false;
170
184
  try {
171
- const parsed = JSON.parse(readFileSync(configPath, "utf8"));
185
+ const parsed = JSON.parse(stripJsonc(readFileSync(configPath, "utf8")));
172
186
  return (Array.isArray(parsed.plugin) &&
173
187
  parsed.plugin.some((entry) => entry === OPENCODE_PLUGIN_PACKAGE));
174
188
  }
@@ -176,6 +190,71 @@ function hasOpenCodePluginRegistration(repoRoot) {
176
190
  return false;
177
191
  }
178
192
  }
193
+ function stripJsonc(raw) {
194
+ let out = "";
195
+ let inString = false;
196
+ let quote = null;
197
+ let escaped = false;
198
+ for (let i = 0; i < raw.length; i += 1) {
199
+ const ch = raw[i];
200
+ const next = raw[i + 1];
201
+ if (inString) {
202
+ out += ch;
203
+ if (escaped)
204
+ escaped = false;
205
+ else if (ch === "\\")
206
+ escaped = true;
207
+ else if (ch === quote) {
208
+ inString = false;
209
+ quote = null;
210
+ }
211
+ continue;
212
+ }
213
+ if (ch === '"' || ch === "'") {
214
+ inString = true;
215
+ quote = ch;
216
+ out += ch;
217
+ continue;
218
+ }
219
+ if (ch === "/" && next === "/") {
220
+ while (i < raw.length && raw[i] !== "\n")
221
+ i += 1;
222
+ out += "\n";
223
+ continue;
224
+ }
225
+ if (ch === "/" && next === "*") {
226
+ i += 2;
227
+ while (i < raw.length && !(raw[i] === "*" && raw[i + 1] === "/"))
228
+ i += 1;
229
+ i += 1;
230
+ continue;
231
+ }
232
+ if (ch === ",") {
233
+ let j = i + 1;
234
+ while (j < raw.length) {
235
+ while (/\s/u.test(raw[j] ?? ""))
236
+ j += 1;
237
+ if (raw[j] === "/" && raw[j + 1] === "/") {
238
+ while (j < raw.length && raw[j] !== "\n")
239
+ j += 1;
240
+ continue;
241
+ }
242
+ if (raw[j] === "/" && raw[j + 1] === "*") {
243
+ j += 2;
244
+ while (j < raw.length && !(raw[j] === "*" && raw[j + 1] === "/"))
245
+ j += 1;
246
+ j += 2;
247
+ continue;
248
+ }
249
+ break;
250
+ }
251
+ if (raw[j] === "}" || raw[j] === "]")
252
+ continue;
253
+ }
254
+ out += ch;
255
+ }
256
+ return out;
257
+ }
179
258
  export function auditHostSetupSurfaceVisibility(input) {
180
259
  const { repoRoot, packageRoot } = input;
181
260
  const opencodePluginRegistered = hasOpenCodePluginRegistration(repoRoot);
@@ -210,7 +289,17 @@ export function auditHostSetupSurfaceVisibility(input) {
210
289
  active: opencodePluginRegistered ? "managed" : "not-installed",
211
290
  support: "full",
212
291
  required: false,
213
- ownership: "native npm plugin registration via the opencode.json plugin entry @webpresso/opencode-plugin",
292
+ ownership: "native npm plugin registration via the opencode.json/opencode.jsonc plugin entry @webpresso/opencode-plugin",
293
+ },
294
+ {
295
+ host: "grok",
296
+ artifact: existsSync(join(repoRoot, ".grok", "config.toml")) ? "installed" : "deferred",
297
+ active: existsSync(join(repoRoot, ".grok", "hooks", "webpresso.json"))
298
+ ? "managed"
299
+ : "not-installed",
300
+ support: "full",
301
+ required: false,
302
+ ownership: "native project .grok/config.toml MCP server plus .grok/hooks/webpresso.json; run /hooks-trust once to arm the hooks",
214
303
  },
215
304
  ];
216
305
  }
@@ -30,6 +30,7 @@ export interface InitFlags {
30
30
  repair?: boolean;
31
31
  profile?: string;
32
32
  }
33
+ export declare function setupDeprecationWarnings(flags: InitFlags): string[];
33
34
  /**
34
35
  * Which tier surfaces a given adoption-ladder profile scaffolds. Strict
35
36
  * supersets (see docs/adoption-ladder.md): quality ⊂ guarded ⊂ full.