the commander is told the rule, not the API

three sentences where there were fourteen. everything an action produces
goes in this directory under classification/, never into the path being
watched, and getting it there is the commander's problem to solve with
whatever ran the action.

what came out was me teaching it the transcription API — read the task's
inputs, here is the endpoint that lists them, pass a destination. that is
one task's detail in a file every commander reads, and the commander can
discover it. the rule is the part only this file can state.

the task half stays and is real: transcribe-audio-file takes an optional
output_dir now, marked `hidden` so the file browser neither renders it nor
counts it as something to ask a person about. without that, declaring it
would have turned the direct right-click run back into a modal with a
field nobody clicking a file has an answer for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
This commit is contained in:
2026-08-25 04:59:06 +00:00
co-authored by Claude Opus 5
parent 2c0e23d4fb
commit af41144689
4 changed files with 26 additions and 12 deletions
@@ -279,6 +279,8 @@ export type TaskInputDef = {
default?: string;
options?: string[];
autofill?: string;
/** For a caller with no browser — never rendered, never asked about. See `useTasks.ts`. */
hidden?: boolean;
};
type TaskInputFormProps = {
@@ -332,7 +334,7 @@ export const TaskInputForm = ({
hideTrackPickers,
}: TaskInputFormProps) => {
const { t } = useTranslation();
const configurableInputs = Object.entries(inputDefs).filter(([key]) => !autoFilledKeys.has(key));
const configurableInputs = Object.entries(inputDefs).filter(([key, def]) => !autoFilledKeys.has(key) && !def.hidden);
if (configurableInputs.length === 0) return null;
return (
@@ -104,3 +104,14 @@ test('agentic and pipeline always take the modal', () => {
expect(runsWithoutPrompting(scriptTask({ mode: 'agentic' }))).toBe(false);
expect(runsWithoutPrompting(scriptTask({ mode: 'pipeline' }))).toBe(false);
});
// An input that exists for a caller with no browser — a commander passing its own output directory.
// Declaring one must not turn a direct right-click run back into a modal with a field nobody clicking a
// file has an answer for.
test('a hidden input is not something to ask a person about', () => {
expect(
runsWithoutPrompting(
scriptTask({ inputs: { file_path: { required: true }, output_dir: { required: false, hidden: true } } }),
),
).toBe(true);
});
@@ -11,6 +11,14 @@ export type TaskInputSpec = {
autofill?: string;
required?: boolean;
options?: unknown;
/**
* Not for a person. An input that exists for callers with no browser — a commander passing its own
* output directory — and that the file browser must neither show nor count as something to ask about.
*
* Without this, declaring one turns a direct right-click run back into a modal with a field nobody
* clicking a file has an answer for.
*/
hidden?: boolean;
};
export type TaskSummary = {
@@ -55,7 +63,7 @@ export type TaskSummary = {
const BROWSER_AUTOFILL = new Set(['entry_name', 'entry_path']);
const isFilledByBrowser = (key: string, spec: TaskInputSpec): boolean =>
key === 'file_path' || (!!spec.autofill && BROWSER_AUTOFILL.has(spec.autofill));
spec.hidden === true || key === 'file_path' || (!!spec.autofill && BROWSER_AUTOFILL.has(spec.autofill));
export const runsWithoutPrompting = (task: TaskSummary): boolean => {
if (task.mode !== 'script') return false;