fauxnix-cli 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/registry.js CHANGED
@@ -154,6 +154,92 @@ export function parseWords(args, shortValues = [], longValues = []) {
154
154
  return { flags, longs, values, missingValue, operandWords };
155
155
  }
156
156
  const specs = new Map();
157
+ /**
158
+ * C-5's curated agent-daily command set. Keep this explicit: a raw count of
159
+ * CommandSpecs is not enough to prove that the commands agents use every day
160
+ * are the ones protected by fail-loud option validation.
161
+ */
162
+ export const AGENT_DAILY_60 = [
163
+ 'basename',
164
+ 'cat',
165
+ 'cd',
166
+ 'chmod',
167
+ 'chown',
168
+ 'clear',
169
+ 'command',
170
+ 'cp',
171
+ 'cut',
172
+ 'date',
173
+ 'df',
174
+ 'diff',
175
+ 'dirname',
176
+ 'du',
177
+ 'echo',
178
+ 'env',
179
+ 'export',
180
+ 'file',
181
+ 'free',
182
+ 'grep',
183
+ 'groups',
184
+ 'gunzip',
185
+ 'gzip',
186
+ 'head',
187
+ 'hostname',
188
+ 'id',
189
+ 'll',
190
+ 'ln',
191
+ 'ls',
192
+ 'mkdir',
193
+ 'mktemp',
194
+ 'mv',
195
+ 'nproc',
196
+ 'printenv',
197
+ 'printf',
198
+ 'ps',
199
+ 'pwd',
200
+ 'readlink',
201
+ 'realpath',
202
+ 'rm',
203
+ 'rmdir',
204
+ 'sleep',
205
+ 'sort',
206
+ 'stat',
207
+ 'tail',
208
+ 'tee',
209
+ 'timeout',
210
+ 'touch',
211
+ 'tr',
212
+ 'type',
213
+ 'uname',
214
+ 'uniq',
215
+ 'unset',
216
+ 'unzip',
217
+ 'uptime',
218
+ 'wc',
219
+ 'which',
220
+ 'whoami',
221
+ 'zcat',
222
+ 'zip',
223
+ ];
224
+ /** Commands deliberately kept outside generic CommandSpec option walking. */
225
+ export const COMMAND_SPEC_EXCLUSIONS = [
226
+ {
227
+ names: ['find'],
228
+ reason: 'option-looking predicates are parsed by the find expression compiler; generic short-option bundling would misread -name',
229
+ },
230
+ {
231
+ names: ['sed', 'awk'],
232
+ reason: 'program text and option grammar require command-specific parsing; any remaining unchecked options must be fixed there rather than treated as generic flags',
233
+ },
234
+ {
235
+ names: ['egrep'],
236
+ reason: 'semantic alias injects grep -E through its own handler; it must not be wrapped as an independent generic option parser',
237
+ },
238
+ {
239
+ names: ['tar'],
240
+ reason: 'argv is passed to Windows bsdtar; rejecting unlisted GNU/bsdtar options before native dispatch would reduce compatibility',
241
+ },
242
+ ];
157
243
  /** Register a spec'd command. Unknown/unsupported options become GNU-style usage errors. */
158
244
  export function registerSpec(spec) {
159
245
  for (const name of spec.names) {
@@ -188,11 +274,30 @@ export function registeredSpecs() {
188
274
  }
189
275
  /** Markdown dump of every CommandSpec — source for docs/command-specs.md. */
190
276
  export function specsMarkdown() {
277
+ const dailySpecd = AGENT_DAILY_60.filter((name) => lookupSpec(name));
278
+ const dailyMissing = AGENT_DAILY_60.filter((name) => !lookupSpec(name));
191
279
  const lines = [
192
280
  '# Command specs',
193
281
  '',
194
282
  'Generated from `CommandSpec`. Unlisted commands still use unchecked `parseWords` (unknown flags ignored). Spec\'d commands fail loud on unknown or unsupported options.',
195
283
  '',
284
+ '## Agent-daily 60 (C-5)',
285
+ '',
286
+ 'Curated command names: ' + AGENT_DAILY_60.map((name) => '`' + name + '`').join(', '),
287
+ '',
288
+ 'Coverage: **' + dailySpecd.length + ' / ' + AGENT_DAILY_60.length + ' spec\'d**.',
289
+ '',
290
+ ...(dailyMissing.length
291
+ ? ['Missing specs: ' + dailyMissing.map((name) => '`' + name + '`').join(', '), '']
292
+ : []),
293
+ '## Intentional CommandSpec exclusions',
294
+ '',
295
+ 'These commands stay outside the generic option walker by design. This is a structural rationale, not a claim that every command-specific option path is already strict.',
296
+ '',
297
+ '| Command | Rationale |',
298
+ '| --- | --- |',
299
+ ...COMMAND_SPEC_EXCLUSIONS.map((entry) => '| ' + entry.names.map((name) => '`' + name + '`').join(', ') + ' | ' + entry.reason + ' |'),
300
+ '',
196
301
  ];
197
302
  for (const spec of registeredSpecs()) {
198
303
  lines.push('## `' + spec.names.join('` / `') + '`');
@@ -296,7 +401,10 @@ export function specOptionError(spec, args, cmdName) {
296
401
  i++;
297
402
  continue;
298
403
  }
299
- if (t.startsWith('-') && t.length > 1 && !/^-?\d/.test(t.slice(1, 2))) {
404
+ const firstShort = t.slice(1, 2);
405
+ if (t.startsWith('-') &&
406
+ t.length > 1 &&
407
+ (!/^\d$/.test(firstShort) || shorts.has(firstShort))) {
300
408
  const body = t.slice(1);
301
409
  for (let c = 0; c < body.length; c++) {
302
410
  const ch = body[c];
@@ -1,5 +1,12 @@
1
1
  import { Assignment, CommandList, Redirect, SimpleCommand, IfCommand, ForCommand, WhileCommand, CaseCommand, Word, WordPart } from './ast.js';
2
2
  import { PipelineCtx } from './registry.js';
3
+ export interface TranslationContext {
4
+ /** `pure` renders a script without consulting command operands on disk. */
5
+ mode: 'execute' | 'pure';
6
+ }
7
+ export declare const EXECUTE_TRANSLATION: TranslationContext;
8
+ export declare const PURE_TRANSLATION: TranslationContext;
9
+ export declare const PURE_SED_FILE_MESSAGE = "fauxnix: translate does not read sed script files; use -e with the script text, or run the command to use -f";
3
10
  /** `${name:-word}` and friends using case-exact fx-scalar0. */
4
11
  export declare function paramExpr(name: string, op: ':-' | ':=' | ':+' | ':?' | '-' | '+' | '?', word: string): string;
5
12
  export declare function varExtraOf(p: WordPart): {
@@ -80,8 +87,8 @@ export declare function argListExpr(words: Word[], fn?: (w: Word) => string): st
80
87
  * Lists (`;` `&&` `||`) reuse translateListInline inside the fx-csub
81
88
  * scriptblock so the newline contract is unchanged.
82
89
  */
83
- export declare function translateCmdSub(cmdText: string, keepNl?: boolean): string;
84
- export declare function translateSimple(cmd: SimpleCommand, position: PipelineCtx['position'], hasStdin: boolean): string;
90
+ export declare function translateCmdSub(cmdText: string, keepNl?: boolean, translation?: TranslationContext): string;
91
+ export declare function translateSimple(cmd: SimpleCommand, position: PipelineCtx['position'], hasStdin: boolean, translation?: TranslationContext): string;
85
92
  /** PS expr: encode a string so SETVALS records can stay newline-delimited. */
86
93
  export declare function encodeSetValExpr(srcExpr: string): string;
87
94
  /**
@@ -103,10 +110,10 @@ export interface PipelineParts {
103
110
  }
104
111
  export declare function translatePipelineBody(p: {
105
112
  commands: Array<SimpleCommand | IfCommand | ForCommand | WhileCommand | CaseCommand>;
106
- }): PipelineParts;
113
+ }, translation?: TranslationContext): PipelineParts;
107
114
  export interface SegmentPlan {
108
115
  op: ';' | '&&' | '||';
109
- /** Spawn-mode wrapScript (CLI/MCP `translate`, one-shot powershell.exe). */
116
+ /** Spawn-mode wrapScript (`translate` output for a one-shot PowerShell process). */
110
117
  script: string;
111
118
  /** Pipeline body before wrapScript — executor host mode re-wraps this. */
112
119
  body: string;
@@ -117,7 +124,7 @@ export interface SegmentPlan {
117
124
  /** First-stage `<` only — FAUXNIX_STDIN_FILE feed. */
118
125
  stdinRedirects: Redirect[];
119
126
  }
120
- export declare function translateCommandList(list: CommandList): SegmentPlan[];
127
+ export declare function translateCommandList(list: CommandList, translation?: TranslationContext): SegmentPlan[];
121
128
  export type WrapMode = 'spawn' | 'host';
122
129
  export interface WrapScriptOptions {
123
130
  /** spawn (default): one-shot process, `exit` at the end. host: no `exit`, no helper re-emit. */
@@ -132,6 +139,6 @@ export interface WrapScriptOptions {
132
139
  export declare function wrapScript(body: string, opts?: WrapScriptOptions): string;
133
140
  /**
134
141
  * Resident-host bootstrap: encoding + full fx-* catalog + JSON-line RPC loop.
135
- * Loaded once via `powershell.exe -File`. Must never `exit` a successful frame.
142
+ * Loaded once via the selected PowerShell's `-File`. Must never `exit` a successful frame.
136
143
  */
137
144
  export declare function hostBootstrapScript(): string;