fix(data): populate ownerDefinition.jobName on workflow step output (swamp-club#237)#1301
fix(data): populate ownerDefinition.jobName on workflow step output (swamp-club#237)#1301
Conversation
…swamp-club#237) Workflow step output data had `ownerDefinition.jobName` always empty, so `swamp data query 'jobName == "..."'` returned 0 rows even though the CEL schema and `design/data-query.md:128` advertise it as a queryable provenance field. Two missing links in the existing provenance pipeline: - `workflowTagOverrides` in execution_service.ts set workflow / workflowRunId / step / source but no `job` tag. - Both `data_writer.ts` factories translated `step → stepName`, `workflow → workflowName`, `source → source` but had no `job → jobName` mapping. This fix mirrors the surrounding `step → stepName` plumbing exactly. No schema change, no migration: `OwnerDefinition.jobName?` already exists, the catalog column is already there, the CEL field is already advertised. This change makes the code match the documented contract. Forward-only: data created before this fix retains empty `jobName`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
Clean, well-scoped bug fix. The change correctly mirrors the existing step → stepName plumbing to add the missing job → jobName mapping in two places (execution_service.ts tag overrides, data_writer.ts factories), which is the minimal fix for the documented contract drift.
Blocking Issues
None.
Suggestions
- The integration test comment block (lines 216–220 of
workflow_query_data_context_test.ts) references the issue number and explains the historical bug context. Per CLAUDE.md, comments should explain the why of the current code rather than reference specific issues — the issue context belongs in the commit message (which already has it). Consider trimming to just the contract being pinned, e.g.// Pins the read-path contract that all three provenance fields are queryable via top-level CEL identifiers.Minor style nit, not blocking.
DDD review: Changes are properly scoped within the domain layer. execution_service.ts (domain service) correctly enriches the tag overrides, and data_writer.ts (factory) correctly maps them onto the OwnerDefinition value object. No aggregate or repository boundary violations. The fix is additive with no schema changes — forward-only semantics are appropriate.
Test coverage: Excellent — unit tests cover both the positive case (jobName populated) and the negative case (jobName omitted when tag absent) for both createResourceWriter and createFileWriterFactory. Integration test verifies the full CEL query path for all three provenance fields.
Security: No concerns — the change only threads an existing string value through an existing pipeline with no new user-facing input surface.
Convention compliance: License headers present, withTempDir uses the Windows EBUSY .catch(() => {}) pattern, no libswamp import boundary violations, test naming follows the functionName: describes behavior convention.
There was a problem hiding this comment.
Adversarial Review
Critical / High
None.
Medium
None.
Low
-
integration/workflow_query_data_context_test.ts:242-261 — The integration test seeds
ownerDefinition.jobNamedirectly viaData.create(), so it validates the CEL query/read path but does not exercise the write path throughcreateResourceWriterorcreateFileWriterFactoryend-to-end. The unit tests indata_writer_test.tscover the write path, so this is not a gap in coverage — just worth noting that the integration test alone wouldn't catch a regression in thetagOverrides → ownerDefinitionmapping. -
src/domain/models/data_writer_test.ts — There is a negative test for the resource writer (
omits ownerDefinition.jobName when not in tagOverrides) but no corresponding negative test for the file writer factory. Symmetry with the existingworkflowRunIdtest pattern would suggest adding one, but the code paths are structurally identical, so the risk is near-zero.
Verdict
PASS — This is a clean, mechanical fix that mirrors the existing workflow → workflowName, step → stepName plumbing pattern exactly. Both construction sites in data_writer.ts are patched. ctx.jobName is a non-optional string validated with .min(1) by the JobSchema, so the truthy check in tagOverrides?.["job"] is always correct. All downstream consumers already use ?? "" fallback. The semantic shift for jobName == "" queries is intentional and documented. No issues found.
Summary
ownerDefinition.jobNamealways empty, soswamp data query 'jobName == "..."'returned 0 rows despite the field being advertised in the CEL schema and documented indesign/data-query.md:128.workflowTagOverridesnever carriedjob, anddata_writer.tsfactories never translatedjob → jobName. This change mirrors the surroundingstep → stepNameplumbing exactly.OwnerDefinition.jobName?, the catalog column, and the CEL field were all already in place.Risk
Low and additive.
tags.jobis a new key;rg 'tags\\.job'returns 0 hits acrosssrc/,integration/, andpackages/. All consumers ofownerDefinition.jobNamealready use?? ""fallback. One narrow semantic shift: ajobName == ""predicate previously matched all workflow data and now matches only non-workflow data — butdesign/data-query.mdalready documentsjobNameas""outside workflows, so any caller relying on the broken semantics was already operating against the documented contract. No internal callers do this.Forward-only
Data created before this fix retains empty
jobNameon disk; new workflow runs populate it. No migration is included — provenance backfill from old data is out of scope and tracked separately.Test plan
data_writer_test.tsfor both resource and file factories —jobNamepopulated whentagOverrides.jobis supplied, omitted when not.workflow_query_data_context_test.tsasserts all three CEL provenance predicates (workflowName,jobName,stepName) resolve fromownerDefinition./tmp/swamp-repro-issue-237. Before:jobName == "greet-job"→ 0 results. After: 2 rows,jobName: "greet-job". Other three queries unchanged.deno check/deno lint/deno fmtclean.deno run test— 5405 passed, 0 failed.Closes swamp-club#237.
🤖 Generated with Claude Code