aiwcli 0.10.2 → 0.10.3

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 (105) hide show
  1. package/dist/commands/clear.d.ts +11 -6
  2. package/dist/commands/clear.js +200 -249
  3. package/dist/commands/init/index.d.ts +1 -17
  4. package/dist/commands/init/index.js +19 -104
  5. package/dist/lib/template-installer.d.ts +7 -12
  6. package/dist/lib/template-installer.js +69 -193
  7. package/dist/lib/template-settings-reconstructor.d.ts +35 -0
  8. package/dist/lib/template-settings-reconstructor.js +130 -0
  9. package/dist/templates/_shared/hooks/__pycache__/archive_plan.cpython-313.pyc +0 -0
  10. package/dist/templates/_shared/hooks/archive_plan.py +10 -2
  11. package/dist/templates/_shared/lib/base/__pycache__/hook_utils.cpython-313.pyc +0 -0
  12. package/dist/templates/_shared/lib/base/__pycache__/inference.cpython-313.pyc +0 -0
  13. package/dist/templates/_shared/lib/base/__pycache__/logger.cpython-313.pyc +0 -0
  14. package/dist/templates/_shared/lib/base/__pycache__/stop_words.cpython-313.pyc +0 -0
  15. package/dist/templates/_shared/lib/base/__pycache__/utils.cpython-313.pyc +0 -0
  16. package/dist/templates/_shared/lib/base/hook_utils.py +8 -10
  17. package/dist/templates/_shared/lib/base/inference.py +51 -62
  18. package/dist/templates/_shared/lib/base/logger.py +35 -21
  19. package/dist/templates/_shared/lib/base/stop_words.py +8 -0
  20. package/dist/templates/_shared/lib/base/utils.py +29 -8
  21. package/dist/templates/_shared/lib/context/__pycache__/plan_manager.cpython-313.pyc +0 -0
  22. package/dist/templates/_shared/lib/context/plan_manager.py +101 -2
  23. package/dist/templates/_shared/lib-ts/base/atomic-write.ts +138 -0
  24. package/dist/templates/_shared/lib-ts/base/constants.ts +299 -0
  25. package/dist/templates/_shared/lib-ts/base/git-state.ts +58 -0
  26. package/dist/templates/_shared/lib-ts/base/hook-utils.ts +360 -0
  27. package/dist/templates/_shared/lib-ts/base/inference.ts +245 -0
  28. package/dist/templates/_shared/lib-ts/base/logger.ts +234 -0
  29. package/dist/templates/_shared/lib-ts/base/state-io.ts +114 -0
  30. package/dist/templates/_shared/lib-ts/base/stop-words.ts +184 -0
  31. package/dist/templates/_shared/lib-ts/base/subprocess-utils.ts +23 -0
  32. package/dist/templates/_shared/lib-ts/base/utils.ts +184 -0
  33. package/dist/templates/_shared/lib-ts/context/context-formatter.ts +432 -0
  34. package/dist/templates/_shared/lib-ts/context/context-selector.ts +497 -0
  35. package/dist/templates/_shared/lib-ts/context/context-store.ts +679 -0
  36. package/dist/templates/_shared/lib-ts/context/plan-manager.ts +292 -0
  37. package/dist/templates/_shared/lib-ts/context/task-tracker.ts +181 -0
  38. package/dist/templates/_shared/lib-ts/handoff/document-generator.ts +215 -0
  39. package/dist/templates/_shared/lib-ts/package.json +21 -0
  40. package/dist/templates/_shared/lib-ts/templates/formatters.ts +102 -0
  41. package/dist/templates/_shared/lib-ts/templates/plan-context.ts +65 -0
  42. package/dist/templates/_shared/lib-ts/tsconfig.json +13 -0
  43. package/dist/templates/_shared/lib-ts/types.ts +151 -0
  44. package/dist/templates/_shared/scripts/__pycache__/status_line.cpython-313.pyc +0 -0
  45. package/dist/templates/_shared/scripts/save_handoff.ts +359 -0
  46. package/dist/templates/_shared/scripts/status_line.py +17 -2
  47. package/dist/templates/cc-native/_cc-native/agents/ARCH-EVOLUTION.md +63 -0
  48. package/dist/templates/cc-native/_cc-native/agents/ARCH-PATTERNS.md +62 -0
  49. package/dist/templates/cc-native/_cc-native/agents/ARCH-STRUCTURE.md +63 -0
  50. package/dist/templates/cc-native/_cc-native/agents/{ASSUMPTION-CHAIN-TRACER.md → ASSUMPTION-TRACER.md} +6 -10
  51. package/dist/templates/cc-native/_cc-native/agents/CLARITY-AUDITOR.md +6 -10
  52. package/dist/templates/cc-native/_cc-native/agents/CLAUDE.md +74 -1
  53. package/dist/templates/cc-native/_cc-native/agents/COMPLETENESS-FEASIBILITY.md +67 -0
  54. package/dist/templates/cc-native/_cc-native/agents/COMPLETENESS-GAPS.md +71 -0
  55. package/dist/templates/cc-native/_cc-native/agents/COMPLETENESS-ORDERING.md +63 -0
  56. package/dist/templates/cc-native/_cc-native/agents/CONSTRAINT-VALIDATOR.md +73 -0
  57. package/dist/templates/cc-native/_cc-native/agents/DESIGN-ADR-VALIDATOR.md +62 -0
  58. package/dist/templates/cc-native/_cc-native/agents/DESIGN-SCALE-MATCHER.md +65 -0
  59. package/dist/templates/cc-native/_cc-native/agents/DEVILS-ADVOCATE.md +6 -9
  60. package/dist/templates/cc-native/_cc-native/agents/DOCUMENTATION-PHILOSOPHY.md +87 -0
  61. package/dist/templates/cc-native/_cc-native/agents/HANDOFF-READINESS.md +5 -9
  62. package/dist/templates/cc-native/_cc-native/agents/{HIDDEN-COMPLEXITY-DETECTOR.md → HIDDEN-COMPLEXITY.md} +6 -10
  63. package/dist/templates/cc-native/_cc-native/agents/INCREMENTAL-DELIVERY.md +67 -0
  64. package/dist/templates/cc-native/_cc-native/agents/PLAN-ORCHESTRATOR.md +91 -18
  65. package/dist/templates/cc-native/_cc-native/agents/RISK-DEPENDENCY.md +63 -0
  66. package/dist/templates/cc-native/_cc-native/agents/RISK-FMEA.md +67 -0
  67. package/dist/templates/cc-native/_cc-native/agents/RISK-PREMORTEM.md +72 -0
  68. package/dist/templates/cc-native/_cc-native/agents/RISK-REVERSIBILITY.md +75 -0
  69. package/dist/templates/cc-native/_cc-native/agents/SCOPE-BOUNDARY.md +78 -0
  70. package/dist/templates/cc-native/_cc-native/agents/SIMPLICITY-GUARDIAN.md +5 -9
  71. package/dist/templates/cc-native/_cc-native/agents/SKEPTIC.md +16 -12
  72. package/dist/templates/cc-native/_cc-native/agents/TESTDRIVEN-BEHAVIOR-AUDITOR.md +62 -0
  73. package/dist/templates/cc-native/_cc-native/agents/TESTDRIVEN-CHARACTERIZATION.md +72 -0
  74. package/dist/templates/cc-native/_cc-native/agents/TESTDRIVEN-FIRST-VALIDATOR.md +62 -0
  75. package/dist/templates/cc-native/_cc-native/agents/TESTDRIVEN-PYRAMID-ANALYZER.md +62 -0
  76. package/dist/templates/cc-native/_cc-native/agents/TRADEOFF-COSTS.md +68 -0
  77. package/dist/templates/cc-native/_cc-native/agents/TRADEOFF-STAKEHOLDERS.md +66 -0
  78. package/dist/templates/cc-native/_cc-native/agents/VERIFY-COVERAGE.md +75 -0
  79. package/dist/templates/cc-native/_cc-native/agents/VERIFY-STRENGTH.md +70 -0
  80. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/cc-native-plan-review.cpython-313.pyc +0 -0
  81. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.py +125 -40
  82. package/dist/templates/cc-native/_cc-native/lib/__pycache__/utils.cpython-313.pyc +0 -0
  83. package/dist/templates/cc-native/_cc-native/lib/utils.py +57 -13
  84. package/dist/templates/cc-native/_cc-native/plan-review.config.json +11 -7
  85. package/oclif.manifest.json +1 -1
  86. package/package.json +1 -1
  87. package/dist/lib/template-merger.d.ts +0 -47
  88. package/dist/lib/template-merger.js +0 -162
  89. package/dist/templates/cc-native/_cc-native/agents/ACCESSIBILITY-TESTER.md +0 -79
  90. package/dist/templates/cc-native/_cc-native/agents/ARCHITECT-REVIEWER.md +0 -48
  91. package/dist/templates/cc-native/_cc-native/agents/CODE-REVIEWER.md +0 -70
  92. package/dist/templates/cc-native/_cc-native/agents/COMPLETENESS-CHECKER.md +0 -59
  93. package/dist/templates/cc-native/_cc-native/agents/CONTEXT-EXTRACTOR.md +0 -92
  94. package/dist/templates/cc-native/_cc-native/agents/DOCUMENTATION-REVIEWER.md +0 -51
  95. package/dist/templates/cc-native/_cc-native/agents/FEASIBILITY-ANALYST.md +0 -57
  96. package/dist/templates/cc-native/_cc-native/agents/FRESH-PERSPECTIVE.md +0 -54
  97. package/dist/templates/cc-native/_cc-native/agents/INCENTIVE-MAPPER.md +0 -61
  98. package/dist/templates/cc-native/_cc-native/agents/PENETRATION-TESTER.md +0 -79
  99. package/dist/templates/cc-native/_cc-native/agents/PERFORMANCE-ENGINEER.md +0 -75
  100. package/dist/templates/cc-native/_cc-native/agents/PRECEDENT-FINDER.md +0 -70
  101. package/dist/templates/cc-native/_cc-native/agents/REVERSIBILITY-ANALYST.md +0 -61
  102. package/dist/templates/cc-native/_cc-native/agents/RISK-ASSESSOR.md +0 -58
  103. package/dist/templates/cc-native/_cc-native/agents/SECOND-ORDER-ANALYST.md +0 -61
  104. package/dist/templates/cc-native/_cc-native/agents/STAKEHOLDER-ADVOCATE.md +0 -55
  105. package/dist/templates/cc-native/_cc-native/agents/TRADE-OFF-ILLUMINATOR.md +0 -204
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Unified logging for all hooks and libraries.
3
+ *
4
+ * Log format: JSONL (one JSON object per line)
5
+ * Log location: _output/hook-log.jsonl (global, all sessions)
6
+ * Filter by session using the "sid" field.
7
+ *
8
+ * Environment variables:
9
+ * - HOOK_LOG_DISABLE=1: Disable all file logging
10
+ * - HOOK_LOG_LEVEL=warn: Minimum level to log (default: debug)
11
+ * - HOOK_ERROR_LOG_DISABLE=1: Legacy alias for HOOK_LOG_DISABLE
12
+ *
13
+ * Never throws. No buffering. Stdlib only.
14
+ * See SPEC.md §3
15
+ */
16
+
17
+ import * as fs from "node:fs";
18
+ import * as path from "node:path";
19
+
20
+ const LEVELS: Record<string, number> = {
21
+ debug: 0,
22
+ info: 1,
23
+ warn: 2,
24
+ error: 3,
25
+ };
26
+
27
+ const MAX_LOG_LINES = 10_000; // Max lines in global log before pruning
28
+
29
+ // Module-level session ID cache
30
+ let _cachedSessionId: string | null = null;
31
+
32
+ // Module-level context path cache (kept for external callers)
33
+ let _cachedContextPath: string | null = null;
34
+ let _contextResolved = false;
35
+
36
+ /**
37
+ * Set the session ID for this process. All subsequent log calls include it.
38
+ */
39
+ export function setSessionId(sessionId: string | null): void {
40
+ _cachedSessionId = sessionId;
41
+ }
42
+
43
+ /**
44
+ * Set the context path for this process. Kept for external callers.
45
+ */
46
+ export function setContextPath(contextPath: string | null): void {
47
+ _cachedContextPath = contextPath;
48
+ _contextResolved = true;
49
+ }
50
+
51
+ export function getContextPath(): string | null {
52
+ if (!_contextResolved) {
53
+ _contextResolved = true; // Don't retry
54
+ }
55
+ return _cachedContextPath;
56
+ }
57
+
58
+ function getMinLevel(): number {
59
+ const env = (process.env.HOOK_LOG_LEVEL ?? "debug").toLowerCase();
60
+ return LEVELS[env] ?? 0;
61
+ }
62
+
63
+ function isDisabled(): boolean {
64
+ return (
65
+ process.env.HOOK_LOG_DISABLE === "1" ||
66
+ process.env.HOOK_ERROR_LOG_DISABLE === "1" ||
67
+ process.env.CCNATIVE_DEBUG_DISABLE === "1"
68
+ );
69
+ }
70
+
71
+ function getProjectRoot(): string {
72
+ return process.env.CLAUDE_PROJECT_DIR || process.cwd();
73
+ }
74
+
75
+ /**
76
+ * Write a structured log entry to the global hook log.
77
+ *
78
+ * All entries go to _output/hook-log.jsonl. Use the "sid" field
79
+ * (set via setSessionId) to filter by session.
80
+ */
81
+ export function hookLog(
82
+ level: string,
83
+ hookName: string,
84
+ message: string,
85
+ opts?: {
86
+ component?: string;
87
+ data?: any;
88
+ traceback_str?: string;
89
+ stderr?: boolean;
90
+ },
91
+ ): void {
92
+ try {
93
+ const levelLower = level.toLowerCase();
94
+ const levelNum = LEVELS[levelLower] ?? 0;
95
+ const component = opts?.component ?? "";
96
+ const tracebackStr = opts?.traceback_str ?? "";
97
+ const stderrEnabled = opts?.stderr !== false;
98
+
99
+ // Write to stderr
100
+ if (stderrEnabled) {
101
+ const prefix = component
102
+ ? `[${hookName}:${component}]`
103
+ : `[${hookName}]`;
104
+ process.stderr.write(`${prefix} ${message}\n`);
105
+ if (tracebackStr) {
106
+ process.stderr.write(tracebackStr + "\n");
107
+ }
108
+ }
109
+
110
+ // Check if file logging is enabled
111
+ if (isDisabled()) return;
112
+
113
+ // Check minimum level
114
+ if (levelNum < getMinLevel()) return;
115
+
116
+ // Build JSONL entry
117
+ const now = new Date();
118
+ const ts = now.toISOString().replace("Z", "").slice(0, 23);
119
+ const entry: Record<string, any> = {
120
+ ts,
121
+ level: levelLower,
122
+ hook: hookName,
123
+ msg: message,
124
+ };
125
+ if (_cachedSessionId) entry.sid = _cachedSessionId;
126
+ if (component) entry.component = component;
127
+ if (opts?.data !== undefined && opts.data !== null) {
128
+ try {
129
+ JSON.stringify(opts.data);
130
+ entry.data = opts.data;
131
+ } catch {
132
+ entry.data = String(opts.data);
133
+ }
134
+ }
135
+ if (tracebackStr) entry.tb = tracebackStr.trimEnd();
136
+
137
+ const line = JSON.stringify(entry) + "\n";
138
+
139
+ // Always write to global log
140
+ const logPath = path.join(getProjectRoot(), "_output", "hook-log.jsonl");
141
+
142
+ // Ensure directory exists
143
+ const dir = path.dirname(logPath);
144
+ fs.mkdirSync(dir, { recursive: true });
145
+
146
+ // Line-count guard: prune to last MAX_LOG_LINES
147
+ try {
148
+ if (fs.existsSync(logPath)) {
149
+ const content = fs.readFileSync(logPath, "utf-8");
150
+ const lines = content.split("\n");
151
+ if (lines.length > MAX_LOG_LINES) {
152
+ fs.writeFileSync(
153
+ logPath,
154
+ lines.slice(lines.length - MAX_LOG_LINES).join("\n"),
155
+ "utf-8",
156
+ );
157
+ }
158
+ }
159
+ } catch {
160
+ // ignore
161
+ }
162
+
163
+ fs.appendFileSync(logPath, line, "utf-8");
164
+ } catch {
165
+ // Never crash
166
+ }
167
+ }
168
+
169
+ export function logDebug(hookName: string, message: string, opts?: Record<string, any>): void {
170
+ hookLog("debug", hookName, message, opts);
171
+ }
172
+
173
+ export function logInfo(hookName: string, message: string, opts?: Record<string, any>): void {
174
+ hookLog("info", hookName, message, opts);
175
+ }
176
+
177
+ export function logWarn(hookName: string, message: string, opts?: Record<string, any>): void {
178
+ hookLog("warn", hookName, message, opts);
179
+ }
180
+
181
+ export function logError(hookName: string, message: string, opts?: Record<string, any>): void {
182
+ hookLog("error", hookName, message, opts);
183
+ }
184
+
185
+ /**
186
+ * Log a structured diagnostic entry at a hook decision point.
187
+ * See SPEC.md §3.8
188
+ */
189
+ export function logDiagnostic(
190
+ hookName: string,
191
+ phase: string,
192
+ summary: string,
193
+ opts?: {
194
+ inputs?: any;
195
+ decision?: any;
196
+ reasoning?: any;
197
+ component?: string;
198
+ data?: any;
199
+ },
200
+ ): void {
201
+ const diagData: Record<string, any> = { phase };
202
+ if (opts?.inputs !== undefined) diagData.inputs = opts.inputs;
203
+ if (opts?.decision !== undefined) diagData.decision = opts.decision;
204
+ if (opts?.reasoning !== undefined) diagData.reasoning = opts.reasoning;
205
+ if (opts?.data && typeof opts.data === "object") {
206
+ Object.assign(diagData, opts.data);
207
+ }
208
+ hookLog("debug", hookName, `[DIAG:${phase}] ${summary}`, {
209
+ component: opts?.component ?? "diag",
210
+ data: diagData,
211
+ });
212
+ }
213
+
214
+ /**
215
+ * Backward-compatible wrapper matching old hook_utils.log_hook_error signature.
216
+ * See SPEC.md §3.6
217
+ */
218
+ export function logHookError(
219
+ hookName: string,
220
+ error: Error | string,
221
+ hookEvent = "unknown",
222
+ tracebackStr = "",
223
+ ): void {
224
+ const errStr = typeof error === "string" ? error : String(error);
225
+ const msg = errStr.replace(/[\n\r]/g, " ").slice(0, 200);
226
+ const errType =
227
+ typeof error === "object" && error !== null
228
+ ? error.constructor.name
229
+ : "Error";
230
+ hookLog("error", hookName, `[${hookEvent}] ${errType}: ${msg}`, {
231
+ traceback_str: tracebackStr,
232
+ stderr: true,
233
+ });
234
+ }
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Shared I/O for state.json — read, write, serialize.
3
+ * Extracted to avoid circular deps between context-store and task-tracker.
4
+ * See SPEC.md §7.1
5
+ */
6
+
7
+ import * as fs from "node:fs";
8
+ import * as path from "node:path";
9
+ import { getContextDir } from "./constants.js";
10
+ import { atomicWrite } from "./atomic-write.js";
11
+ import { logWarn } from "./logger.js";
12
+ import type { ContextState, Mode } from "../types.js";
13
+
14
+ /** Mode migration from legacy context_manager values. */
15
+ const MODE_MIGRATION: Record<string, Mode> = {
16
+ none: "idle",
17
+ planning: "idle",
18
+ pending_implementation: "has_plan",
19
+ implementing: "active",
20
+ };
21
+
22
+ /**
23
+ * Serialize a ContextState for JSON output.
24
+ * Omits null/undefined keys but keeps false, 0, empty string, and empty arrays.
25
+ */
26
+ export function toDict(state: ContextState): Record<string, unknown> {
27
+ const result: Record<string, unknown> = {};
28
+ for (const [key, value] of Object.entries(state)) {
29
+ if (value !== null && value !== undefined) {
30
+ result[key] = value;
31
+ }
32
+ }
33
+ return result;
34
+ }
35
+
36
+ /**
37
+ * Get path to state.json for a context.
38
+ */
39
+ export function statePath(contextId: string, projectRoot?: string): string {
40
+ return path.join(getContextDir(contextId, projectRoot), "state.json");
41
+ }
42
+
43
+ /**
44
+ * Read and parse state.json for a context.
45
+ * Applies legacy mode migration. Returns null if file doesn't exist or is corrupt.
46
+ */
47
+ export function readStateJson(
48
+ contextId: string,
49
+ projectRoot?: string,
50
+ ): ContextState | null {
51
+ const sp = statePath(contextId, projectRoot);
52
+ if (!fs.existsSync(sp)) return null;
53
+
54
+ try {
55
+ const raw = fs.readFileSync(sp, "utf-8");
56
+ const data = JSON.parse(raw) as Record<string, any>;
57
+ return dictToState(data);
58
+ } catch (e: any) {
59
+ logWarn("state_io", `Failed to read state.json for '${contextId}': ${e}`);
60
+ return null;
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Atomically write state.json for a context.
66
+ * Returns [success, error].
67
+ */
68
+ export function writeStateJson(
69
+ contextId: string,
70
+ state: ContextState,
71
+ projectRoot?: string,
72
+ ): [boolean, string | null] {
73
+ const sp = statePath(contextId, projectRoot);
74
+ const dir = path.dirname(sp);
75
+ fs.mkdirSync(dir, { recursive: true });
76
+
77
+ const content = JSON.stringify(toDict(state), null, 2);
78
+ return atomicWrite(sp, content);
79
+ }
80
+
81
+ /**
82
+ * Construct a ContextState from a dict, migrating old mode names.
83
+ * Only includes fields that are present in the source data (preserves null-stripping).
84
+ */
85
+ export function dictToState(data: Record<string, any>): ContextState {
86
+ const rawMode: string = data.mode ?? "idle";
87
+ const mode: Mode = (MODE_MIGRATION[rawMode] ?? rawMode) as Mode;
88
+
89
+ const state: any = {
90
+ id: data.id,
91
+ status: data.status ?? "active",
92
+ summary: data.summary ?? "",
93
+ method: data.method ?? "",
94
+ tags: data.tags ?? [],
95
+ created_at: data.created_at ?? "",
96
+ last_active: data.last_active ?? "",
97
+ mode,
98
+ plan_anchors: data.plan_anchors ?? [],
99
+ plan_consumed: data.plan_consumed ?? false,
100
+ handoff_consumed: data.handoff_consumed ?? false,
101
+ session_ids: data.session_ids ?? [],
102
+ tasks: data.tasks ?? [],
103
+ };
104
+
105
+ // Only set nullable fields if they exist in the source data
106
+ if ("plan_path" in data) state.plan_path = data.plan_path;
107
+ if ("plan_hash" in data) state.plan_hash = data.plan_hash;
108
+ if ("plan_signature" in data) state.plan_signature = data.plan_signature;
109
+ if ("plan_id" in data) state.plan_id = data.plan_id;
110
+ if ("handoff_path" in data) state.handoff_path = data.handoff_path;
111
+ if ("last_session" in data) state.last_session = data.last_session;
112
+
113
+ return state as ContextState;
114
+ }
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Stop words for context ID generation.
3
+ *
4
+ * Generated from analysis of 1,424 prompts, context summaries, and plan files.
5
+ * Words that appear frequently but don't help identify the specific task.
6
+ *
7
+ * ACTION VERBS ARE INTENTIONALLY EXCLUDED:
8
+ * add, fix, update, create, implement, refactor, migrate, debug, remove, change,
9
+ * move, rename, delete, build, test, deploy, verify, analyze, modify, write, run,
10
+ * check, replace, save, sync, load, extract, install, clean, merge, etc.
11
+ *
12
+ * See SPEC.md §14.1
13
+ */
14
+
15
+ export const STOP_WORDS: ReadonlySet<string> = new Set([
16
+ // ARTICLES
17
+ "a", "an", "the",
18
+
19
+ // PREPOSITIONS
20
+ "to", "for", "in", "on", "at", "by", "with", "from", "of", "about",
21
+ "into", "over", "under", "between", "through", "during", "before", "after",
22
+ "above", "below", "against", "among", "around", "behind", "beside", "besides",
23
+ "beyond", "down", "inside", "outside", "near", "off", "onto", "out",
24
+ "since", "toward", "towards", "until", "upon", "within", "without",
25
+ "across", "along", "via", "per",
26
+
27
+ // PRONOUNS - Personal
28
+ "i", "you", "he", "she", "it", "we", "they",
29
+ "me", "him", "her", "us", "them",
30
+ "myself", "yourself", "himself", "herself", "itself", "ourselves", "themselves",
31
+
32
+ // PRONOUNS - Possessive
33
+ "my", "your", "his", "her", "its", "our", "their",
34
+ "mine", "yours", "hers", "ours", "theirs",
35
+
36
+ // PRONOUNS - Demonstrative
37
+ "this", "that", "these", "those",
38
+
39
+ // PRONOUNS - Relative
40
+ "who", "whom", "whose", "which",
41
+
42
+ // PRONOUNS - Indefinite
43
+ "someone", "somebody", "something", "anyone", "anybody", "anything",
44
+ "everyone", "everybody", "everything", "no one", "nobody", "nothing",
45
+ "one", "ones",
46
+
47
+ // AUXILIARY/MODAL VERBS
48
+ "am", "is", "are", "was", "were", "be", "been", "being",
49
+ "have", "has", "had", "having",
50
+ "do", "does", "did", "doing", "done",
51
+ "can", "could", "will", "would", "shall", "should", "may", "might", "must",
52
+
53
+ // CONJUNCTIONS
54
+ "and", "or", "but", "nor", "so", "yet",
55
+ "if", "then", "else", "whether", "unless", "although", "though",
56
+ "because", "while", "whereas", "whenever", "wherever",
57
+
58
+ // QUESTION WORDS
59
+ "what", "when", "where", "why", "how",
60
+
61
+ // ADVERBS OF PLACE/TIME
62
+ "here", "there", "now", "always", "never", "often", "sometimes",
63
+ "already", "still", "soon", "later", "ago", "today", "tomorrow",
64
+ "yesterday", "currently", "previously", "recently", "immediately",
65
+ "finally", "eventually", "meanwhile", "afterwards",
66
+
67
+ // NEGATION
68
+ "no", "not", "none", "neither",
69
+ "don", "doesn", "didn", "won", "wouldn", "couldn", "shouldn",
70
+ "isn", "aren", "wasn", "weren", "hasn", "haven", "hadn",
71
+
72
+ // QUANTIFIERS
73
+ "some", "any", "all", "each", "every", "both", "few", "more", "most",
74
+ "many", "much", "several", "other", "another", "enough", "less", "least",
75
+ "either", "such",
76
+
77
+ // FILLER/HEDGE WORDS
78
+ "just", "also", "only", "really", "actually", "basically", "simply",
79
+ "very", "quite", "rather", "pretty", "somewhat", "almost", "nearly",
80
+ "exactly", "completely", "entirely", "totally", "absolutely",
81
+ "probably", "possibly", "maybe", "perhaps", "definitely", "certainly",
82
+ "apparently", "obviously", "clearly", "literally", "essentially",
83
+
84
+ // SPEECH-TO-TEXT FILLERS (STT artifacts from voice input)
85
+ "um", "uh", "ah", "oh", "hmm", "hm", "er", "eh", "huh",
86
+ "hey", "hi", "hello", "yeah", "yep", "yup", "nah", "nope",
87
+ "gonna", "gotta", "wanna", "kinda", "sorta",
88
+ "stuff", "anyway", "anyways", "alright", "right", "well",
89
+
90
+ // COMMON REQUEST PHRASES
91
+ "want", "need", "help", "please", "like", "let", "get",
92
+ "think", "know", "see", "try", "make", "give", "take",
93
+ "look", "looking", "trying", "going", "getting", "making",
94
+
95
+ // COMMON NON-ACTION VERBS
96
+ "go", "come", "put", "say", "tell", "ask", "find", "keep",
97
+ "seem", "appear", "become", "remain", "stay", "feel", "show", "mean",
98
+ "include", "provide", "require", "allow", "expect", "cause",
99
+ "follow", "consider", "continue", "start", "begin", "end",
100
+ "contain", "contains",
101
+
102
+ // LINKING/TRANSITION WORDS
103
+ "however", "therefore", "thus", "hence", "otherwise", "instead",
104
+ "moreover", "furthermore", "nevertheless", "nonetheless", "accordingly",
105
+ "consequently", "similarly", "likewise", "conversely", "alternatively",
106
+
107
+ // FILE EXTENSIONS
108
+ "py", "md", "ts", "json", "js", "yaml", "toml", "exe", "bat",
109
+
110
+ // COMMON CODING TERMS
111
+ "using", "used", "uses",
112
+ "based", "following",
113
+ "same", "different", "specific", "existing", "new", "current", "first",
114
+ "full", "complete", "single", "multiple", "simple",
115
+ "needed", "required", "provided", "expected", "correctly",
116
+ "works", "working", "work",
117
+
118
+ // STRUCTURAL WORDS
119
+ "step", "steps", "phase", "below",
120
+
121
+ // QUERY LANGUAGE
122
+ "questions", "question", "clarification",
123
+
124
+ // OVERLY GENERIC TERMS
125
+ "thing", "things", "way", "ways", "kind", "type", "types",
126
+ "example", "examples", "case", "cases",
127
+ "part", "parts", "point", "points",
128
+ "time", "times", "next", "last",
129
+ "set", "list", "group", "item", "items",
130
+
131
+ // PROGRAMMING KEYWORDS
132
+ "self", "def", "return", "import", "true", "false", "none", "str",
133
+ "const", "async", "class", "assert", "except", "dict", "len", "args",
134
+ "sys", "eprint", "elif", "lambda", "yield", "pass",
135
+
136
+ // GENERIC ADJECTIVES
137
+ "high", "low", "important", "critical", "optional", "manual",
138
+ "real", "empty", "stable", "active", "proper", "correct",
139
+ "basic", "main", "primary", "secondary", "general", "overall",
140
+
141
+ // GENERIC TECHNICAL NOUNS
142
+ "information", "format", "status", "method", "purpose", "result",
143
+ "source", "value", "option", "options", "feature", "features", "issue",
144
+ "process", "version", "mode", "state",
145
+
146
+ // DOCUMENT/CODE STRUCTURE
147
+ "section", "lines", "line", "folder", "directory", "index",
148
+ "level", "block", "chunk", "region", "header", "footer",
149
+
150
+ // FRAGMENT WORDS
151
+ "re", "pl", "aiw", "ve", "ll", "doesn", "t", "s",
152
+
153
+ // CONTRACTED FORMS
154
+ "im", "ive", "id", "ill", "youre", "youve", "youll",
155
+ "hes", "shes", "weve", "theyre", "theyve", "dont", "doesnt",
156
+ "didnt", "wont", "wouldnt", "cant", "couldnt", "shouldnt", "isnt",
157
+ "arent", "wasnt", "werent", "hasnt", "havent", "hadnt", "lets",
158
+ "thats", "whats", "heres", "theres", "whos",
159
+
160
+ // SHORT NOISE
161
+ "etc", "up", "as", "cc",
162
+
163
+ // NUMBER WORDS
164
+ "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten",
165
+
166
+ // SINGLE LETTERS
167
+ "b", "c", "d", "e", "f", "g", "h", "j", "k", "l", "m", "n", "o", "p",
168
+ "q", "r", "u", "v", "w", "x", "y", "z",
169
+
170
+ // SHORT FILLER
171
+ "too", "yes", "ok", "okay",
172
+ ]);
173
+
174
+ /**
175
+ * Filter stop words from text.
176
+ * Splits on whitespace, removes words in STOP_WORDS set and single-char words.
177
+ * See SPEC.md §6.4
178
+ */
179
+ export function filterStopWords(text: string): string {
180
+ return text
181
+ .split(/\s+/)
182
+ .filter((word) => word.length > 1 && !STOP_WORDS.has(word.toLowerCase()))
183
+ .join(" ");
184
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Subprocess environment utilities.
3
+ * See SPEC.md §5.10
4
+ */
5
+
6
+ /**
7
+ * Check if this is an internal subprocess call.
8
+ * All hooks should check this and return early to prevent recursion.
9
+ */
10
+ export function isInternalCall(): boolean {
11
+ return process.env.AIWCLI_INTERNAL_CALL === "true";
12
+ }
13
+
14
+ /**
15
+ * Get environment for internal subprocess calls.
16
+ * Returns a copy of process.env with AIWCLI_INTERNAL_CALL=true.
17
+ */
18
+ export function getInternalSubprocessEnv(): Record<string, string | undefined> {
19
+ return {
20
+ ...process.env,
21
+ AIWCLI_INTERNAL_CALL: "true",
22
+ };
23
+ }