taskchef 7.27.1 → 7.28.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskchef",
3
- "version": "7.27.1",
3
+ "version": "7.28.0",
4
4
  "description": "Dispatch work from a data-only workspace to visible Codex project tasks.",
5
5
  "author": {
6
6
  "name": "Favo Yang",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskchef",
3
- "version": "7.27.1",
3
+ "version": "7.28.0",
4
4
  "description": "A non-blocking interactive dispatcher for visible Codex tasks.",
5
5
  "license": "MIT",
6
6
  "author": "Favo Yang",
@@ -37,6 +37,7 @@
37
37
  "docs/images/reported-work-duration-mobile.jpg",
38
38
  "index.js",
39
39
  "mcp",
40
+ "scripts/roles",
40
41
  "scripts/benchmark-dispatch-prepare.js",
41
42
  "scripts/e2e-benchmark.js",
42
43
  "src",
@@ -0,0 +1,172 @@
1
+ #!/usr/bin/env python3
2
+ """Read native Codex agent preferences without applying their instruction layers.
3
+
4
+ Requires Python 3.11+. Standalone, standard library only. TaskChef packages an
5
+ identical copy; neither installation imports the other at runtime.
6
+ """
7
+ import argparse
8
+ import json
9
+ import os
10
+ from pathlib import Path
11
+ import sys
12
+ import tomllib
13
+
14
+ ROLES = ('planner', 'implementer', 'reviewer')
15
+ EFFORTS = ('none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max', 'ultra')
16
+
17
+
18
+ def read_layer(directory):
19
+ found = {}
20
+ problems = []
21
+ try:
22
+ with os.scandir(directory) as entries:
23
+ files = sorted(Path(entry.path) for entry in entries if entry.name.endswith('.toml'))
24
+ for file in files:
25
+ try:
26
+ if file.stat().st_size > 65536:
27
+ raise ValueError('profile exceeds 64 KiB')
28
+ with file.open('rb') as stream:
29
+ data = tomllib.load(stream)
30
+ name = data.get('name')
31
+ if name not in ROLES:
32
+ if file.stem in ROLES:
33
+ raise ValueError('name must match the role filename')
34
+ continue
35
+ errors = []
36
+ for field in ('description', 'developer_instructions'):
37
+ if not isinstance(data.get(field), str) or not data[field].strip():
38
+ errors.append(f'{field} must be a nonempty string')
39
+ model = data.get('model')
40
+ effort = data.get('model_reasoning_effort')
41
+ entry = {'source': str(file), 'model': model, 'effort': effort, 'problems': errors}
42
+ if name in found:
43
+ entry['problems'].append('duplicate role name in the same directory')
44
+ found[name] = entry
45
+ except (OSError, ValueError) as error:
46
+ # Do not expose TOML lines, which can contain unrelated private data.
47
+ message = f'{file}: unreadable or malformed agent TOML ({type(error).__name__})'
48
+ problems.append(message)
49
+ if file.stem in ROLES:
50
+ found[file.stem] = {'source': str(file), 'model': None, 'effort': None, 'problems': [message]}
51
+ except FileNotFoundError:
52
+ return found, problems
53
+ except OSError:
54
+ message = f'{directory}: cannot read agent directory'
55
+ problems.append(message)
56
+ found = {role: {'source': str(directory), 'model': None, 'effort': None, 'problems': [message]} for role in ROLES}
57
+ return found, problems
58
+
59
+
60
+ def resolve(project=None, codex_home=None, explicit_model=None, explicit_effort=None):
61
+ home = Path(codex_home or os.environ.get('CODEX_HOME') or Path.home() / '.codex').expanduser().resolve()
62
+ personal, problems = read_layer(home / 'agents')
63
+ local, local_problems = read_layer(Path(project).resolve() / '.codex' / 'agents') if project else ({}, [])
64
+ problems += local_problems
65
+ catalog = None
66
+ catalog_source = str(home / 'models_cache.json')
67
+ try:
68
+ cache = json.loads(Path(catalog_source).read_text())
69
+ if not isinstance(cache, dict) or not isinstance(cache.get('models'), list):
70
+ raise ValueError('invalid catalog')
71
+ for model in cache['models']:
72
+ if not isinstance(model, dict) or not isinstance(model.get('slug'), str):
73
+ raise ValueError('invalid model entry')
74
+ levels = model.get('supported_reasoning_levels')
75
+ if not isinstance(levels, list) or any(not isinstance(level, dict) or not isinstance(level.get('effort'), str) for level in levels):
76
+ raise ValueError('invalid effort catalog')
77
+ catalog = {model['slug']: model for model in cache['models']}
78
+ except FileNotFoundError:
79
+ pass
80
+ except (OSError, ValueError, KeyError, TypeError):
81
+ problems.append('Local Codex model catalog is unreadable or malformed; validate availability with the current native tool.')
82
+ results = []
83
+ for role in ROLES:
84
+ entry = local.get(role, personal.get(role))
85
+ source = entry['source'] if entry else None
86
+ model = entry['model'] if entry else None
87
+ effort = entry['effort'] if entry else None
88
+ errors = list(entry['problems']) if entry else []
89
+ if explicit_model is not None:
90
+ model, effort = explicit_model, explicit_effort
91
+ effective_source = 'explicit user model choice'
92
+ errors = []
93
+ else:
94
+ effective_source = source
95
+ if explicit_effort is not None:
96
+ effort = explicit_effort
97
+ if model is not None and (not isinstance(model, str) or not model.strip() or len(model) > 256):
98
+ errors.append('model must be a nonempty string of at most 256 characters')
99
+ if effort is not None and effort not in EFFORTS:
100
+ errors.append('reasoning effort is unsupported')
101
+ status = 'invalid' if errors else 'configured' if (model is not None or effort is not None) else 'missing'
102
+ availability = 'not checked; native tool must validate before dispatch'
103
+ if model and not errors and catalog is not None:
104
+ if model not in catalog:
105
+ errors.append('model absent from local Codex catalog; confirm against the current native tool before dispatch')
106
+ status = 'unavailable'
107
+ else:
108
+ supported = [v.get('effort') for v in catalog[model].get('supported_reasoning_levels', []) if isinstance(v, dict)]
109
+ if effort and effort not in supported:
110
+ errors.append('effort absent from local model catalog; confirm against the current native tool')
111
+ status = 'unavailable'
112
+ availability = 'present in cached catalog; current native tool is authoritative'
113
+ overrides = {}
114
+ if status == 'configured':
115
+ if model is not None:
116
+ overrides['model'] = model
117
+ if effort is not None:
118
+ overrides['thinking'] = effort
119
+ results.append({'role': role, 'source': source, 'effectiveSource': effective_source,
120
+ 'model': model, 'effort': effort, 'status': status,
121
+ 'availability': availability, 'problems': errors,
122
+ 'taskOverrides': overrides,
123
+ 'subagentOverrides': {('reasoning_effort' if k == 'thinking' else k): v for k, v in overrides.items()},
124
+ 'fallback': 'inherit parent settings' if role == 'reviewer' else 'native new-task default (not guaranteed dispatcher inheritance)'})
125
+ return {'roles': results, 'problems': problems, 'catalogSource': catalog_source if catalog is not None else None,
126
+ 'precedence': 'explicit user model (and its explicit effort) > project role > personal role > native defaults; explicit effort alone overrides role effort',
127
+ 'scope': 'Model and effort only; agent instructions, tools, permissions, and other TOML keys are not applied by this adapter.'}
128
+
129
+
130
+ def setup(role, model, effort, codex_home=None):
131
+ home = Path(codex_home or os.environ.get('CODEX_HOME') or Path.home() / '.codex').expanduser().resolve()
132
+ existing, problems = read_layer(home / 'agents')
133
+ if role in existing or problems:
134
+ return {'created': False, 'role': role, 'problems': problems or ['existing role preserved'], 'source': existing.get(role, {}).get('source')}
135
+ if not model.strip() or len(model) > 256 or effort not in EFFORTS:
136
+ raise ValueError('invalid model or effort')
137
+ directory = home / 'agents'
138
+ directory.mkdir(parents=True, exist_ok=True)
139
+ target = directory / f'{role}.toml'
140
+ data = {'name': role, 'description': f'{role.capitalize()} model preferences',
141
+ 'developer_instructions': f'Perform the assigned {role} work within the user\'s requested scope.',
142
+ 'model': model, 'model_reasoning_effort': effort}
143
+ try:
144
+ with target.open('x') as stream:
145
+ stream.write(''.join(f'{key} = {json.dumps(value)}\n' for key, value in data.items()))
146
+ except FileExistsError:
147
+ return {'created': False, 'role': role, 'source': str(target), 'problems': ['existing file preserved']}
148
+ return {'created': True, 'role': role, 'source': str(target), 'model': model, 'effort': effort}
149
+
150
+
151
+ def main():
152
+ parser = argparse.ArgumentParser(description=__doc__)
153
+ parser.add_argument('--project')
154
+ parser.add_argument('--codex-home')
155
+ parser.add_argument('--role', choices=ROLES)
156
+ parser.add_argument('--model')
157
+ parser.add_argument('--effort')
158
+ parser.add_argument('--setup', action='store_true')
159
+ args = parser.parse_args()
160
+ if args.setup:
161
+ if not (args.role and args.model and args.effort):
162
+ parser.error('--setup requires --role, --model, and --effort')
163
+ result = setup(args.role, args.model, args.effort, args.codex_home)
164
+ else:
165
+ result = resolve(args.project, args.codex_home, args.model, args.effort)
166
+ if args.role:
167
+ result['roles'] = [r for r in result['roles'] if r['role'] == args.role]
168
+ print(json.dumps(result, indent=2))
169
+
170
+
171
+ if __name__ == '__main__':
172
+ main()
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: taskchef-bootstrap
3
- description: "Initialize, diagnose, or refresh TaskChef dispatcher workspaces, the Codex project index, task history, and managed AGENTS.md instructions. Use when creating a TaskChef workspace, indexing or reindexing Codex projects, importing, listing, or removing indexed projects, running TaskChef doctor, or repairing dispatcher setup. Do not dispatch user work or report on executor threads."
3
+ description: "Initialize or repair the TaskChef dispatcher workspace and manage its local Codex project index. Use for setup, doctor, import, or reindex requests; not dispatch or executor reporting."
4
4
  ---
5
5
 
6
6
  # TaskChef Bootstrap
@@ -50,118 +50,35 @@ all deterministic workspace operations.
50
50
  End without dispatching unless the user
51
51
  separately requested work.
52
52
 
53
- ## Index Codex projects
53
+ ## Project index operations
54
54
 
55
- TaskChef's project index is the local list of Codex projects available for
56
- delegation. It stores canonical paths and routing metadata such as curated
57
- names, descriptions, Git status, and GitHub repositories. It does not index
58
- repository contents or create a second kind of project.
55
+ For adding, importing, removing, listing, or reindexing projects, read
56
+ [project index](references/project-index.md). Preserve exact canonical local
57
+ Codex project identity and existing curated entries; opening a folder is not
58
+ proof of registration. Completion requires verifying the intended index entry.
59
59
 
60
- Index only Codex projects local to the TaskChef workspace's execution host.
61
- Remote connection projects are outside the v1 contract. Never index the
62
- TaskChef dispatcher workspace or a directory containing it; the dispatcher is
63
- the inbox, while indexed Codex projects own delegated work.
60
+ ## Optional model roles
64
61
 
65
- ### Existing Codex project
62
+ Offer planner, implementer, and reviewer profiles during setup. Model and effort
63
+ preferences belong in user configuration, never defaults hard-coded in skills.
64
+ If the user provides values, configure them without asking again. Otherwise
65
+ explain the optional profiles and retain native defaults until values are chosen.
66
66
 
67
- 1. List native local Codex projects once. Resolve the requested existing folder
68
- with `realpath` and require an exact canonical-path match in that list. A
69
- similar name, a parent or child directory, and a remote connection project
70
- are not matches.
71
- 2. Index the exact path with the existing `project add <canonical-path> --name
72
- <curated-name> --description <curated-description> --json` CLI workflow.
73
- Despite the command's historical `add` name, this writes one TaskChef index
74
- entry for an existing Codex project. The CLI detects Git status, the exact
75
- Git root, and a canonical GitHub `origin` when no repository option is
76
- supplied. Repeated `--github-repo <canonical-url>` arguments replace that
77
- detection and form the complete advertised repository list, so repeat the
78
- origin explicitly when it should remain routable. Use `--no-github` when the
79
- user intentionally wants an empty list.
80
- 3. Run `project list --json` and require one indexed entry with the exact
81
- canonical path and intended routing metadata. Only then report that the
82
- Codex project is ready for delegation through TaskChef.
67
+ Run `python3 <plugin-root>/scripts/roles/resolve_roles.py` to preview personal
68
+ roles. Python 3.11+ is required for this optional helper. Create each requested
69
+ missing profile with:
83
70
 
84
- ### New or not-yet-saved Codex folder
85
-
86
- 1. Create the folder only when the user explicitly asked to create it. Preserve
87
- unrelated existing contents. Do not initialize Git unless requested or
88
- clearly required by the user's broader task. Resolve the resulting existing
89
- folder with `realpath`.
90
- 2. Register or open that exact canonical folder with the supported
91
- `<validated-codex-cli> app <canonical-path>` mechanism. Reuse a validated CLI
92
- path supplied by the current Codex Desktop environment when available. Use
93
- the same resolver contract as `workspace init --register-codex` otherwise:
94
- an explicit `--codex-cli` path takes precedence over `TASKCHEF_CODEX_CLI`;
95
- each must resolve to an executable that passes `app --help`. Without an
96
- override, inspect `codex` executables from `PATH`, prefer a validated
97
- candidate whose path contains `Contents/Resources`, and otherwise validate
98
- only the first executable `codex` in PATH order. Never assume an arbitrary
99
- shell `codex`, invoke `codex add`, or hard-code an application bundle path.
100
- 3. Re-list native local Codex projects and require an exact canonical-path
101
- match. Opening is a request, not proof that Codex saved the project. If the
102
- exact match is absent, report that the folder was opened or registration was
103
- requested but Codex registration remains unverified; do not index it in
104
- TaskChef or call it delegation-ready.
105
- 4. After Codex verification, index the project as in the existing-project path.
106
- Run `project list --json` and verify the exact TaskChef index entry. Report
107
- delegation readiness only after both the native Codex match and TaskChef
108
- indexing are verified.
109
-
110
- For a managed `*-workspace` Codex project, advertise every relevant child or
111
- subrepository with repeated `--github-repo <canonical-github-url>` arguments,
112
- including the workspace repository itself when it can own issue or pull-request
113
- links. These explicit values are the complete list; automatic origin detection
114
- does not supplement them. This lets TaskChef route each canonical GitHub URL to
115
- the correct workspace rather than guessing from the folder name.
116
-
117
- ### Reindex after Codex changes
118
-
119
- When the user asks TaskChef to reindex or catch up after saving more projects in
120
- Codex, list native local Codex projects once and run `project list --json` once
121
- before mutation. Compare exact canonical paths, then index each requested
122
- eligible Codex project that is missing from TaskChef by following the
123
- appropriate path above, sharing the batch verification instead of relisting
124
- after each write. After all additions, run `project list --json` once more and
125
- verify every intended canonical path and its routing metadata before reporting
126
- the index as current.
127
-
128
- Do not call `project add` for a path already in the TaskChef index; it rejects
129
- duplicate paths and must not be presented as a metadata refresh. Preserve
130
- existing curated entries, and do not remove entries merely because they are
131
- absent from the current Codex list. Refreshing or removing an existing entry
132
- requires an explicit user request and the project-management workflows below.
133
-
134
- ## Manage the project index
135
-
136
- 1. Bulk import with `project import <file|-> --json`. Input is a JSON array of
137
- objects containing `path` plus optional `name`, `description`, and
138
- `githubRepos`, which is always a JSON array of GitHub repository URLs. Before
139
- importing, list native local Codex projects once, canonicalize every input
140
- path, and require an exact local-project match for every entry. Reject or
141
- report every unmatched path instead of indexing it. Import merges by
142
- canonical path, preserves an existing name or description when omitted, and
143
- unions existing and imported repository lists without duplicates. Use
144
- `--replace` only when the user explicitly requests replacement. Run
145
- `project list --json` afterward and verify every imported entry.
146
- 2. Inspect indexed projects with `project list --json`. Remove by name with
147
- `project remove`. Existing task entries keep their project snapshots.
148
-
149
- Example managed-workspace import entry:
150
-
151
- ```json
152
- {
153
- "name": "skills-workspace",
154
- "path": "/workspace/skills-workspace",
155
- "githubRepos": [
156
- "https://github.com/example/skill-one",
157
- "https://github.com/example/skill-two"
158
- ],
159
- "description": "Manages the listed child skill repositories."
160
- }
71
+ ```sh
72
+ python3 <plugin-root>/scripts/roles/resolve_roles.py --setup --role <role> --model <requested-model> --effort <requested-effort>
161
73
  ```
162
74
 
163
- TaskChef accepts configuration schema version 2 only. Its optional exact
164
- `dashboard` object contains boolean `autostart`; absence means enabled and
165
- `false` opts out of MCP-lifecycle dashboard startup without disabling manual
166
- `$taskchef-dashboard` recovery. `githubRepos` is always an array; unsupported
167
- configuration is rejected without being rewritten.
75
+ This authorized role setup may create `$CODEX_HOME/agents/<role>.toml` (default
76
+ `~/.codex/agents/`) outside the dispatcher workspace. Existing definitions,
77
+ including custom filenames, are preserved. Report conflicts and diagnostics;
78
+ never overwrite a custom role. Re-run the preview and check model/effort against
79
+ the available native interface. Missing roles are optional: TaskChef omits
80
+ new-task overrides; reviewers inherit parent settings. Native new-task defaults
81
+ are not guaranteed dispatcher inheritance. Read the delegate's
82
+ [role resolution](../taskchef-delegate/references/model-roles.md) for precedence
83
+ and adapter limits. Open the dashboard's `/#settings` preview to show the
84
+ configured sources, requested effective settings, fallback, and problems.
@@ -0,0 +1,119 @@
1
+ # Project index operations
2
+
3
+ Resolve the plugin root and use its CLI as described in SKILL.md.
4
+
5
+ ## Index Codex projects
6
+
7
+ TaskChef's project index is the local list of Codex projects available for
8
+ delegation. It stores canonical paths and routing metadata such as curated
9
+ names, descriptions, Git status, and GitHub repositories. It does not index
10
+ repository contents or create a second kind of project.
11
+
12
+ Index only Codex projects local to the TaskChef workspace's execution host.
13
+ Remote connection projects are outside the v1 contract. Never index the
14
+ TaskChef dispatcher workspace or a directory containing it; the dispatcher is
15
+ the inbox, while indexed Codex projects own delegated work.
16
+
17
+ ### Existing Codex project
18
+
19
+ 1. List native local Codex projects once. Resolve the requested existing folder
20
+ with `realpath` and require an exact canonical-path match in that list. A
21
+ similar name, a parent or child directory, and a remote connection project
22
+ are not matches.
23
+ 2. Index the exact path with the existing `project add <canonical-path> --name
24
+ <curated-name> --description <curated-description> --json` CLI workflow.
25
+ Despite the command's historical `add` name, this writes one TaskChef index
26
+ entry for an existing Codex project. The CLI detects Git status, the exact
27
+ Git root, and a canonical GitHub `origin` when no repository option is
28
+ supplied. Repeated `--github-repo <canonical-url>` arguments replace that
29
+ detection and form the complete advertised repository list, so repeat the
30
+ origin explicitly when it should remain routable. Use `--no-github` when the
31
+ user intentionally wants an empty list.
32
+ 3. Run `project list --json` and require one indexed entry with the exact
33
+ canonical path and intended routing metadata. Only then report that the
34
+ Codex project is ready for delegation through TaskChef.
35
+
36
+ ### New or not-yet-saved Codex folder
37
+
38
+ 1. Create the folder only when the user explicitly asked to create it. Preserve
39
+ unrelated existing contents. Do not initialize Git unless requested or
40
+ clearly required by the user's broader task. Resolve the resulting existing
41
+ folder with `realpath`.
42
+ 2. Register or open that exact canonical folder with the supported
43
+ `<validated-codex-cli> app <canonical-path>` mechanism. Reuse a validated CLI
44
+ path supplied by the current Codex Desktop environment when available. Use
45
+ the same resolver contract as `workspace init --register-codex` otherwise:
46
+ an explicit `--codex-cli` path takes precedence over `TASKCHEF_CODEX_CLI`;
47
+ each must resolve to an executable that passes `app --help`. Without an
48
+ override, inspect `codex` executables from `PATH`, prefer a validated
49
+ candidate whose path contains `Contents/Resources`, and otherwise validate
50
+ only the first executable `codex` in PATH order. Never assume an arbitrary
51
+ shell `codex`, invoke `codex add`, or hard-code an application bundle path.
52
+ 3. Re-list native local Codex projects and require an exact canonical-path
53
+ match. Opening is a request, not proof that Codex saved the project. If the
54
+ exact match is absent, report that the folder was opened or registration was
55
+ requested but Codex registration remains unverified; do not index it in
56
+ TaskChef or call it delegation-ready.
57
+ 4. After Codex verification, index the project as in the existing-project path.
58
+ Run `project list --json` and verify the exact TaskChef index entry. Report
59
+ delegation readiness only after both the native Codex match and TaskChef
60
+ indexing are verified.
61
+
62
+ For a managed `*-workspace` Codex project, advertise every relevant child or
63
+ subrepository with repeated `--github-repo <canonical-github-url>` arguments,
64
+ including the workspace repository itself when it can own issue or pull-request
65
+ links. These explicit values are the complete list; automatic origin detection
66
+ does not supplement them. This lets TaskChef route each canonical GitHub URL to
67
+ the correct workspace rather than guessing from the folder name.
68
+
69
+ ### Reindex after Codex changes
70
+
71
+ When the user asks TaskChef to reindex or catch up after saving more projects in
72
+ Codex, list native local Codex projects once and run `project list --json` once
73
+ before mutation. Compare exact canonical paths, then index each requested
74
+ eligible Codex project that is missing from TaskChef by following the
75
+ appropriate path above, sharing the batch verification instead of relisting
76
+ after each write. After all additions, run `project list --json` once more and
77
+ verify every intended canonical path and its routing metadata before reporting
78
+ the index as current.
79
+
80
+ Do not call `project add` for a path already in the TaskChef index; it rejects
81
+ duplicate paths and must not be presented as a metadata refresh. Preserve
82
+ existing curated entries, and do not remove entries merely because they are
83
+ absent from the current Codex list. Refreshing or removing an existing entry
84
+ requires an explicit user request and the project-management workflows below.
85
+
86
+ ## Manage the project index
87
+
88
+ 1. Bulk import with `project import <file|-> --json`. Input is a JSON array of
89
+ objects containing `path` plus optional `name`, `description`, and
90
+ `githubRepos`, which is always a JSON array of GitHub repository URLs. Before
91
+ importing, list native local Codex projects once, canonicalize every input
92
+ path, and require an exact local-project match for every entry. Reject or
93
+ report every unmatched path instead of indexing it. Import merges by
94
+ canonical path, preserves an existing name or description when omitted, and
95
+ unions existing and imported repository lists without duplicates. Use
96
+ `--replace` only when the user explicitly requests replacement. Run
97
+ `project list --json` afterward and verify every imported entry.
98
+ 2. Inspect indexed projects with `project list --json`. Remove by name with
99
+ `project remove`. Existing task entries keep their project snapshots.
100
+
101
+ Example managed-workspace import entry:
102
+
103
+ ```json
104
+ {
105
+ "name": "skills-workspace",
106
+ "path": "/workspace/skills-workspace",
107
+ "githubRepos": [
108
+ "https://github.com/example/skill-one",
109
+ "https://github.com/example/skill-two"
110
+ ],
111
+ "description": "Manages the listed child skill repositories."
112
+ }
113
+ ```
114
+
115
+ TaskChef accepts configuration schema version 2 only. Its optional exact
116
+ `dashboard` object contains boolean `autostart`; absence means enabled and
117
+ `false` opts out of MCP-lifecycle dashboard startup without disabling manual
118
+ `$taskchef-dashboard` recovery. `githubRepos` is always an array; unsupported
119
+ configuration is rejected without being rewritten.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: taskchef-copilot
3
- description: "Explain and coordinate TaskChef executor outcomes from cached task briefs. Use when the user asks what finished, what needs attention, why a delegated task failed or needs input, what should happen next, asks to answer, follow up, resume, or continue the same recorded assignment in its existing task, or explicitly invokes the historical $taskchef-report name. The dashboard remains the primary monitoring UI. Use live Codex metadata only for an explicit fresh/live request or a meaningful focused contradiction, and never poll."
3
+ description: "Explain TaskChef outcomes from cached briefs or continue an explicitly selected assignment in its existing task. Handles historical $taskchef-report requests; dashboard monitoring is separate."
4
4
  ---
5
5
 
6
6
  # TaskChef Copilot
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: taskchef-delegate
3
- description: "Dispatch actionable requests through the per-user TaskChef workspace into independently openable Codex project tasks. Use automatically for actionable work received in the canonical TaskChef dispatcher workspace. From any other project, use only when the user explicitly asks to delegate or split separate work into Codex tasks; TaskChef-related subject matter alone is not delegation intent. Record before creation, require executor self-linking, and never wait for executor completion."
3
+ description: "Dispatch work received in the canonical TaskChef workspace into Codex tasks. Elsewhere, use only for explicit delegation of separate work; an existing executor keeps its assignment."
4
4
  ---
5
5
 
6
6
  # TaskChef Delegate
@@ -49,6 +49,13 @@ stop and report that the TaskChef plugin must be reloaded or installed.
49
49
  3. Route against configured project `name`, `description`, and canonical
50
50
  `githubRepos`; use `path` only as checkout identity. Require exactly one
51
51
  match and an exact native-project path. Ask instead of guessing.
52
+ Select `planner` for a requested planning assignment and `implementer` for
53
+ coding work. Use the matched project's `projectModelRoles` from preparation;
54
+ resolve explicit user choices and follow [model roles](references/model-roles.md).
55
+ Small coding changes need no separate planning task. For a planning/coding
56
+ split, the saved plan is the handoff to a separately requested implementation
57
+ assignment; do not switch models during a turn or coordinate phases automatically.
58
+ Resolve configuration problems before recording the task.
52
59
  4. Build each executor instruction in this exact shape:
53
60
 
54
61
  - Begin with the actual assignment on the first line and keep its complete
@@ -0,0 +1,49 @@
1
+ # Dispatch model roles
2
+
3
+ Preparation includes personal and per-project model previews. Use the exact
4
+ matched project's preview. Role preferences use native Codex agent TOML under
5
+ `$CODEX_HOME/agents/` (default `~/.codex/agents/`) and that project's
6
+ `.codex/agents/`; they are optional. The resolver requires Python 3.11+.
7
+
8
+ Select `planner` for a planning assignment or `implementer` for coding. Pass
9
+ its `taskOverrides` as native `model` and `thinking` arguments only after checking
10
+ those values against the current create-task tool's supported model/effort
11
+ choices. A missing role means omit both arguments and use the native new-task
12
+ default. This is not guaranteed to inherit the dispatcher's model.
13
+
14
+ Explicit user model choices take precedence over the project role, personal
15
+ role, and native defaults. An explicit model without explicit effort omits effort and uses the native
16
+ interface's omission behavior; do not mix in a different role's effort or claim
17
+ a specific effective effort without evidence. Explicit effort
18
+ alone replaces the resolved role effort. Project roles replace personal roles
19
+ as a unit. To resolve explicit choices, or recheck a preview after configuration
20
+ changes, run:
21
+
22
+ ```sh
23
+ python3 <plugin-root>/scripts/roles/resolve_roles.py --project <project-path> --role implementer --model <user-model> --effort <user-effort>
24
+ ```
25
+
26
+ Omit flags the user did not specify. Resolve the plugin root from this skill's
27
+ real path, two parents above the skill directory. Do not substitute dispatcher
28
+ paths for the target project or infer model names from skill prose.
29
+
30
+ Report malformed profiles, duplicate names, unavailable models/efforts, and
31
+ resolver failures. Do not quietly fall back and claim preferences were honored.
32
+ The local model catalog is advisory: explain if a current native tool disproves
33
+ its stale warning. Otherwise resolve the problem or obtain a valid explicit
34
+ choice before task creation. Native creation failures retain normal TaskChef
35
+ failure reporting. A preparation without role fields supports historical
36
+ installations: check role files before deciding that no preferences exist.
37
+
38
+ Only model and effort are adapted. The native agent file's instructions, tools,
39
+ permissions, and other settings are not applied by create-task arguments. A
40
+ role name in a title is not a native role selector. If the native interface adds
41
+ a role selector, use it only with verified effective settings.
42
+
43
+ For a plan-to-implementation handoff, a planner assignment can save
44
+ `plans/addition.md` describing a pure addition function and the acceptance
45
+ example `2 + 3 = 5`. A later implementer assignment reads that exact plan,
46
+ implements the function, runs the example, and uses fresh reviewer subagents.
47
+ The dispatcher returns after each creation; it does not wait for or launch
48
+ subsequent phases automatically. A small addition change can instead go
49
+ straight to the implementer.