huskies: merge 945
This commit is contained in:
+11
-21
@@ -57,21 +57,20 @@ mod tests {
|
||||
write_story(
|
||||
&stage_dir,
|
||||
"10_story_shadow_test.md",
|
||||
"---\nname: Shadow Test\nagent: coder-opus\nretry_count: 2\nblocked: false\n---\n# Story\n",
|
||||
"---\nname: Shadow Test\nagent: coder-opus\nretry_count: 2\n---\n# Story\n",
|
||||
);
|
||||
|
||||
// Perform the upsert directly (bypass the global singleton).
|
||||
let now = chrono::Utc::now().to_rfc3339();
|
||||
sqlx::query(
|
||||
"INSERT INTO pipeline_items \
|
||||
(id, name, stage, agent, retry_count, blocked, depends_on, content, created_at, updated_at) \
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?9) \
|
||||
(id, name, stage, agent, retry_count, depends_on, content, created_at, updated_at) \
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?8) \
|
||||
ON CONFLICT(id) DO UPDATE SET \
|
||||
name = excluded.name, \
|
||||
stage = excluded.stage, \
|
||||
agent = excluded.agent, \
|
||||
retry_count = excluded.retry_count, \
|
||||
blocked = excluded.blocked, \
|
||||
depends_on = excluded.depends_on, \
|
||||
content = COALESCE(excluded.content, pipeline_items.content), \
|
||||
updated_at = excluded.updated_at",
|
||||
@@ -81,7 +80,6 @@ mod tests {
|
||||
.bind("2_current")
|
||||
.bind("coder-opus")
|
||||
.bind(2_i64)
|
||||
.bind(0_i64)
|
||||
.bind(Option::<String>::None)
|
||||
.bind("---\nname: Shadow Test\n---\n# Story\n")
|
||||
.bind(&now)
|
||||
@@ -122,15 +120,14 @@ mod tests {
|
||||
let content = "---\nname: Test\n---\n# Story\n";
|
||||
sqlx::query(
|
||||
"INSERT INTO pipeline_items \
|
||||
(id, name, stage, agent, retry_count, blocked, depends_on, content, created_at, updated_at) \
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?9)",
|
||||
(id, name, stage, agent, retry_count, depends_on, content, created_at, updated_at) \
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?8)",
|
||||
)
|
||||
.bind("99_story_col_test")
|
||||
.bind(Option::<String>::None)
|
||||
.bind("1_backlog")
|
||||
.bind(Option::<String>::None)
|
||||
.bind(Option::<i64>::None)
|
||||
.bind(Option::<i64>::None)
|
||||
.bind(Option::<String>::None)
|
||||
.bind(content)
|
||||
.bind(&now)
|
||||
@@ -162,15 +159,14 @@ mod tests {
|
||||
// Insert initial row in backlog.
|
||||
sqlx::query(
|
||||
"INSERT INTO pipeline_items \
|
||||
(id, name, stage, agent, retry_count, blocked, depends_on, content, created_at, updated_at) \
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?9)",
|
||||
(id, name, stage, agent, retry_count, depends_on, content, created_at, updated_at) \
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?8)",
|
||||
)
|
||||
.bind("5_story_move")
|
||||
.bind("Move Me")
|
||||
.bind("1_backlog")
|
||||
.bind(Option::<String>::None)
|
||||
.bind(Option::<i64>::None)
|
||||
.bind(Option::<i64>::None)
|
||||
.bind(Option::<String>::None)
|
||||
.bind("---\nname: Move Me\n---\n")
|
||||
.bind(&now)
|
||||
@@ -181,14 +177,13 @@ mod tests {
|
||||
// Upsert with new stage (simulating move to current).
|
||||
sqlx::query(
|
||||
"INSERT INTO pipeline_items \
|
||||
(id, name, stage, agent, retry_count, blocked, depends_on, content, created_at, updated_at) \
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?9) \
|
||||
(id, name, stage, agent, retry_count, depends_on, content, created_at, updated_at) \
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?8) \
|
||||
ON CONFLICT(id) DO UPDATE SET \
|
||||
name = excluded.name, \
|
||||
stage = excluded.stage, \
|
||||
agent = excluded.agent, \
|
||||
retry_count = excluded.retry_count, \
|
||||
blocked = excluded.blocked, \
|
||||
depends_on = excluded.depends_on, \
|
||||
content = COALESCE(excluded.content, pipeline_items.content), \
|
||||
updated_at = excluded.updated_at",
|
||||
@@ -198,7 +193,6 @@ mod tests {
|
||||
.bind("2_current")
|
||||
.bind(Option::<String>::None)
|
||||
.bind(Option::<i64>::None)
|
||||
.bind(Option::<i64>::None)
|
||||
.bind(Option::<String>::None)
|
||||
.bind(Option::<String>::None) // content NULL → COALESCE preserves existing
|
||||
.bind(&now)
|
||||
@@ -266,15 +260,14 @@ mod tests {
|
||||
// Insert a live row.
|
||||
sqlx::query(
|
||||
"INSERT INTO pipeline_items \
|
||||
(id, name, stage, agent, retry_count, blocked, depends_on, content, created_at, updated_at) \
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?9)",
|
||||
(id, name, stage, agent, retry_count, depends_on, content, created_at, updated_at) \
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?8)",
|
||||
)
|
||||
.bind("42_story_to_delete")
|
||||
.bind("Delete Me")
|
||||
.bind("2_current")
|
||||
.bind(Option::<String>::None)
|
||||
.bind(Option::<i64>::None)
|
||||
.bind(Option::<i64>::None)
|
||||
.bind(Option::<String>::None)
|
||||
.bind("---\nname: Delete Me\n---\n")
|
||||
.bind(&now)
|
||||
@@ -322,7 +315,6 @@ mod tests {
|
||||
name: Some("Typed Name".into()),
|
||||
agent: Some("coder-1".into()),
|
||||
retry_count: Some(2),
|
||||
blocked: Some(true),
|
||||
depends_on: Some(vec![100, 200]),
|
||||
};
|
||||
write_item_with_content(story_id, "2_current", content, meta);
|
||||
@@ -332,7 +324,6 @@ mod tests {
|
||||
assert_eq!(view.name(), Some("Typed Name"));
|
||||
assert_eq!(view.agent(), Some("coder-1"));
|
||||
assert_eq!(view.retry_count(), 2);
|
||||
assert!(view.blocked());
|
||||
assert_eq!(view.depends_on(), &[100, 200]);
|
||||
|
||||
// Content is stored verbatim (no parsing, no rewrite).
|
||||
@@ -416,7 +407,6 @@ mod tests {
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
write_content(
|
||||
story_id,
|
||||
|
||||
+7
-15
@@ -18,7 +18,6 @@ pub struct ItemMeta {
|
||||
pub name: Option<String>,
|
||||
pub agent: Option<String>,
|
||||
pub retry_count: Option<i64>,
|
||||
pub blocked: Option<bool>,
|
||||
pub depends_on: Option<Vec<u32>>,
|
||||
}
|
||||
|
||||
@@ -50,12 +49,11 @@ fn normalise_stage_str(stage: &str) -> &str {
|
||||
"3_qa" => "qa",
|
||||
"4_merge" => "merge",
|
||||
"4_merge_failure" => "merge_failure",
|
||||
"4_merge_failure_final" => "merge_failure_final",
|
||||
"5_done" => "done",
|
||||
"6_archived" => "archived",
|
||||
// `7_frozen` has no direct clean equivalent (the variant was
|
||||
// removed in story 934 stage 4). Returning the unmapped string
|
||||
// makes `Stage::from_dir` return None, so the write is logged and
|
||||
// skipped — frozen items should be seeded via the `frozen` flag.
|
||||
"7_frozen" => "frozen",
|
||||
"7_review_hold" => "review_hold",
|
||||
other => other,
|
||||
}
|
||||
}
|
||||
@@ -94,7 +92,6 @@ pub fn write_item_with_content(story_id: &str, stage: &str, content: &str, meta:
|
||||
meta.name.as_deref(),
|
||||
meta.agent.as_deref(),
|
||||
meta.retry_count,
|
||||
meta.blocked,
|
||||
depends_on_json.as_deref(),
|
||||
None,
|
||||
None,
|
||||
@@ -109,7 +106,6 @@ pub fn write_item_with_content(story_id: &str, stage: &str, content: &str, meta:
|
||||
name: meta.name,
|
||||
agent: meta.agent,
|
||||
retry_count: meta.retry_count,
|
||||
blocked: meta.blocked,
|
||||
depends_on: depends_on_json,
|
||||
content: Some(content.to_string()),
|
||||
};
|
||||
@@ -139,10 +135,10 @@ pub fn move_item_stage(
|
||||
_ => None,
|
||||
};
|
||||
|
||||
// Story 929: metadata (name/agent/blocked/depends_on) is owned by the
|
||||
// CRDT typed registers — no need to re-derive it from the content body's
|
||||
// YAML front matter on every stage transition. Pass `None` for those
|
||||
// fields so write_item leaves the existing registers untouched.
|
||||
// Story 929: metadata (name/agent/depends_on) is owned by the CRDT typed
|
||||
// registers — no need to re-derive it from the content body's YAML front
|
||||
// matter on every stage transition. Pass `None` for those fields so
|
||||
// write_item leaves the existing registers untouched.
|
||||
let new_stage = normalise_stage_str(new_stage);
|
||||
let Some(typed_stage) = crate::pipeline_state::Stage::from_dir(new_stage) else {
|
||||
crate::slog!(
|
||||
@@ -161,7 +157,6 @@ pub fn move_item_stage(
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
merged_at_ts,
|
||||
);
|
||||
// Bug 780: stage transitions reset retry_count to 0. retry_count tracks
|
||||
@@ -177,7 +172,6 @@ pub fn move_item_stage(
|
||||
let view = crate::crdt_state::read_item(story_id);
|
||||
let name = view.as_ref().and_then(|v| v.name().map(str::to_string));
|
||||
let agent = view.as_ref().and_then(|v| v.agent().map(str::to_string));
|
||||
let blocked = view.as_ref().map(|v| v.blocked());
|
||||
let depends_on = view
|
||||
.as_ref()
|
||||
.map(|v| v.depends_on())
|
||||
@@ -189,7 +183,6 @@ pub fn move_item_stage(
|
||||
name,
|
||||
agent,
|
||||
retry_count: Some(0),
|
||||
blocked,
|
||||
depends_on,
|
||||
content,
|
||||
};
|
||||
@@ -212,7 +205,6 @@ pub fn delete_item(story_id: &str) {
|
||||
name: None,
|
||||
agent: None,
|
||||
retry_count: None,
|
||||
blocked: None,
|
||||
depends_on: None,
|
||||
content: None,
|
||||
};
|
||||
|
||||
@@ -18,7 +18,6 @@ pub(super) struct PipelineWriteMsg {
|
||||
pub(super) name: Option<String>,
|
||||
pub(super) agent: Option<String>,
|
||||
pub(super) retry_count: Option<i64>,
|
||||
pub(super) blocked: Option<bool>,
|
||||
pub(super) depends_on: Option<String>,
|
||||
pub(super) content: Option<String>,
|
||||
}
|
||||
@@ -84,14 +83,13 @@ pub async fn init(db_path: &Path) -> Result<(), sqlx::Error> {
|
||||
let now = chrono::Utc::now().to_rfc3339();
|
||||
let result = sqlx::query(
|
||||
"INSERT INTO pipeline_items \
|
||||
(id, name, stage, agent, retry_count, blocked, depends_on, content, created_at, updated_at) \
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?9) \
|
||||
(id, name, stage, agent, retry_count, depends_on, content, created_at, updated_at) \
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?8) \
|
||||
ON CONFLICT(id) DO UPDATE SET \
|
||||
name = excluded.name, \
|
||||
stage = excluded.stage, \
|
||||
agent = excluded.agent, \
|
||||
retry_count = excluded.retry_count, \
|
||||
blocked = excluded.blocked, \
|
||||
depends_on = excluded.depends_on, \
|
||||
content = COALESCE(excluded.content, pipeline_items.content), \
|
||||
updated_at = excluded.updated_at",
|
||||
@@ -101,7 +99,6 @@ pub async fn init(db_path: &Path) -> Result<(), sqlx::Error> {
|
||||
.bind(&msg.stage)
|
||||
.bind(&msg.agent)
|
||||
.bind(msg.retry_count)
|
||||
.bind(msg.blocked.map(|b| b as i64))
|
||||
.bind(&msg.depends_on)
|
||||
.bind(&msg.content)
|
||||
.bind(&now)
|
||||
|
||||
Reference in New Issue
Block a user