Skip to content

refactor: unnest task runs, have parent id instead#1176

Merged
leonardmq merged 2 commits into
mainfrom
leonard/kil-490-refactor-unnest-taskruns
Mar 31, 2026
Merged

refactor: unnest task runs, have parent id instead#1176
leonardmq merged 2 commits into
mainfrom
leonard/kil-490-refactor-unnest-taskruns

Conversation

@leonardmq

@leonardmq leonardmq commented Mar 28, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do?

Rollback #1126 that was nesting TaskRuns into each other through our parenting system. Instead, we do it through having a parent id on the task run, which will simplify.

Checklists

  • Tests have been run locally and passed
  • New tests have been added to any work in /lib

Summary by CodeRabbit

  • New Features

    • API now exposes an optional parent run ID on run records (parent_task_run_id) so runs can reference their parent explicitly.
  • Refactor

    • Run storage flattened: all runs live under tasks with explicit parent-run references instead of nested run-as-parent folders.
  • Bug Fixes

    • Validation and loading paths simplified; error messages and persistence checks updated for clearer failure cases.
  • Tests

    • Test suites updated to assert parent_run_id semantics and new flattened run behavior.

@coderabbitai

coderabbitai Bot commented Mar 28, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 25222d28-0133-4f9f-8753-a2ce03aaffc3

📥 Commits

Reviewing files that changed from the base of the PR and between cab8cd8 and 12d345d.

📒 Files selected for processing (2)
  • libs/core/kiln_ai/adapters/model_adapters/base_adapter.py
  • libs/core/kiln_ai/adapters/model_adapters/test_saving_adapter_results.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • libs/core/kiln_ai/adapters/model_adapters/test_saving_adapter_results.py

Walkthrough

Refactors TaskRun to remove nested TaskRun-as-parent support: TaskRuns are now always children of Tasks and may reference a parent run via a new parent_task_run_id field; polymorphic parent-type validation and related traversal methods were removed; adapter and tests updated to use the new field.

Changes

Cohort / File(s) Summary
API Schema
app/web_ui/src/lib/api_schema.d.ts
Added optional parent_task_run_id to TaskRun-Input and TaskRun-Output; removed docs referencing nested TaskRun parentage.
Adapter Layer
libs/core/kiln_ai/adapters/model_adapters/base_adapter.py, libs/core/kiln_ai/adapters/model_adapters/test_saving_adapter_results.py
BaseAdapter.generate_run() now always sets TaskRun.parent = self.task and sets parent_task_run_id (or raises if provided parent run has no id); tests updated to assert parent_task_run_id semantics and new error case.
Base datamodel
libs/core/kiln_ai/datamodel/basemodel.py
Removed polymorphic parent extension points (_parent_types, _check_parent_type); consolidated parent-type validation to a single post-validator and simplified child-path iteration to load a single parent type.
Task & TaskRun datamodels
libs/core/kiln_ai/datamodel/task.py, libs/core/kiln_ai/datamodel/task_run.py
Deleted TaskRun DFS lookup and nested-parent APIs; removed KilnParentModel inheritance from TaskRun; added `parent_task_run_id: str
Tests — datamodel
libs/core/kiln_ai/datamodel/test_basemodel.py, libs/core/kiln_ai/datamodel/test_models.py, libs/core/kiln_ai/datamodel/test_task.py
Extensive test updates to validate flat TaskRun hierarchy using parent_task_run_id; removed or replaced polymorphic-parent and nested-run tests; updated error-expectations and path-loading assertions.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • scosman
  • sfierro
  • chiang-daniel

Poem

🐰 I hopped through code with nimble pride,
Turned tangled nests to paths that glide,
A tiny id now links the run,
Flat fields sparkle in morning sun,
Hooray for clarity—hop, hop, wide!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'refactor: unnest task runs, have parent id instead' accurately and concisely describes the main change: removing TaskRun nesting via the parenting system and replacing it with a parent_task_run_id field.
Description check ✅ Passed The description clearly explains the rollback of PR #1126 and introduces the parent_id approach. However, it is missing the 'Related Issues' section and the Contributor License Agreement confirmation mentioned in the template.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch leonard/kil-490-refactor-unnest-taskruns

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@leonardmq leonardmq marked this pull request as draft March 28, 2026 08:32

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the TaskRun data model to use a flat storage structure instead of a nested file system hierarchy. TaskRun objects now reside directly under their parent Task and maintain lineage through a new parent_task_run_id field. This change simplifies the codebase by removing complex polymorphic parent logic, custom parent loading overrides, and expensive recursive file system traversals. Feedback was provided regarding a potential performance regression in parent type validation during child iteration, suggesting an optimization to avoid full model loading.

Comment thread libs/core/kiln_ai/datamodel/basemodel.py
@github-actions

github-actions Bot commented Mar 28, 2026

Copy link
Copy Markdown

📊 Coverage Report

Overall Coverage: 91%

Diff: origin/main...HEAD

  • libs/core/kiln_ai/adapters/model_adapters/base_adapter.py (100%)
  • libs/core/kiln_ai/datamodel/basemodel.py (100%)
  • libs/core/kiln_ai/datamodel/task_run.py (100%)

Summary

  • Total: 16 lines
  • Missing: 0 lines
  • Coverage: 100%

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@libs/core/kiln_ai/adapters/model_adapters/base_adapter.py`:
- Around line 609-612: The code is using parent_task_run.id as
parent_task_run_id even when parent_task_run may be unsaved (TaskRun.id can be
cleared later), which risks dangling references; modify the block that sets
parent=self.task and parent_task_run_id to first verify parent_task_run is saved
(e.g., check parent_task_run is not None and parent_task_run.id is not None) and
if it is unsaved either raise a clear exception (ValueError) instructing callers
to persist the parent TaskRun first or explicitly persist/save the
parent_task_run before reading its id; ensure you reference and guard the
parent_task_run and parent_task_run_id usage in the same method so no transient
IDs are passed through.

In `@libs/core/kiln_ai/datamodel/basemodel.py`:
- Around line 614-616: The code currently calls
cls.parent_type().load_from_file(parent_path) unconditionally which will try to
open a directory when parent_path is a folder; first check whether parent_path
is a directory (os.path.isdir(parent_path)) and if so handle it before calling
load_from_file: if the parent type provides a directory loader (e.g., a
load_from_dir or similar on cls.parent_type()), call that with parent_path;
otherwise locate a concrete file inside the directory (e.g., the first matching
child file) and pass that file path into
cls.parent_type().load_from_file(parent_file_path); ensure the variable names
referenced are parent_path, cls.parent_type(), and load_from_file so the change
is easy to find.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4be709ad-9f92-4c04-a320-2e66bec504f6

📥 Commits

Reviewing files that changed from the base of the PR and between af2c37e and cab8cd8.

📒 Files selected for processing (9)
  • app/web_ui/src/lib/api_schema.d.ts
  • libs/core/kiln_ai/adapters/model_adapters/base_adapter.py
  • libs/core/kiln_ai/adapters/model_adapters/test_saving_adapter_results.py
  • libs/core/kiln_ai/datamodel/basemodel.py
  • libs/core/kiln_ai/datamodel/task.py
  • libs/core/kiln_ai/datamodel/task_run.py
  • libs/core/kiln_ai/datamodel/test_basemodel.py
  • libs/core/kiln_ai/datamodel/test_models.py
  • libs/core/kiln_ai/datamodel/test_task.py
💤 Files with no reviewable changes (1)
  • libs/core/kiln_ai/datamodel/task.py

Comment thread libs/core/kiln_ai/adapters/model_adapters/base_adapter.py Outdated
Comment thread libs/core/kiln_ai/datamodel/basemodel.py
@leonardmq leonardmq marked this pull request as ready for review March 30, 2026 17:18
default=None,
description="The trace of the task run in OpenAI format. This is the list of messages that were sent to/from the model.",
)
parent_task_run_id: str | None = Field(

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only real addition in this class in this PR, the rest is undoing what had been added in #1126

return None
return self.parent # type: ignore

def find_task_run_by_id_dfs(

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was added in #1126, no longer needed since we flatten all TaskRuns and don't nest them in directory structures now

self,
expected_parent_types: List[Type[KilnBaseModel]] | None = None,
) -> Self:
@model_validator(mode="after")

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file diff only undoes what was added in #1126

@chiang-daniel

Copy link
Copy Markdown
Contributor

Do we need to do anything for existing task runs that have embedded task runs?

@leonardmq

leonardmq commented Mar 31, 2026

Copy link
Copy Markdown
Collaborator Author

Do we need to do anything for existing task runs that have embedded task runs?

There are none right now - that was not being used by anybody (except me for multiturn chat)

@chiang-daniel

@leonardmq leonardmq merged commit 92076e0 into main Mar 31, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants