Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/plugin-scanner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,14 @@ jobs:
with:
plugin_dir: "."
mode: scan
format: json
output: plugin-security-report.json
pr_comment: "off"
min_score: 80
fail_on_severity: high
- name: Show complete scanner findings
if: always()
run: |
if [ -f plugin-security-report.json ]; then
cat plugin-security-report.json
fi
10 changes: 5 additions & 5 deletions packages/claude-taskflow/plugin/skills/taskflow/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,9 @@ For a non-trivial flow you'll iterate on, **write the definition to a file**
(typically in the OS tmp dir) and point every call at it with `defineFile`:

```jsonc
// 1. write /tmp/audit.json with the `write` tool (a full {name, phases:[…]} object)
// 1. write /tmp/audit.json with the `write` tool (a full {name, phases:[...]} object)
// 2. verify, iterate, run — all reference the SAME file by path:
{ "name": "taskflow_plan", "arguments": { "defineFile": "/tmp/audit.json", "args": { … } } } // zero tokens: bind + plan + budget bound
{ "name": "taskflow_plan", "arguments": { "defineFile": "/tmp/audit.json", "args": { ... } } } // zero tokens: bind + plan + budget bound
{ "name": "taskflow_verify", "arguments": { "defineFile": "/tmp/audit.json" } } // zero tokens
{ "name": "taskflow_compile", "arguments": { "defineFile": "/tmp/audit.json" } } // diagram
{ "name": "taskflow_lint", "arguments": { "defineFile": "/tmp/audit.json" } } // script-lint + custom verifiers
Expand Down Expand Up @@ -572,7 +572,7 @@ Each effect:
**Phase output is the payload.** With one declared `fs.write`, the phase's
output becomes the staged file content (see the example: `process.stdout.write`
= the report). With several `fs.write` effects, the phase must emit JSON
mapping each effect id to its content (`{ "report": "…", "backup": "…" }`).
mapping each effect id to its content (`{ "report": "...", "backup": "..." }`).
Commit promotes each file atomically; a later failure restores every admitted
file to its durable pre-state, and a direct write by the agent/script to a
**declared final path** is detected and restored — only the resource
Expand Down Expand Up @@ -624,8 +624,8 @@ more than comparing every approach.
{
"id": "quick", "type": "race",
"branches": [
{ "task": "Answer with a short heuristic…", "agent": "executor" },
{ "task": "Answer with a thorough search…", "agent": "researcher" }
{ "task": "Answer with a short heuristic...", "agent": "executor" },
{ "task": "Answer with a thorough search...", "agent": "researcher" }
],
"final": true
}
Expand Down
32 changes: 16 additions & 16 deletions packages/claude-taskflow/plugin/skills/taskflow/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Top-level keys of the taskflow definition object.
| `agentScope` | `user`\|`project`\|`both` | `user` | Which agent dirs to load. See §6. |
| `scriptCwd` | `invocation`\|`flow` | `invocation` | Default cwd policy for `script` phases. `flow` requires trusted saved-flow/`defineFile` provenance; explicit phase `cwd` wins, and inherited cwd-bridge boundaries still constrain the resolved source directory. `taskFile` is the same class of load-time trusted source (see §2). |
| `args` | record | `{}` | Declared invocation arguments. See §3. |
| `hooks` | object | — | **0.2.7.** Terminal fire-and-forget notifications: `onComplete` / `onFail` / `onBlocked` arrays of `{type:"webhook"\|"file"\|"command", …}`. Payload is summary-only (`taskflow.hook.v1`) — never transcripts. Hook failure never changes run status. `https` or `http://127.0.0.1\|localhost` for webhooks; `command.run` is argv-only (no shell string). |
| `hooks` | object | — | **0.2.7.** Terminal fire-and-forget notifications: `onComplete` / `onFail` / `onBlocked` arrays of `{type:"webhook"\|"file"\|"command", ...}`. Payload is summary-only (`taskflow.hook.v1`) — never transcripts. Hook failure never changes run status. `https` or `http://127.0.0.1\|localhost` for webhooks; `command.run` is argv-only (no shell string). |
| `phases` | array | — | **Required.** The phase DAG. See §2. |
| `version` | number | `1` | Informational metadata in 0.2.x; it does not select runtime semantics or migrate a flow. |

Expand All @@ -66,11 +66,11 @@ Keys of each object in `phases[]`. Some only apply to specific `type`s.
"id": "audit", // required, unique — referenced via {steps.audit.output}
"type": "map", // agent | parallel | map | gate | reduce | approval | flow | loop | tournament | script | race | expand (default: agent)
"agent": "analyst", // agent name to run this phase
"task": "Audit {item.route}…",
"task": "Audit {item.route}...",
"dependsOn": ["discover"],// DAG edges
"over": "{steps.discover.json}", // [map] array to fan out over
"as": "item", // [map] loop var name (default: item)
"branches": [ /* … */ ], // [parallel|race] static task list
"branches": [ /* ... */ ], // [parallel|race] static task list
"from": ["audit"], // [reduce] phase ids to aggregate
"def": "{steps.plan.json}", // [expand|flow] inline fragment / dynamic sub-flow
"expandMode": "nested", // [expand] nested | graft
Expand All @@ -86,7 +86,7 @@ Keys of each object in `phases[]`. Some only apply to specific `type`s.

| Key | Applies to | Default | Notes |
|-----|-----------|---------|-------|
| `id` | all | — | **Required, unique.** Used in `{steps.<id>…}`. |
| `id` | all | — | **Required, unique.** Used in `{steps.<id>...}`. |
| `type` | all | `agent` | One of the **12** phase types (agent, parallel, map, gate, reduce, approval, flow, loop, tournament, script, **race**, **expand**). |
| `agent` | all | first available | Agent name; resolved from the scoped pool. |
| `task` | agent, gate, map, reduce | — | Prompt; supports interpolation. Required for these types unless `taskFile` is set. |
Expand Down Expand Up @@ -268,8 +268,8 @@ There are **two independent concurrency limits**:
"concurrency": 6, // ≤6 sibling phases run at once
"phases": [
{ "id": "scan", "type": "map", "over": "{steps.list.json}",
"concurrency": 3, // …but this map only fans out 3 at a time
"task": "…", "dependsOn": ["list"] }
"concurrency": 3, // ...but this map only fans out 3 at a time
"task": "...", "dependsOn": ["list"] }
]
}
```
Expand Down Expand Up @@ -431,7 +431,7 @@ fingerprint folds **“did the world change?”** signals into that key, so an
external change becomes a cache **miss** even when the task text is identical.
Each entry is one of:

| Entry | Becomes a miss when… | Resolves to |
| Entry | Becomes a miss when... | Resolves to |
|-------|----------------------|-------------|
| `git:HEAD` / `git:<ref>` | the commit moves | the resolved SHA (30s timeout → `<timeout>`; no git → `<no-git>`) |
| `glob:<pattern>` | the **set of matching paths** or their metadata changes | sorted path list with size + mtime (content-hashed globs use `glob!:` instead, which is mtime-independent) |
Expand Down Expand Up @@ -493,7 +493,7 @@ Each entry is one of:
```jsonc
{ "id": "review", "type": "gate", "agent": "reviewer",
"model": "claude-opus-4", "thinking": "high",
"task": "…\nVERDICT:", "dependsOn": ["audit"] }
"task": "...\nVERDICT:", "dependsOn": ["audit"] }
```

**Sandbox a phase to read-only in a subdirectory:**
Expand All @@ -512,7 +512,7 @@ Each entry is one of:

**Project-only agents:**
```jsonc
{ "name": "ci-audit", "agentScope": "project", "phases": [ /* … */ ] }
{ "name": "ci-audit", "agentScope": "project", "phases": [ /* ... */ ] }
```

---
Expand Down Expand Up @@ -551,22 +551,22 @@ symlinks, and commit atomically; `--emit both` preflights both destinations.

**Authoring notes (kinds ↔ runes)**

Import: `import { flow, agent, map, … } from "taskflow-dsl"`. Runes erase to Taskflow
Import: `import { flow, agent, map, ... } from "taskflow-dsl"`. Runes erase to Taskflow
JSON kinds (single source: `PHASE_TYPES` in core + `erase/kinds/*` registry).

| JSON `type` | DSL rune(s) | Notes |
|-------------|-------------|--------|
| `agent` | `agent(task, opts?)` | templates → `{steps.*}` / `{item.*}` |
| `parallel` | `parallel([agent…])` | waits for all branches |
| `map` | `map(source, item => agent…)` | `over` + `as` |
| `parallel` | `parallel([agent...])` | waits for all branches |
| `map` | `map(source, item => agent...)` | `over` + `as` |
| `gate` | `gate(up, opts?, task?)` · `gate.automated` · `gate.scored` | sugar → `eval` / `score` |
| `reduce` | `reduce([…], () => agent…)` | `from` |
| `reduce` | `reduce([...], () => agent...)` | `from` |
| `approval` | `approval({ request })` | |
| `flow` | `subflow("name")` · `subflow.def(plan)` | use vs def |
| `loop` | `loop({ task, until?, … })` | |
| `tournament` | `tournament({ branches/variants, judge, … })` | |
| `loop` | `loop({ task, until?, ... })` | |
| `tournament` | `tournament({ branches/variants, judge, ... })` | |
| `script` | `script(run, opts?)` | string or argv array |
| `race` | `race([agent…], { cancelLosers? })` | first **success** wins; cooperative loser usage is counted |
| `race` | `race([agent...], { cancelLosers? })` | first **success** wins; cooperative loser usage is counted |
| `expand` | `expand` / `expand.nested` / `expand.graft` | `def` + `expandMode` |

- `const [a,b] = parallel([agent(...), agent(...)])` desugars to **two real agent phases** (`a`, `b`) that run concurrently (no `dependsOn` between them). Prefer this when you need `{steps.a.output}`.
Expand Down
10 changes: 5 additions & 5 deletions packages/codex-taskflow/plugin/skills/taskflow/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,9 @@ For a non-trivial flow you'll iterate on, **write the definition to a file**
(typically in the OS tmp dir) and point every call at it with `defineFile`:

```jsonc
// 1. write /tmp/audit.json with the `write` tool (a full {name, phases:[…]} object)
// 1. write /tmp/audit.json with the `write` tool (a full {name, phases:[...]} object)
// 2. verify, iterate, run — all reference the SAME file by path:
{ "name": "taskflow_plan", "arguments": { "defineFile": "/tmp/audit.json", "args": { … } } } // zero tokens: bind + plan + budget bound
{ "name": "taskflow_plan", "arguments": { "defineFile": "/tmp/audit.json", "args": { ... } } } // zero tokens: bind + plan + budget bound
{ "name": "taskflow_verify", "arguments": { "defineFile": "/tmp/audit.json" } } // zero tokens
{ "name": "taskflow_compile", "arguments": { "defineFile": "/tmp/audit.json" } } // diagram
{ "name": "taskflow_lint", "arguments": { "defineFile": "/tmp/audit.json" } } // script-lint + custom verifiers
Expand Down Expand Up @@ -567,7 +567,7 @@ Each effect:
**Phase output is the payload.** With one declared `fs.write`, the phase's
output becomes the staged file content (see the example: `process.stdout.write`
= the report). With several `fs.write` effects, the phase must emit JSON
mapping each effect id to its content (`{ "report": "…", "backup": "…" }`).
mapping each effect id to its content (`{ "report": "...", "backup": "..." }`).
Commit promotes each file atomically; a later failure restores every admitted
file to its durable pre-state, and a direct write by the agent/script to a
**declared final path** is detected and restored — only the resource
Expand Down Expand Up @@ -619,8 +619,8 @@ more than comparing every approach.
{
"id": "quick", "type": "race",
"branches": [
{ "task": "Answer with a short heuristic…", "agent": "executor" },
{ "task": "Answer with a thorough search…", "agent": "researcher" }
{ "task": "Answer with a short heuristic...", "agent": "executor" },
{ "task": "Answer with a thorough search...", "agent": "researcher" }
],
"final": true
}
Expand Down
32 changes: 16 additions & 16 deletions packages/codex-taskflow/plugin/skills/taskflow/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Top-level keys of the taskflow definition object.
| `agentScope` | `user`\|`project`\|`both` | `user` | Which agent dirs to load. See §6. |
| `scriptCwd` | `invocation`\|`flow` | `invocation` | Default cwd policy for `script` phases. `flow` requires trusted saved-flow/`defineFile` provenance; explicit phase `cwd` wins, and inherited cwd-bridge boundaries still constrain the resolved source directory. `taskFile` is the same class of load-time trusted source (see §2). |
| `args` | record | `{}` | Declared invocation arguments. See §3. |
| `hooks` | object | — | **0.2.7.** Terminal fire-and-forget notifications: `onComplete` / `onFail` / `onBlocked` arrays of `{type:"webhook"\|"file"\|"command", …}`. Payload is summary-only (`taskflow.hook.v1`) — never transcripts. Hook failure never changes run status. `https` or `http://127.0.0.1\|localhost` for webhooks; `command.run` is argv-only (no shell string). |
| `hooks` | object | — | **0.2.7.** Terminal fire-and-forget notifications: `onComplete` / `onFail` / `onBlocked` arrays of `{type:"webhook"\|"file"\|"command", ...}`. Payload is summary-only (`taskflow.hook.v1`) — never transcripts. Hook failure never changes run status. `https` or `http://127.0.0.1\|localhost` for webhooks; `command.run` is argv-only (no shell string). |
| `phases` | array | — | **Required.** The phase DAG. See §2. |
| `version` | number | `1` | Informational metadata in 0.2.x; it does not select runtime semantics or migrate a flow. |

Expand All @@ -66,11 +66,11 @@ Keys of each object in `phases[]`. Some only apply to specific `type`s.
"id": "audit", // required, unique — referenced via {steps.audit.output}
"type": "map", // agent | parallel | map | gate | reduce | approval | flow | loop | tournament | script | race | expand (default: agent)
"agent": "analyst", // agent name to run this phase
"task": "Audit {item.route}…",
"task": "Audit {item.route}...",
"dependsOn": ["discover"],// DAG edges
"over": "{steps.discover.json}", // [map] array to fan out over
"as": "item", // [map] loop var name (default: item)
"branches": [ /* … */ ], // [parallel|race] static task list
"branches": [ /* ... */ ], // [parallel|race] static task list
"from": ["audit"], // [reduce] phase ids to aggregate
"def": "{steps.plan.json}", // [expand|flow] inline fragment / dynamic sub-flow
"expandMode": "nested", // [expand] nested | graft
Expand All @@ -86,7 +86,7 @@ Keys of each object in `phases[]`. Some only apply to specific `type`s.

| Key | Applies to | Default | Notes |
|-----|-----------|---------|-------|
| `id` | all | — | **Required, unique.** Used in `{steps.<id>…}`. |
| `id` | all | — | **Required, unique.** Used in `{steps.<id>...}`. |
| `type` | all | `agent` | One of the **12** phase types (agent, parallel, map, gate, reduce, approval, flow, loop, tournament, script, **race**, **expand**). |
| `agent` | all | first available | Agent name; resolved from the scoped pool. |
| `task` | agent, gate, map, reduce | — | Prompt; supports interpolation. Required for these types unless `taskFile` is set. |
Expand Down Expand Up @@ -268,8 +268,8 @@ There are **two independent concurrency limits**:
"concurrency": 6, // ≤6 sibling phases run at once
"phases": [
{ "id": "scan", "type": "map", "over": "{steps.list.json}",
"concurrency": 3, // …but this map only fans out 3 at a time
"task": "…", "dependsOn": ["list"] }
"concurrency": 3, // ...but this map only fans out 3 at a time
"task": "...", "dependsOn": ["list"] }
]
}
```
Expand Down Expand Up @@ -428,7 +428,7 @@ fingerprint folds **“did the world change?”** signals into that key, so an
external change becomes a cache **miss** even when the task text is identical.
Each entry is one of:

| Entry | Becomes a miss when… | Resolves to |
| Entry | Becomes a miss when... | Resolves to |
|-------|----------------------|-------------|
| `git:HEAD` / `git:<ref>` | the commit moves | the resolved SHA (30s timeout → `<timeout>`; no git → `<no-git>`) |
| `glob:<pattern>` | the **set of matching paths** or their metadata changes | sorted path list with size + mtime (content-hashed globs use `glob!:` instead, which is mtime-independent) |
Expand Down Expand Up @@ -490,7 +490,7 @@ Each entry is one of:
```jsonc
{ "id": "review", "type": "gate", "agent": "reviewer",
"model": "claude-opus-4", "thinking": "high",
"task": "…\nVERDICT:", "dependsOn": ["audit"] }
"task": "...\nVERDICT:", "dependsOn": ["audit"] }
```

**Sandbox a phase to read-only in a subdirectory:**
Expand All @@ -509,7 +509,7 @@ Each entry is one of:

**Project-only agents:**
```jsonc
{ "name": "ci-audit", "agentScope": "project", "phases": [ /* … */ ] }
{ "name": "ci-audit", "agentScope": "project", "phases": [ /* ... */ ] }
```

---
Expand Down Expand Up @@ -548,22 +548,22 @@ symlinks, and commit atomically; `--emit both` preflights both destinations.

**Authoring notes (kinds ↔ runes)**

Import: `import { flow, agent, map, … } from "taskflow-dsl"`. Runes erase to Taskflow
Import: `import { flow, agent, map, ... } from "taskflow-dsl"`. Runes erase to Taskflow
JSON kinds (single source: `PHASE_TYPES` in core + `erase/kinds/*` registry).

| JSON `type` | DSL rune(s) | Notes |
|-------------|-------------|--------|
| `agent` | `agent(task, opts?)` | templates → `{steps.*}` / `{item.*}` |
| `parallel` | `parallel([agent…])` | waits for all branches |
| `map` | `map(source, item => agent…)` | `over` + `as` |
| `parallel` | `parallel([agent...])` | waits for all branches |
| `map` | `map(source, item => agent...)` | `over` + `as` |
| `gate` | `gate(up, opts?, task?)` · `gate.automated` · `gate.scored` | sugar → `eval` / `score` |
| `reduce` | `reduce([…], () => agent…)` | `from` |
| `reduce` | `reduce([...], () => agent...)` | `from` |
| `approval` | `approval({ request })` | |
| `flow` | `subflow("name")` · `subflow.def(plan)` | use vs def |
| `loop` | `loop({ task, until?, … })` | |
| `tournament` | `tournament({ branches/variants, judge, … })` | |
| `loop` | `loop({ task, until?, ... })` | |
| `tournament` | `tournament({ branches/variants, judge, ... })` | |
| `script` | `script(run, opts?)` | string or argv array |
| `race` | `race([agent…], { cancelLosers? })` | first **success** wins; cooperative loser usage is counted |
| `race` | `race([agent...], { cancelLosers? })` | first **success** wins; cooperative loser usage is counted |
| `expand` | `expand` / `expand.nested` / `expand.graft` | `def` + `expandMode` |

- `const [a,b] = parallel([agent(...), agent(...)])` desugars to **two real agent phases** (`a`, `b`) that run concurrently (no `dependsOn` between them). Prefer this when you need `{steps.a.output}`.
Expand Down
10 changes: 5 additions & 5 deletions packages/grok-taskflow/plugin/skills/taskflow/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,9 @@ For a non-trivial flow you'll iterate on, **write the definition to a file**
(typically in the OS tmp dir) and point every call at it with `defineFile`:

```jsonc
// 1. write /tmp/audit.json with the `write` tool (a full {name, phases:[…]} object)
// 1. write /tmp/audit.json with the `write` tool (a full {name, phases:[...]} object)
// 2. verify, iterate, run — all reference the SAME file by path:
{ "name": "taskflow_plan", "arguments": { "defineFile": "/tmp/audit.json", "args": { … } } } // zero tokens: bind + plan + budget bound
{ "name": "taskflow_plan", "arguments": { "defineFile": "/tmp/audit.json", "args": { ... } } } // zero tokens: bind + plan + budget bound
{ "name": "taskflow_verify", "arguments": { "defineFile": "/tmp/audit.json" } } // zero tokens
{ "name": "taskflow_compile", "arguments": { "defineFile": "/tmp/audit.json" } } // diagram
{ "name": "taskflow_lint", "arguments": { "defineFile": "/tmp/audit.json" } } // script-lint + custom verifiers
Expand Down Expand Up @@ -577,7 +577,7 @@ Each effect:
**Phase output is the payload.** With one declared `fs.write`, the phase's
output becomes the staged file content (see the example: `process.stdout.write`
= the report). With several `fs.write` effects, the phase must emit JSON
mapping each effect id to its content (`{ "report": "…", "backup": "…" }`).
mapping each effect id to its content (`{ "report": "...", "backup": "..." }`).
Commit promotes each file atomically; a later failure restores every admitted
file to its durable pre-state, and a direct write by the agent/script to a
**declared final path** is detected and restored — only the resource
Expand Down Expand Up @@ -629,8 +629,8 @@ more than comparing every approach.
{
"id": "quick", "type": "race",
"branches": [
{ "task": "Answer with a short heuristic…", "agent": "executor" },
{ "task": "Answer with a thorough search…", "agent": "researcher" }
{ "task": "Answer with a short heuristic...", "agent": "executor" },
{ "task": "Answer with a thorough search...", "agent": "researcher" }
],
"final": true
}
Expand Down
Loading
Loading