Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .zed/rules
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ refactor:
1. Check for an existing issue — search Linear for a corresponding issue.
2. If none exists — ask the developer whether to create one. Do not proceed without
either a linked issue or explicit approval to skip.
3. When a new issue is discovered during development (bug, design problem, deferred
3. When starting work on an issue — update its Linear status to "In Progress".
4. When a new issue is discovered during development (bug, design problem, deferred
work), create a corresponding Linear issue using the template below.

When creating Linear issues, always use this template for the description:
Expand Down Expand Up @@ -96,6 +97,9 @@ Remove any optional sections that don't apply rather than leaving them empty.
When working on a feature, create and checkout a git branch using the gitBranchName
returned by the primary Linear issue (e.g. eywalker/plt-911-add-documentation-for-orcapod-python).

Feature branch PRs always target the "dev" branch. The dev → main PR is used
for versioning/releases only.

If a feature branch / PR corresponds to multiple Linear issues, list all of them in the
PR description body so that Linear's GitHub integration auto-tracks the PR against each
issue. Use the format "Fixes PLT-123" or "Closes PLT-123" (GitHub magic words) for issues
Expand Down
6 changes: 5 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ refactor:
1. **Check for an existing issue** — search Linear for a corresponding issue.
2. **If none exists** — ask the developer whether to create one. Do not proceed without
either a linked issue or explicit approval to skip.
3. **When a new issue is discovered** during development (bug, design problem, deferred
3. **When starting work on an issue** — update its Linear status to **In Progress**.
4. **When a new issue is discovered** during development (bug, design problem, deferred
work), create a corresponding Linear issue using the template below.

When creating Linear issues, always use this template for the description:
Expand Down Expand Up @@ -102,6 +103,9 @@ Remove any optional sections that don't apply rather than leaving them empty.
When working on a feature, create and checkout a git branch using the `gitBranchName`
returned by the primary Linear issue (e.g. `eywalker/plt-911-add-documentation-for-orcapod-python`).

**Feature branch PRs always target the `dev` branch.** The `dev` → `main` PR is used
for versioning/releases only.

If a feature branch / PR corresponds to multiple Linear issues, list all of them in the
PR description body so that Linear's GitHub integration auto-tracks the PR against each
issue. Use the format `Fixes PLT-123` or `Closes PLT-123` (GitHub magic words) for issues
Expand Down
20 changes: 20 additions & 0 deletions DESIGN_ISSUES.md
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,26 @@ For derived sources (e.g., `DerivedSource`), the stream may not have a meaningfu

---

## `src/orcapod/core/cached_function_pod.py` / `src/orcapod/core/result_cache.py`

### RC1 — `ResultCache.record_path` not overridable via public API
**Status:** open
**Severity:** medium

When loading a pipeline with a `PacketFunctionProxy` (PLT-931), the
`CachedFunctionPod`'s `record_path` may differ from the original because the
pod-level URI is recomputed from a deserialized schema (whose semantic hash
may diverge from the original due to the `Python type → Arrow string → Python type`
round-trip). The workaround reaches into private fields:
`node._cached_function_pod._cache._record_path = stored_path`.

**Fix:** Add a public `override_record_path(path)` method to `CachedFunctionPod`
(or `ResultCache`) that validates and sets the record path. Alternatively, accept
an optional `record_path_override` in `CachedFunctionPod.__init__` that takes
precedence over the computed path when provided.

---

## `src/orcapod/core/nodes/` — Config and context delegation chain

### T2 — `orcapod_config` not on any protocol; delegation chain needs review
Expand Down
13 changes: 11 additions & 2 deletions src/orcapod/core/function_pod.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,19 +295,28 @@ def to_config(self) -> dict[str, Any]:
return config

@classmethod
def from_config(cls, config: dict[str, Any]) -> "FunctionPod":
def from_config(
cls,
config: dict[str, Any],
*,
fallback_to_proxy: bool = False,
) -> "FunctionPod":
"""Reconstruct a FunctionPod from a config dict.

Args:
config: A dict as produced by :meth:`to_config`.
fallback_to_proxy: If ``True`` and the packet function cannot be
resolved, use a ``PacketFunctionProxy`` instead of raising.

Returns:
A new ``FunctionPod`` instance.
"""
from orcapod.pipeline.serialization import resolve_packet_function_from_config

pf_config = config["packet_function"]
packet_function = resolve_packet_function_from_config(pf_config)
packet_function = resolve_packet_function_from_config(
pf_config, fallback_to_proxy=fallback_to_proxy
)

node_config = None
if config.get("node_config") is not None:
Expand Down
15 changes: 11 additions & 4 deletions src/orcapod/core/nodes/function_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,23 +224,30 @@ def from_descriptor(
pipeline_path = tuple(descriptor.get("pipeline_path", ()))
# Derive pipeline_path_prefix by stripping the suffix that
# __init__ appends (packet_function.uri + node hash element).
# We pass the full pipeline_path_prefix from the descriptor.
# The descriptor stores the complete pipeline_path; we need
# to reconstruct the prefix that was originally passed to
# __init__. The suffix added is: pf.uri + (f"node:{hash}",).
# Instead of reverse-engineering, use the descriptor's path
# minus what __init__ will add. For full mode we let __init__
# recompute pipeline_path from the prefix.
pf_uri_len = len(function_pod.packet_function.uri) + 1 # +1 for node:hash
prefix = (
pipeline_path[:-pf_uri_len] if len(pipeline_path) > pf_uri_len else ()
)

# Derive result_path_prefix from the stored result_record_path
# by stripping the URI suffix that CachedFunctionPod appends.
stored_result_path = tuple(
descriptor.get("result_record_path", ())
)
uri_len = len(function_pod.packet_function.uri)
result_prefix: tuple[str, ...] | None = None
if stored_result_path and len(stored_result_path) > uri_len:
result_prefix = stored_result_path[:-uri_len]

node = cls(
function_pod=function_pod,
input_stream=input_stream,
pipeline_database=pipeline_db,
result_database=result_db,
result_path_prefix=result_prefix,
pipeline_path_prefix=prefix,
label=descriptor.get("label"),
)
Expand Down
1 change: 1 addition & 0 deletions src/orcapod/core/packet_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,7 @@ def to_config(self) -> dict[str, Any]:
"""
return {
"packet_function_type_id": self.packet_function_type_id,
"uri": list(self.uri),
"config": {
"module_path": self._function.__module__,
"callable_name": self._function_name,
Expand Down
Loading
Loading