qlogicagent 2.17.9 → 2.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/agent.js +21 -21
  2. package/dist/cli.js +1 -1566
  3. package/dist/index.js +445 -421
  4. package/dist/orchestration.js +7 -7
  5. package/dist/protocol.js +1 -1
  6. package/dist/skills/builtin/desktop-screenshot/SKILL.md +62 -0
  7. package/dist/skills/builtin/office-doc-reading/SKILL.md +19 -0
  8. package/dist/skills/mcp/astraclaw-native-mcp-server.js +7 -6
  9. package/dist/types/agent/tool-loop/artifact-final-contract.d.ts +18 -0
  10. package/dist/types/agent/tool-loop/loop-helpers.d.ts +9 -0
  11. package/dist/types/agent/tool-loop.d.ts +14 -5
  12. package/dist/types/agent/types.d.ts +5 -0
  13. package/dist/types/cli/acp-session-handlers.d.ts +8 -1
  14. package/dist/types/cli/acp-session-host.d.ts +5 -1
  15. package/dist/types/cli/default-project-bootstrap.d.ts +33 -0
  16. package/dist/types/cli/handlers/agents-handler.d.ts +9 -0
  17. package/dist/types/cli/handlers/config-handler.d.ts +5 -0
  18. package/dist/types/cli/handlers/files-handler.d.ts +7 -0
  19. package/dist/types/cli/handlers/session-handler.d.ts +49 -0
  20. package/dist/types/cli/handlers/turn-handler.d.ts +77 -0
  21. package/dist/types/cli/media-understanding.d.ts +45 -0
  22. package/dist/types/cli/permission-rule-persistence.d.ts +16 -0
  23. package/dist/types/cli/session-context.d.ts +5 -1
  24. package/dist/types/cli/stdio-acp-request-host.d.ts +1 -1
  25. package/dist/types/cli/stdio-rpc-handler-hosts.d.ts +4 -0
  26. package/dist/types/cli/stdio-server.d.ts +17 -1
  27. package/dist/types/cli/tool-bootstrap-core-registration.d.ts +2 -0
  28. package/dist/types/cli/turn-core.d.ts +2 -0
  29. package/dist/types/orchestration/agent-instance.d.ts +4 -0
  30. package/dist/types/orchestration/delegation-coordinator.d.ts +10 -0
  31. package/dist/types/orchestration/product-persistence.d.ts +4 -0
  32. package/dist/types/orchestration/workflow/capability-catalog.d.ts +1 -1
  33. package/dist/types/orchestration/workflow/workflow-controller.d.ts +1 -1
  34. package/dist/types/orchestration/workflow/workflow-runtime.d.ts +1 -1
  35. package/dist/types/protocol/notifications.d.ts +1 -1
  36. package/dist/types/protocol/wire/acp-agent-management.d.ts +16 -0
  37. package/dist/types/protocol/wire/agent-events.d.ts +2 -2
  38. package/dist/types/protocol/wire/agent-methods.d.ts +3 -0
  39. package/dist/types/protocol/wire/index.d.ts +1 -1
  40. package/dist/types/protocol/wire/notification-payloads.d.ts +26 -0
  41. package/dist/types/runtime/execution/turn-progress-notifier.d.ts +16 -0
  42. package/dist/types/runtime/infra/acp-detector.d.ts +40 -6
  43. package/dist/types/runtime/infra/acp-protocol-adapter.d.ts +14 -0
  44. package/dist/types/runtime/infra/agent-process.d.ts +16 -0
  45. package/dist/types/runtime/infra/astraclaw-capabilities.d.ts +2 -2
  46. package/dist/types/runtime/infra/builtin-skills-seed.d.ts +31 -0
  47. package/dist/types/runtime/infra/llmrouter-catalog.d.ts +26 -6
  48. package/dist/types/runtime/infra/model-registry.d.ts +43 -2
  49. package/dist/types/runtime/infra/project-data-gc.d.ts +7 -1
  50. package/dist/types/runtime/infra/skill-resolver.d.ts +15 -0
  51. package/dist/types/runtime/infra/user-dirs.d.ts +21 -0
  52. package/dist/types/runtime/permission-model.d.ts +1 -1
  53. package/dist/types/runtime/ports/permission-contracts.d.ts +5 -2
  54. package/dist/types/runtime/prompt/environment-context.d.ts +24 -2
  55. package/dist/types/runtime/prompt/fresh-workspace-evidence.d.ts +1 -2
  56. package/dist/types/runtime/prompt/identity-section.d.ts +17 -0
  57. package/dist/types/runtime/session/inbound-upload-persistence.d.ts +20 -0
  58. package/dist/types/runtime/session/native/claude-session-source.d.ts +23 -0
  59. package/dist/types/runtime/session/native/codex-index.d.ts +21 -0
  60. package/dist/types/runtime/session/native/codex-session-source.d.ts +31 -0
  61. package/dist/types/runtime/session/native/cwd-normalize.d.ts +53 -0
  62. package/dist/types/runtime/session/native/ephemeral-rollout-sweep.d.ts +13 -0
  63. package/dist/types/runtime/session/native/native-cwd-agents.d.ts +17 -0
  64. package/dist/types/runtime/session/native/native-session-source.d.ts +89 -0
  65. package/dist/types/runtime/session/native/native-title.d.ts +1 -0
  66. package/dist/types/runtime/session/native/register-builtin-sources.d.ts +1 -0
  67. package/dist/types/runtime/session/session-recovery.d.ts +58 -0
  68. package/dist/types/runtime/session/session-types.d.ts +30 -0
  69. package/dist/types/skills/permissions/hook-runner.d.ts +9 -0
  70. package/dist/types/skills/permissions/settings-watcher.d.ts +7 -0
  71. package/dist/types/skills/tools/exec-tool.d.ts +1 -1
  72. package/dist/types/skills/tools/shell/command-classification.d.ts +1 -0
  73. package/dist/types/skills/tools/shell/index.d.ts +3 -3
  74. package/dist/types/skills/tools/shell/powershell-provider.d.ts +8 -3
  75. package/dist/types/skills/tools/shell/shell-exec.d.ts +18 -0
  76. package/dist/types/skills/tools/shell/shell-provider.d.ts +67 -5
  77. package/dist/types/transport/acp-server.d.ts +6 -0
  78. package/package.json +4 -1
@@ -2,6 +2,22 @@ import type { ChatMessage } from "../../protocol/wire/index.js";
2
2
  import type { TokenUsage } from "../../agent/types.js";
3
3
  import type { SessionUsageSnapshot } from "./session-state.js";
4
4
  export declare const SESSION_SCHEMA_VERSION = 1;
5
+ /** 熔断阈值:连续崩溃中断达此次数后放弃自动恢复(对齐 hermes stuck-loop 的 3)。 */
6
+ export declare const MAX_INTERRUPTED_RECOVERY = 3;
7
+ /**
8
+ * 在飞轮次标记。turn 开始写入 SessionMetadata.inflightTurn,正常完成/用户主动中断时清除。
9
+ * 崩溃/非优雅退出时它残留在磁盘上 —— 这就是"上次这轮没跑完"的显式信号
10
+ * (对照 codex CLI 靠时间戳隐式推断、坏了要手动裁 JSONL,见 docs/session-lifecycle-recovery-spec.md §7)。
11
+ */
12
+ export interface InflightTurnMarker {
13
+ turnId: string;
14
+ /** turn 开始时间(ISO)。启动扫描用它与 transcript 最后一条 assistant 消息的 ts 做双校验。 */
15
+ startedAt: string;
16
+ /** 最后一条 user 消息前若干字(UI 提示用,不含敏感全文)。 */
17
+ lastUserPreview?: string;
18
+ /** 该轮是否已执行过有副作用的工具(写文件/发消息/外部 API)。安全档不据此自动续,仅用于 UI"可能重复"提示 + 为智能档铺路。 */
19
+ hadSideEffectTool?: boolean;
20
+ }
5
21
  export interface SessionMetadata {
6
22
  schemaVersion?: number;
7
23
  sessionId: string;
@@ -30,6 +46,12 @@ export interface SessionMetadata {
30
46
  groupPlatform?: string;
31
47
  totalInputTokens?: number;
32
48
  totalOutputTokens?: number;
49
+ /** 在飞轮次标记:存在即"上次这轮没跑完"(崩溃残留)。turn 开始写、正常完成/中断清。 */
50
+ inflightTurn?: InflightTurnMarker;
51
+ /** 连续崩溃中断计数;turn 正常完成清零;达 MAX_INTERRUPTED_RECOVERY 熔断放弃恢复。 */
52
+ interruptedTurnCount?: number;
53
+ /** 达熔断阈值放弃恢复的时间戳(UI 显示"多次中断已停止自动恢复")。 */
54
+ recoveryAbandonedAt?: string;
33
55
  }
34
56
  export interface PersistedSession {
35
57
  metadata: SessionMetadata;
@@ -43,6 +65,14 @@ export interface MessageDisplayMetadata {
43
65
  chatId?: string;
44
66
  userId?: string;
45
67
  userName?: string;
68
+ /**
69
+ * Presentation kind for a persisted message whose ROLE alone doesn't capture how
70
+ * the UI should render it. Currently: "mid_turn_guidance" — a user-authored message
71
+ * injected into a running turn (运行中引导). It stays role:"user" (the model must see
72
+ * it as the user's words), but the desktop renders it as an agent-side "收到引导"
73
+ * receipt line rather than a standalone user bubble.
74
+ */
75
+ kind?: string;
46
76
  }
47
77
  export interface PersistedChatMessage extends ChatMessage {
48
78
  timestamp?: string;
@@ -43,6 +43,14 @@ export interface PermissionCheckerDeps {
43
43
  sessionId?: string;
44
44
  /** Getter for current turn ID (changes per turn). */
45
45
  getTurnId?: () => string;
46
+ /**
47
+ * Persist a directory allow-rule across restarts (user picked "始终允许此文件夹").
48
+ * Wired by the CLI layer to append into the user-level settings.json; optional so
49
+ * headless/test checkers degrade to session-only memory.
50
+ */
51
+ persistPermissionRule?: (rule: {
52
+ pathPrefix: string;
53
+ }) => void | Promise<void>;
46
54
  }
47
55
  export declare class PermissionChecker {
48
56
  private readonly ruleEngine;
@@ -57,6 +65,7 @@ export declare class PermissionChecker {
57
65
  private readonly auditLogger;
58
66
  private readonly sessionId;
59
67
  private readonly getTurnId;
68
+ private readonly persistPermissionRule;
60
69
  private unregisterHook;
61
70
  /** Tool meta cache — populated from ToolDefinition[] at agent creation */
62
71
  private toolMetaCache;
@@ -1,6 +1,13 @@
1
1
  /**
2
2
  * Settings watcher for canonical qlogicagent permission settings.
3
3
  *
4
+ * Two layers (CC settings semantics):
5
+ * - user level ~/.qlogicagent/profiles/<owner>/settings.json — where config.update persists
6
+ * - project level <projectRoot>/.qlogicagent/settings.json — repo-local overrides
7
+ * The project file's `permissions` object, when present, overrides the user file's.
8
+ * Both layers are watched; either changing re-resolves the effective permissions.
9
+ * (写读同源:此前 config.update 写用户级、watcher 只读项目级,重启后持久模式永远丢失。)
10
+ *
4
11
  * Only the `permissions` object is accepted. Removed top-level aliases such as
5
12
  * `permissionMode`, `permissionRules`, and `defaultBehavior` must fail loudly.
6
13
  */
@@ -16,7 +16,7 @@ export declare const EXEC_TOOL_SCHEMA: {
16
16
  readonly properties: {
17
17
  readonly command: {
18
18
  readonly type: "string";
19
- readonly description: "Shell command to execute in PowerShell." | "Shell command to execute in bash. Use Unix-style commands (ls, cat, mkdir -p, etc.).";
19
+ readonly description: "Shell command to execute in PowerShell. See the # Environment section for the active edition and path/syntax rules." | "Shell command to execute in bash. Use Unix-style commands (ls, cat, mkdir -p, etc.).";
20
20
  };
21
21
  readonly description: {
22
22
  readonly type: "string";
@@ -50,3 +50,4 @@ export declare function requiresDedicatedReadSearchTool(classification: CommandC
50
50
  * called for reads/searches now (directory listing is allowed via exec — see above).
51
51
  */
52
52
  export declare function dedicatedToolRedirectMessage(classification: CommandClassification): string;
53
+ export declare function commandTargetsBinaryFile(command: string | null): boolean;
@@ -1,5 +1,5 @@
1
- export type { ShellType, BuildCommandOpts, BuiltCommand, ShellProvider, } from "./shell-provider.js";
2
- export { isPowerShellToolEnabled, getDefaultShellType, generateCommandId, } from "./shell-provider.js";
1
+ export type { ShellType, PowerShellEdition, ShellSelection, WindowsPowerShellResolution, WindowsPowerShellProbe, BuildCommandOpts, BuiltCommand, ShellProvider, } from "./shell-provider.js";
2
+ export { isPowerShellToolEnabled, resolveShellSelection, resolveWindowsPowerShell, getDefaultShellType, generateCommandId, } from "./shell-provider.js";
3
3
  export { createBashProvider } from "./bash-provider.js";
4
4
  export type { BashProviderOptions } from "./bash-provider.js";
5
5
  export { createPowerShellProvider, encodePowerShellCommand, } from "./powershell-provider.js";
@@ -14,5 +14,5 @@ export type { ProgressCallback } from "./task-output.js";
14
14
  export type { ExecResult, ShellCommand } from "./shell-command.js";
15
15
  export { wrapSpawn, createAbortedCommand, createFailedCommand, } from "./shell-command.js";
16
16
  export { subprocessEnv } from "./subprocess-env.js";
17
- export { exec, getCwd, setCwd, initCwd, getOriginalCwd, setShellProvider, getShellProvider, } from "./shell-exec.js";
17
+ export { exec, getCwd, setCwd, initCwd, getOriginalCwd, setShellProvider, getShellProvider, getActiveShellInfo, } from "./shell-exec.js";
18
18
  export type { ExecOptions } from "./shell-exec.js";
@@ -1,4 +1,4 @@
1
- import type { ShellProvider } from "./shell-provider.js";
1
+ import type { ShellProvider, PowerShellEdition } from "./shell-provider.js";
2
2
  /**
3
3
  * Encode a PowerShell command as UTF-16LE Base64 for -EncodedCommand.
4
4
  * This avoids all quoting/escaping issues when passing complex commands
@@ -7,9 +7,14 @@ import type { ShellProvider } from "./shell-provider.js";
7
7
  * Ported directly from cc's `encodePowerShellCommand()`.
8
8
  */
9
9
  export declare function encodePowerShellCommand(psCommand: string): string;
10
+ export interface PowerShellProviderOptions {
11
+ /** Which PowerShell edition `shellPath` is (5.1 vs 7+); surfaced as `psEdition`. */
12
+ edition?: PowerShellEdition;
13
+ }
10
14
  /**
11
15
  * Create a PowerShell ShellProvider.
12
16
  *
13
- * @param shellPath Absolute path to pwsh.exe or powershell.exe
17
+ * @param shellPath Absolute path (or PATH-resolvable name) to pwsh.exe / powershell.exe
18
+ * @param options Optional edition metadata (from `resolveWindowsPowerShell`)
14
19
  */
15
- export declare function createPowerShellProvider(shellPath: string): ShellProvider;
20
+ export declare function createPowerShellProvider(shellPath: string, options?: PowerShellProviderOptions): ShellProvider;
@@ -31,6 +31,24 @@ export declare function setShellProvider(provider: ShellProvider): void;
31
31
  * Get the current shell provider, or throw if not configured.
32
32
  */
33
33
  export declare function getShellProvider(): ShellProvider;
34
+ /**
35
+ * Read-only snapshot of the active shell provider's identity, as plain data.
36
+ *
37
+ * Consumed by the prompt layer (via the CLI, which passes it in — the prompt
38
+ * layer must not import shell modules) to tailor environment guidance to the
39
+ * shell that `exec()` actually drives, instead of re-guessing from env vars.
40
+ *
41
+ * Returns `undefined` when no provider has been configured yet. This MUST NOT
42
+ * throw: prompt assembly can run before/without `setShellProvider()` (tests,
43
+ * lightweight turns), and a missing provider is a normal "fall back to
44
+ * detectShellType()" signal, not an error.
45
+ */
46
+ export declare function getActiveShellInfo(): {
47
+ type: ShellType;
48
+ shellPath: string;
49
+ psEdition?: "5.1" | "7+";
50
+ isGitBashOnWindows?: boolean;
51
+ } | undefined;
34
52
  /**
35
53
  * Execute a shell command using the configured provider.
36
54
  * Creates a new child process for each invocation.
@@ -2,6 +2,13 @@
2
2
  * Discriminated shell type identifier.
3
3
  */
4
4
  export type ShellType = "bash" | "powershell";
5
+ /**
6
+ * Which PowerShell edition the active provider drives.
7
+ * "5.1" = Windows PowerShell (powershell.exe) — no `&&`/`||`, use `;`.
8
+ * "7+" = PowerShell 7 (pwsh) — `&&`/`||` supported.
9
+ * Consumed by prompt/guidance layers to tailor syntax advice.
10
+ */
11
+ export type PowerShellEdition = "5.1" | "7+";
5
12
  /**
6
13
  * Options passed to `buildExecCommand`.
7
14
  */
@@ -45,19 +52,31 @@ export interface ShellProvider {
45
52
  * PowerShell: false (no POSIX process groups on Windows).
46
53
  */
47
54
  readonly detached: boolean;
55
+ /**
56
+ * For PowerShell providers: which edition the binary is (5.1 vs 7+).
57
+ * Undefined for bash. Read by prompt guidance to decide `&&` vs `;`.
58
+ */
59
+ readonly psEdition?: PowerShellEdition;
60
+ /**
61
+ * True when this is a bash provider running on Windows (Git Bash / MSYS).
62
+ * Undefined/false otherwise. Read by prompt guidance for path conventions.
63
+ */
64
+ readonly isGitBashOnWindows?: boolean;
48
65
  /**
49
66
  * Wrap a raw user command into a full shell command string.
50
67
  * Handles:
51
68
  * - Environment snapshots / session env sourcing (bash)
52
- * - UTF-16LE EncodedCommand wrapping (PowerShell)
53
69
  * - CWD tracking (`pwd -P > file` / `Get-Location | Out-File`)
54
70
  * - stdin redirect for interactive commands (bash)
71
+ * Returns the UNENCODED script; PowerShell's UTF-16LE EncodedCommand wrapping
72
+ * happens in getSpawnArgs so the encode is applied exactly once.
55
73
  */
56
74
  buildExecCommand(command: string, opts: BuildCommandOpts): Promise<BuiltCommand>;
57
75
  /**
58
76
  * Return the argv array for `child_process.spawn()`.
59
77
  * E.g. bash → `['-c', commandString]`
60
- * PS → `['-NoProfile', '-NonInteractive', '-Command', cmd]`
78
+ * PS → `['-NoProfile', '-NonInteractive', '-EncodedCommand', <utf16le-base64(commandString)>]`
79
+ * (`commandString` is the UNENCODED script; PS encodes it here, exactly once.)
61
80
  */
62
81
  getSpawnArgs(commandString: string): string[];
63
82
  /**
@@ -66,18 +85,61 @@ export interface ShellProvider {
66
85
  */
67
86
  getEnvironmentOverrides(command: string): Promise<Record<string, string>>;
68
87
  }
88
+ /** High-level shell family selected for the current platform + env. */
89
+ export type ShellSelection = "powershell" | "bash";
90
+ /**
91
+ * Pure decision: given a platform + env, pick the shell family.
92
+ *
93
+ * Contract (the "flip default"):
94
+ * - non-win32 → bash (unchanged)
95
+ * - win32, QLOGICAGENT_SHELL=bash → bash (explicit opt-in Git Bash)
96
+ * - win32, QLOGICAGENT_SHELL=powershell|pwsh → powershell
97
+ * - win32, QLOGICAGENT_USE_POWERSHELL truthy (compat alias) → powershell
98
+ * - win32, nothing set → powershell ← flipped default
99
+ *
100
+ * `QLOGICAGENT_SHELL` is the single three-state switch; the legacy
101
+ * `QLOGICAGENT_USE_POWERSHELL` truthy flag is kept as a compat alias but is
102
+ * overridden by an explicit `QLOGICAGENT_SHELL=bash`.
103
+ */
104
+ export declare function resolveShellSelection(platform: NodeJS.Platform, env: NodeJS.ProcessEnv): ShellSelection;
69
105
  /**
70
- * Check if PowerShell tool mode should be enabled.
106
+ * Check if PowerShell tool mode should be enabled for the live process.
71
107
  * Mirrors cc's `isPowerShellToolEnabled()`.
72
108
  *
73
- * On Windows: enabled when `QLOGICAGENT_USE_POWERSHELL` is truthy.
74
- * On non-Windows: always false.
109
+ * On Windows the default is now PowerShell (see `resolveShellSelection`);
110
+ * `QLOGICAGENT_SHELL=bash` opts back into Git Bash. On non-Windows: false.
75
111
  */
76
112
  export declare function isPowerShellToolEnabled(): boolean;
77
113
  /**
78
114
  * Default shell type for the current platform.
79
115
  */
80
116
  export declare function getDefaultShellType(): ShellType;
117
+ /**
118
+ * Result of Windows PowerShell resolution: the binary to spawn plus which
119
+ * edition it is (so guidance can decide `&&` vs `;`).
120
+ */
121
+ export interface WindowsPowerShellResolution {
122
+ shellPath: string;
123
+ psEdition: PowerShellEdition;
124
+ }
125
+ /**
126
+ * Injectable probes for `resolveWindowsPowerShell` (so it is unit-testable off
127
+ * a real Windows host). Defaults hit the real filesystem / PATH.
128
+ */
129
+ export interface WindowsPowerShellProbe {
130
+ /** Whether a path exists on disk. */
131
+ exists(path: string): boolean;
132
+ /** Absolute path to `pwsh` on PATH, or null if not found. */
133
+ pwshOnPath(): string | null;
134
+ }
135
+ /**
136
+ * Resolve which PowerShell binary to drive on Windows.
137
+ *
138
+ * Order: explicit `QLOGICAGENT_POWERSHELL_PATH` → `pwsh` on PATH (PS7) →
139
+ * well-known pwsh install path (PS7) → `powershell.exe` (5.1, always present).
140
+ * The returned `psEdition` records which one was chosen.
141
+ */
142
+ export declare function resolveWindowsPowerShell(env: NodeJS.ProcessEnv, probe: WindowsPowerShellProbe): WindowsPowerShellResolution;
81
143
  /**
82
144
  * Generate a short random hex ID for CWD temp file naming.
83
145
  * Matches cc's `Math.floor(Math.random() * 0x10000).toString(16)`.
@@ -154,6 +154,12 @@ export declare class AcpServer {
154
154
  * Returns a promise that resolves with the host's chosen option.
155
155
  */
156
156
  requestPermission(params: AcpPermissionRequestParams): Promise<AcpPermissionRequestResult>;
157
+ /**
158
+ * Cancel every in-flight permission request (turn abort / session cancel). Each
159
+ * awaiter resolves to "deny" and its maps are cleared, so a cancelled turn's
160
+ * pending approval can't survive to poison the next turn.
161
+ */
162
+ cancelAllPendingPermissions(): void;
157
163
  /** Whether the host supports extended events */
158
164
  get supportsExtendedEvents(): boolean;
159
165
  /** Whether the host supports extended methods */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qlogicagent",
3
- "version": "2.17.9",
3
+ "version": "2.18.1",
4
4
  "description": "XiaozhiClaw Agent CLI — subprocess architecture (JSON-RPC over stdio)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -69,6 +69,7 @@
69
69
  "build:search-svc": "node scripts/build-search-svc.mjs",
70
70
  "start": "node dist/cli.js",
71
71
  "test": "vitest run",
72
+ "test:replay": "vitest run benchmarks/transcript-replay",
72
73
  "check": "pnpm run check:encoding-corruption && tsc --noEmit && pnpm test && pnpm run check:architecture-boundaries && pnpm run check:provider-core-boundary && pnpm run check:provider-core-release-sync && pnpm run check:pet-core-boundary && pnpm run check:workspace-hygiene && pnpm run check:package-artifact",
73
74
  "test:watch": "vitest",
74
75
  "benchmark:hermes-superiority": "tsx benchmarks/hermes-superiority/runner.ts",
@@ -81,6 +82,7 @@
81
82
  "check:workspace-hygiene": "node scripts/check-workspace-hygiene.mjs",
82
83
  "check:workspace-hygiene:strict": "node scripts/check-workspace-hygiene.mjs --strict",
83
84
  "check:package-artifact": "npm run build && node scripts/check-package-artifact.mjs",
85
+ "corpus:export-feedback": "tsx scripts/export-feedback-corpus.ts",
84
86
  "redteam:community-desensitization": "tsx src/runtime/community/community-desensitization-red-team-cli.ts",
85
87
  "clean:workspace-hygiene": "node scripts/clean-workspace-hygiene.mjs",
86
88
  "release": "node scripts/release.mjs"
@@ -106,6 +108,7 @@
106
108
  "@types/better-sqlite3": "^7.6.13",
107
109
  "@types/node": "^22.15.0",
108
110
  "esbuild": "^0.28.0",
111
+ "javascript-obfuscator": "^5.4.3",
109
112
  "oxlint": "1.67.0",
110
113
  "tsx": "^4.19.0",
111
114
  "typescript": "^5.9.0",