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:
@@ -230,16 +230,9 @@ export function commanderClaudeMd(params: CommanderClaudeMdParams): string {
|
||||
'those live here, in your own directory. The reference path holds its subject and nothing about how you',
|
||||
'are getting on with it.',
|
||||
'',
|
||||
'Everything an action produces goes in THIS directory, by default and without discussion. Make a',
|
||||
'directory here for it — the layout below — and put the results there. Anywhere else is a dispatch',
|
||||
'decision, made later and only because the owner asked for it. Do not raise it on the first turn.',
|
||||
'',
|
||||
'**That holds even when the action itself writes somewhere else.** A platform task decides where it',
|
||||
'puts its own output, and a task built for a person clicking a file will often leave the result beside',
|
||||
'that file. That is right for the person and wrong for you: it puts your work in the middle of the',
|
||||
'thing you are watching, where the owner did not ask for it and where your next pass has to tell your',
|
||||
'own output apart from your subject. When an action leaves its result outside this directory, MOVE it',
|
||||
'here. Every time, without asking.',
|
||||
'Everything an action produces goes in THIS directory, under `classification/`. Never into the path you',
|
||||
'watch — that holds its subject, not your work. Getting the result there is your problem to solve with',
|
||||
'whatever ran the action; where it ends up is not negotiable.',
|
||||
'',
|
||||
'**A spawned agent follows a FILE, not a prompt.** Put the rules in `procedures/<something>.md` here and',
|
||||
'point the agent at it. When the rule changes you edit one document; a prompt baked into a loop is a',
|
||||
|
||||
+3
-1
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user