Skip to content

Commit 1e9c951

Browse files
committed
Add taskflow lint gate for result quality
Introduce taskflow artifact linting to improve process/result stability.\n\nChanges:\n- add scripts/codex_task_lint.sh to taskflow kit templates\n - mode=scaffold: verifies artifact set + unresolved template tokens\n - mode=complete: additionally fails on placeholder-style unfinished content\n- install codex_task_lint.sh via taskflow installer and manage it in .gitignore block\n- add coverage in scripts/test_kits.sh:\n - scaffold lint must pass after task generation\n - complete lint must fail on unfinished scaffold artifacts\n- document lint usage in kit README and top-level quality gate summary\n\nValidation:\n- scripts/test_kits.sh passes end-to-end locally.
1 parent 1ca1567 commit 1e9c951

5 files changed

Lines changed: 146 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Coverage includes:
4141
- syntax checks for shell/python sources
4242
- installer `.gitignore` resilience and idempotency
4343
- config validation failure checks for bootstrap/taskflow JSON
44+
- taskflow lint checks (`scaffold` pass, `complete` fail-on-placeholders)
4445
- CLI applicability (`codex_session.sh`)
4546
- Codex App applicability (`codex_verify_session.sh`, `codex_task.sh`)
4647
- AGENTS/Skills applicability (startup contract and checklist state)

kits/codex-taskflow-kit/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Strict mode defaults are enabled:
3535
## What it installs
3636

3737
- `scripts/codex_task.sh`
38+
- `scripts/codex_task_lint.sh`
3839
- `.codex_taskflow/config.json`
3940
- `.codex_taskflow/taskflow_engine.py`
4041
- `.codex_taskflow/templates/*.md`
@@ -51,6 +52,13 @@ Each task creates:
5152
- `work/taskflow/<task_id>/50_handoff.md`
5253
- `work/taskflow/<task_id>/taskflow.json`
5354

55+
Lint helper:
56+
57+
```bash
58+
bash scripts/codex_task_lint.sh --latest --mode scaffold
59+
bash scripts/codex_task_lint.sh --latest --mode complete
60+
```
61+
5462
## Install Into Any Repo
5563

5664
```bash

kits/codex-taskflow-kit/bin/install.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ ensure_gitignore_block() {
9090
local end_marker="# <<< codex-taskflow-kit (local-only)"
9191
local tmp_file
9292
local source_file="$gitignore_file"
93-
local managed_regex='^(\.codex_taskflow/|scripts/codex_task\.sh|work/taskflow/)$'
93+
local managed_regex='^(\.codex_taskflow/|scripts/codex_task\.sh|scripts/codex_task_lint\.sh|work/taskflow/)$'
9494

9595
if [[ ! -f "$gitignore_file" ]]; then
9696
if [[ "$DRY_RUN" -eq 1 ]]; then
@@ -114,6 +114,7 @@ ensure_gitignore_block() {
114114
printf "\n%s\n" "$start_marker"
115115
printf "%s\n" ".codex_taskflow/"
116116
printf "%s\n" "scripts/codex_task.sh"
117+
printf "%s\n" "scripts/codex_task_lint.sh"
117118
printf "%s\n" "work/taskflow/"
118119
printf "%s\n" "$end_marker"
119120
} >> "$tmp_file"
@@ -162,6 +163,7 @@ copy_file() {
162163

163164
FILES=(
164165
"scripts/codex_task.sh"
166+
"scripts/codex_task_lint.sh"
165167
".codex_taskflow/config.json"
166168
".codex_taskflow/taskflow_engine.py"
167169
".codex_taskflow/templates/intake.md"
@@ -183,6 +185,7 @@ if [[ "$DRY_RUN" -eq 1 ]]; then
183185
else
184186
chmod +x \
185187
"$TARGET/scripts/codex_task.sh" \
188+
"$TARGET/scripts/codex_task_lint.sh" \
186189
"$TARGET/.codex_taskflow/taskflow_engine.py"
187190
fi
188191

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5+
WORK_DIR="$ROOT_DIR/work/taskflow"
6+
TASK_DIR=""
7+
MODE="scaffold"
8+
9+
usage() {
10+
cat <<'USAGE'
11+
Usage:
12+
bash scripts/codex_task_lint.sh [--task-dir <path> | --latest] [--mode scaffold|complete]
13+
14+
Modes:
15+
scaffold Validate generated taskflow structure and unresolved template tokens.
16+
complete Validate scaffold checks plus unresolved placeholders in handoff content.
17+
USAGE
18+
}
19+
20+
fail() {
21+
echo "[taskflow-lint] ERROR: $1" >&2
22+
exit 1
23+
}
24+
25+
resolve_task_dir() {
26+
local latest
27+
28+
if [[ -n "$TASK_DIR" ]]; then
29+
[[ -d "$TASK_DIR" ]] || fail "task directory not found: $TASK_DIR"
30+
TASK_DIR="$(cd "$TASK_DIR" && pwd)"
31+
return
32+
fi
33+
34+
[[ -d "$WORK_DIR" ]] || fail "taskflow work directory not found: $WORK_DIR"
35+
latest="$(find "$WORK_DIR" -mindepth 1 -maxdepth 1 -type d | sort | tail -n 1)"
36+
[[ -n "$latest" ]] || fail "no taskflow directories found under: $WORK_DIR"
37+
TASK_DIR="$latest"
38+
}
39+
40+
check_required_files() {
41+
local required=(
42+
"$TASK_DIR/00_intake.md"
43+
"$TASK_DIR/10_scope.md"
44+
"$TASK_DIR/20_plan.md"
45+
"$TASK_DIR/30_execution_log.md"
46+
"$TASK_DIR/40_verification.md"
47+
"$TASK_DIR/50_handoff.md"
48+
"$TASK_DIR/taskflow.json"
49+
)
50+
local file
51+
52+
for file in "${required[@]}"; do
53+
[[ -s "$file" ]] || fail "required file missing or empty: $file"
54+
done
55+
}
56+
57+
check_unresolved_tokens() {
58+
local file
59+
for file in "$TASK_DIR"/*.md; do
60+
if grep -Eq '\{\{[A-Z0-9_]+\}\}' "$file"; then
61+
fail "unresolved template token detected: $file"
62+
fi
63+
done
64+
}
65+
66+
check_complete_mode() {
67+
local file
68+
local placeholder_pattern='^-[[:space:]]*$|^1\.[[:space:]]*$|TODO: add task details|^-[[:space:]]*(Decision|Why|Tradeoff|Symptom|Observed behavior|Expected behavior|Time|Risk tolerance|Non-functional requirements|Components/files likely affected|Dependencies/external systems|Command|Result):[[:space:]]*$'
69+
70+
for file in "$TASK_DIR"/*.md; do
71+
if grep -Eq "$placeholder_pattern" "$file"; then
72+
fail "placeholder-style content remains in complete mode: $file"
73+
fi
74+
done
75+
}
76+
77+
while (( $# > 0 )); do
78+
case "$1" in
79+
--task-dir)
80+
shift
81+
TASK_DIR="${1:-}"
82+
;;
83+
--latest)
84+
TASK_DIR=""
85+
;;
86+
--mode)
87+
shift
88+
MODE="${1:-}"
89+
;;
90+
-h|--help)
91+
usage
92+
exit 0
93+
;;
94+
*)
95+
fail "unknown argument: $1"
96+
;;
97+
esac
98+
shift || true
99+
done
100+
101+
case "$MODE" in
102+
scaffold|complete) ;;
103+
*)
104+
fail "--mode must be scaffold or complete"
105+
;;
106+
esac
107+
108+
resolve_task_dir
109+
check_required_files
110+
check_unresolved_tokens
111+
112+
if [[ "$MODE" == "complete" ]]; then
113+
check_complete_mode
114+
fi
115+
116+
echo "[taskflow-lint] PASS mode=$MODE task_dir=$TASK_DIR"

scripts/test_kits.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ run_surface_smoke_checks() {
212212
assert_file "$target_repo/scripts/codex_session.sh"
213213
assert_file "$target_repo/scripts/codex_verify_session.sh"
214214
assert_file "$target_repo/scripts/codex_task.sh"
215+
assert_file "$target_repo/scripts/codex_task_lint.sh"
215216

216217
# Bootstrap output control surface.
217218
(
@@ -251,6 +252,22 @@ EOF
251252
task_json="$(echo "$task_json" | tr -d '\r')"
252253
assert_file "$task_json"
253254

255+
(
256+
cd "$target_repo"
257+
bash scripts/codex_task_lint.sh --latest --mode scaffold >"$target_repo/taskflow-lint-scaffold.out"
258+
)
259+
assert_grep 'PASS mode=scaffold' "$target_repo/taskflow-lint-scaffold.out" "taskflow scaffold lint did not pass"
260+
261+
set +e
262+
(
263+
cd "$target_repo"
264+
bash scripts/codex_task_lint.sh --latest --mode complete >"$target_repo/taskflow-lint-complete.out" 2>"$target_repo/taskflow-lint-complete.err"
265+
)
266+
local lint_complete_status=$?
267+
set -e
268+
[[ "$lint_complete_status" -ne 0 ]] || fail "taskflow complete lint unexpectedly passed on scaffold artifacts"
269+
assert_grep 'placeholder-style content remains in complete mode' "$target_repo/taskflow-lint-complete.err" "taskflow complete lint missing expected failure signal"
270+
254271
# Agent Skills surface: AGENTS startup contract + generated startup order + PASS checklist.
255272
cat >"$target_repo/AGENTS.md" <<'EOF'
256273
# AGENTS

0 commit comments

Comments
 (0)