Skip to content
This repository was archived by the owner on Apr 11, 2026. It is now read-only.

Commit 0bf4ae4

Browse files
z23ccclaude
andcommitted
feat(flowctl): add Phase 1.5 Investigation + --investigation CLI flag
Add Phase 1.5 "Investigation" to the phase registry between Re-anchor and TDD/Implement. Add --investigation flag to `task spec` command for patching `## Investigation targets` sections. Update default task spec template to include empty investigation targets placeholder. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f24c273 commit 0bf4ae4

3 files changed

Lines changed: 20 additions & 8 deletions

File tree

flowctl/crates/flowctl-cli/src/commands/task/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ pub enum TaskCmd {
5757
/// Acceptance section file.
5858
#[arg(long, alias = "acceptance")]
5959
accept: Option<String>,
60+
/// Investigation targets section file.
61+
#[arg(long)]
62+
investigation: Option<String>,
6063
},
6164
/// Reset task to todo.
6265
Reset {
@@ -171,7 +174,7 @@ fn parse_domain(s: &str) -> Domain {
171174
fn create_task_spec(id: &str, title: &str, acceptance: Option<&str>) -> String {
172175
let acceptance_content = acceptance.unwrap_or("- [ ] TBD");
173176
format!(
174-
"# {} {}\n\n## Description\nTBD\n\n## Acceptance\n{}\n\n## Done summary\nTBD\n\n## Evidence\n- Commits:\n- Tests:\n- PRs:\n",
177+
"# {} {}\n\n## Description\nTBD\n\n## Investigation targets\n\n## Acceptance\n{}\n\n## Done summary\nTBD\n\n## Evidence\n- Commits:\n- Tests:\n- PRs:\n",
175178
id, title, acceptance_content
176179
)
177180
}
@@ -338,7 +341,8 @@ pub fn dispatch(cmd: &TaskCmd, json: bool) {
338341
file,
339342
desc,
340343
accept,
341-
} => query::cmd_task_set_spec(json, id, file.as_deref(), desc.as_deref(), accept.as_deref()),
344+
investigation,
345+
} => query::cmd_task_set_spec(json, id, file.as_deref(), desc.as_deref(), accept.as_deref(), investigation.as_deref()),
342346
TaskCmd::Reset { task_id, cascade } => mutate::cmd_task_reset(json, task_id, *cascade),
343347
TaskCmd::Skip { task_id, reason } => mutate::cmd_task_skip(json, task_id, reason.as_deref()),
344348
TaskCmd::Split {

flowctl/crates/flowctl-cli/src/commands/task/query.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub(super) fn cmd_task_set_spec(
1818
file: Option<&str>,
1919
description: Option<&str>,
2020
acceptance: Option<&str>,
21+
investigation: Option<&str>,
2122
) {
2223
let flow_dir = ensure_flow_exists();
2324

@@ -28,8 +29,8 @@ pub(super) fn cmd_task_set_spec(
2829
));
2930
}
3031

31-
if file.is_none() && description.is_none() && acceptance.is_none() {
32-
error_exit("Requires --file, --description, or --acceptance");
32+
if file.is_none() && description.is_none() && acceptance.is_none() && investigation.is_none() {
33+
error_exit("Requires --file, --description, --acceptance, or --investigation");
3334
}
3435

3536
let mut doc = load_task_doc(&flow_dir, task_id);
@@ -67,6 +68,12 @@ pub(super) fn cmd_task_set_spec(
6768
sections_updated.push("## Acceptance");
6869
}
6970

71+
if let Some(inv_file) = investigation {
72+
let inv_content = read_file_or_stdin(inv_file);
73+
doc.body = patch_body_section(&doc.body, "## Investigation targets", &inv_content);
74+
sections_updated.push("## Investigation targets");
75+
}
76+
7077
doc.frontmatter.updated_at = Utc::now();
7178
write_task_doc(&flow_dir, task_id, &doc);
7279

flowctl/crates/flowctl-core/src/types.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ impl std::fmt::Display for PhaseStatus {
305305
pub const PHASE_DEFS: &[(&str, &str, &str)] = &[
306306
("0", "Verify Configuration", "OWNED_FILES verified and configuration validated"),
307307
("1", "Re-anchor", "Run flowctl show <task> and verify spec was read"),
308+
("1.5", "Investigation", "Required investigation target files read and patterns noted"),
308309
("2a", "TDD Red-Green", "Failing tests written and confirmed to fail"),
309310
("2", "Implement", "Feature implemented and code compiles"),
310311
("2.5", "Verify & Fix", "flowctl guard passes and diff reviewed"),
@@ -319,9 +320,9 @@ pub const PHASE_DEFS: &[(&str, &str, &str)] = &[
319320
/// Phase sequences by mode (from Python constants.py).
320321
/// Phase `5c` (outputs_dump) is NOT in these static sequences — it is added
321322
/// dynamically by `worker-phase next` based on the `outputs.enabled` config.
322-
pub const PHASE_SEQ_DEFAULT: &[&str] = &["0", "1", "2", "2.5", "3", "5", "5b", "6"];
323-
pub const PHASE_SEQ_TDD: &[&str] = &["0", "1", "2a", "2", "2.5", "3", "5", "5b", "6"];
324-
pub const PHASE_SEQ_REVIEW: &[&str] = &["0", "1", "2", "2.5", "3", "4", "5", "5b", "6"];
323+
pub const PHASE_SEQ_DEFAULT: &[&str] = &["0", "1", "1.5", "2", "2.5", "3", "5", "5b", "6"];
324+
pub const PHASE_SEQ_TDD: &[&str] = &["0", "1", "1.5", "2a", "2", "2.5", "3", "5", "5b", "6"];
325+
pub const PHASE_SEQ_REVIEW: &[&str] = &["0", "1", "1.5", "2", "2.5", "3", "4", "5", "5b", "6"];
325326

326327
// ── Evidence ─────────────────────────────────────────────────────────
327328

@@ -551,7 +552,7 @@ mod tests {
551552

552553
#[test]
553554
fn test_phase_defs_complete() {
554-
assert_eq!(PHASE_DEFS.len(), 11);
555+
assert_eq!(PHASE_DEFS.len(), 12);
555556
// Verify all phase sequences reference valid phase IDs
556557
let valid_ids: Vec<&str> = PHASE_DEFS.iter().map(|(id, _, _)| *id).collect();
557558
for seq_id in PHASE_SEQ_DEFAULT {

0 commit comments

Comments
 (0)