FN-8444: include planning time in task metrics
Track active planning time alongside execution time for costs, analytics, and task displays. - Persist planning timing state across task lifecycle transitions and recovery - Include planning activity in token cost, analytics, and dashboard timing displays - Add PostgreSQL migration support using the configured migration directory Files changed: .changeset/fn-8444-planning-time-cost.md | 7 +++ docs/dashboard-guide.md | 3 ++ docs/task-management.md | 5 ++ packages/core/src/index.ts | 1 + .../migrations/0029_planning_active_timing.sql | 3 ++ packages/core/src/postgres/schema-applier.ts | 14 ++++- packages/core/src/postgres/schema/project.ts | 2 + packages/core/src/productivity-analytics.ts | 29 +++++----- packages/core/src/store.ts | 2 +- .../core/src/task-store/archive-lifecycle-2.ts | 2 + packages/core/src/task-store/moves.ts | 7 +++ packages/core/src/task-store/persistence.ts | 4 ++ packages/core/src/task-store/remaining-ops-2.ts | 2 +- packages/core/src/task-store/serialization.ts | 7 +++ packages/core/src/task-store/task-row-mappers.ts | 2 +- packages/core/src/task-store/task-update.ts | 10 ++++ packages/core/src/task-timing.ts | 35 ++++++++++++ packages/core/src/types.ts | 12 +++++ packages/dashboard/app/components/TaskCard.tsx | 13 ++--- .../app/components/TaskTokenStatsPanel.tsx | 6 ++- .../app/components/__tests__/TaskCard.test.tsx | 17 ++++++ .../app/utils/__tests__/taskTiming.test.ts | 9 +++- packages/dashboard/app/utils/taskTiming.ts | 14 +++++ packages/dashboard/app/utils/taskTokenCost.ts | 2 + .../dashboard/src/task-planner-chat-metrics.ts | 14 ++++- packages/engine/src/__tests__/self-healing.test.ts | 61 +++++++++++++++++++++ packages/engine/src/executor.ts | 50 +++++++++++++++++ packages/engine/src/runtimes/in-process-runtime.ts | 3 ++ packages/engine/src/self-healing.ts | 62 ++++++++++++++++++++++ packages/engine/src/triage.ts | 10 ++++ packages/i18n/locales/en/app.json | 2 +- packages/i18n/locales/es/app.json | 2 +- packages/i18n/locales/fr/app.json | 2 +- packages/i18n/locales/ko/app.json | 2 +- packages/i18n/locales/zh-CN/app.json | 2 +- packages/i18n/locales/zh-TW/app.json | 2 +- 36 files changed, 384 insertions(+), 36 deletions(-) Fusion-Task-Id: FN-8444 Fusion-Task-Lineage: 0178e0a7-3018-4ef4-be9b-6de5f964fb58 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
-- FNXC:TaskTiming 2026-08-01-10:00: durable planning AI session accounting.
|
||||
ALTER TABLE project.tasks ADD COLUMN IF NOT EXISTS cumulative_planning_ms bigint;
|
||||
ALTER TABLE project.tasks ADD COLUMN IF NOT EXISTS planning_started_at text;
|
||||
@@ -37,7 +37,7 @@ FNXC:PostgresBigintCounters 2026-07-19-12:00:
|
||||
SCHEMA_BASELINE_VERSION advances to 0026 for the bigint counters migration.
|
||||
Per-migration identities above stay fixed; only this latest-version marker moves.
|
||||
*/
|
||||
export const SCHEMA_BASELINE_VERSION = "0028";
|
||||
export const SCHEMA_BASELINE_VERSION = "0029";
|
||||
/** FNXC:SymbolLock 2026-07-31-10:00: upgrades need durable task declarations before admission resolves symbols. */
|
||||
export const TASK_DECLARED_SYMBOLS_VERSION = "0028";
|
||||
const INITIAL_SCHEMA_VERSION = "0000";
|
||||
@@ -124,6 +124,8 @@ export const TASK_VERIFICATION_REQUEST_VERSION = "0024";
|
||||
export const SYMBOL_LOCKS_SCHEMA_VERSION = "0025";
|
||||
/** FNXC:PostgresBigintCounters 2026-07-18-21:45: widen overflow-prone counters to bigint before SQLite migration. */
|
||||
export const BIGINT_COUNTERS_VERSION = "0026";
|
||||
/** FNXC:TaskTiming 2026-08-01-10:00: existing clusters need planning-session timing columns. */
|
||||
export const PLANNING_ACTIVE_TIMING_VERSION = "0029";
|
||||
|
||||
/**
|
||||
* Thrown when the database was migrated by a NEWER Fusion binary than the one now
|
||||
@@ -312,6 +314,8 @@ const WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_MIGRATION_PATH = join(
|
||||
MIGRATIONS_DIR,
|
||||
"0027_workflow_ir_pin_and_legacy_adoption.sql",
|
||||
);
|
||||
|
||||
const PLANNING_ACTIVE_TIMING_MIGRATION_PATH = join(MIGRATIONS_DIR, "0029_planning_active_timing.sql");
|
||||
const TASK_DECLARED_SYMBOLS_MIGRATION_PATH = join(MIGRATIONS_DIR, "0028_task_declared_symbols.sql");
|
||||
|
||||
/**
|
||||
@@ -409,6 +413,7 @@ export async function applySchemaBaseline(
|
||||
const symbolLocksAlreadyApplied = applied.includes(SYMBOL_LOCKS_SCHEMA_VERSION);
|
||||
const bigintCountersAlreadyApplied = applied.includes(BIGINT_COUNTERS_VERSION);
|
||||
const workflowIrPinAndLegacyAdoptionAlreadyApplied = applied.includes(WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_VERSION);
|
||||
const planningActiveTimingAlreadyApplied = applied.includes(PLANNING_ACTIVE_TIMING_VERSION);
|
||||
assertBinaryNotOlderThanDatabase(applied);
|
||||
let schemaChanged = false;
|
||||
|
||||
@@ -830,6 +835,13 @@ export async function applySchemaBaseline(
|
||||
baseline so databases that already recorded 0000 gain the IR-pin and adoption columns;
|
||||
without the forward migration those clusters crash on the first slim TaskStore SELECT.
|
||||
*/
|
||||
if (!planningActiveTimingAlreadyApplied) {
|
||||
const migrationSql = await readFile(PLANNING_ACTIVE_TIMING_MIGRATION_PATH, "utf8");
|
||||
await tx.execute(sql.raw(migrationSql));
|
||||
await tx.execute(sql`INSERT INTO public.${sql.identifier(MIGRATION_BOOKKEEPING_TABLE)} (version) VALUES (${PLANNING_ACTIVE_TIMING_VERSION}) ON CONFLICT (version) DO NOTHING`);
|
||||
schemaChanged = true;
|
||||
}
|
||||
|
||||
if (!workflowIrPinAndLegacyAdoptionAlreadyApplied) {
|
||||
const migrationSql = await readFile(WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_MIGRATION_PATH, "utf8");
|
||||
await tx.execute(sql.raw(migrationSql));
|
||||
|
||||
@@ -178,6 +178,8 @@ export const tasks = projectSchema.table("tasks", {
|
||||
columnMovedAt: text("column_moved_at"),
|
||||
firstExecutionAt: text("first_execution_at"),
|
||||
cumulativeActiveMs: bigint("cumulative_active_ms", { mode: "number" }),
|
||||
cumulativePlanningMs: bigint("cumulative_planning_ms", { mode: "number" }),
|
||||
planningStartedAt: text("planning_started_at"),
|
||||
/*
|
||||
FNXC:PostgresMigrationColumnCoverage 2026-07-14-13:17:
|
||||
Keep the task schema aligned with late SQLite lifecycle migrations. JSON lifecycle markers stay jsonb for native backend reads; retired board/question fields remain text so their legacy payloads round-trip byte-for-byte.
|
||||
|
||||
Reference in New Issue
Block a user