Skip to content

feat: fix target system live property - #42

Merged
brunozoric merged 28 commits into
mainfrom
bruno/feat/fix-target-system-live-property
Sep 7, 2026
Merged

feat: fix target system live property#42
brunozoric merged 28 commits into
mainfrom
bruno/feat/fix-target-system-live-property

Conversation

@brunozoric

Copy link
Copy Markdown
Contributor

No description provided.

brunozoric and others added 23 commits September 4, 2026 08:52
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…n plans

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…S.md

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…eld version guard

OsProcessor.querySourceRecord/queryTargetRecord now return the companion-table
row with data decompressed (same shape OsScanner yields), so addLiveField reads
the published revision's version correctly for draft-over-published entries.

addLiveField now uses readPositiveIntegerVersion (root then data fallback),
cache check is !== undefined instead of truthiness, and non-integer versions
produce live: null with a warning instead of live: { version: undefined }.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…o IDynamoDbClient

updateAttribute does a conditional SET on a single attribute path, returning
"written" or "condition-failed" (ConditionalCheckFailedException is caught,
never retried). ScanOptions.limit stops the generator after N yielded items;
sortKeyEquals adds a server-side FilterExpression. MockDynamoDbClient updated
to support all three.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Appends line + newline, creating parent directory. Used by ChangeReport
to write fix-live audit trail entries as they happen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pure decision logic: given a group of L, P, and REV# records for one PK,
decides which records need their data.live field filled, cleared, or fixed.
24 test cases cover all skip conditions (no-L, invalid version, status
contradictions, missing/mismatched REV#) and change reasons (missing-live,
empty-live, wrong-version, stale-live). OS table skips REV# checks.

Abstractions define the contract for runners (DDB/OS), ChangeReport (JSONL
audit trail), and FixLiveState (dry-run gate).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Appends one JSON line per change/skip event under
.transfer/<runId>/fix-live-report.jsonl. Undefined before values are
serialized as null. Test container and MockChangeReport for runner tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
FixLiveState reads/writes .transfer/state/fix-live/<project>__<system>.json.
recordDryRun and recordLiveRun preserve each other's data. FixLiveFeature
registers LiveFieldReconciler, ChangeReport, and FixLiveState.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…strap wiring

BaseLiveFieldRunner: scan L rows per segment → queryAll full PK group →
prepareGroup → reconciler.decide → conditional UpdateItem (or dry-run report).
DdbLiveFieldRunner writes ["data","live"] only, filters internal models.

Helpers: createEmptyStats (zero-initialized reason counters), runConcurrently
(bounded worker pool), cmsEntryGuards (isCmsEntryRow, isInternalModel).

FixLiveFeature now registered in bootstrap.ts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three tests against a real DynamoDB (dynalite): dry-run leaves the table
unchanged, live-run writes data.live via conditional UpdateItem (verifies
empty-string preservation via convertEmptyValues and _md unchanged),
condition-failed via MdBumpingClient proxy reports changed-during-run.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ompresses

OS subclass: acceptsRow always passes (modelId is inside the blob),
prepareGroup decompresses all rows and filters internal models after,
buildWrite recompresses the full data blob with only live changed.
Decompress failure → skipped group with decompress-failed reason.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two tests against dynalite with real gzip: dry-run reports empty-live on L
and leaves the table unchanged, live-run rewrites the L blob with only live
changed and verifies P blob is untouched and idempotent re-run finds nothing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…entations

Every prompt method returns null on cancel (never exits). ClackPrompts,
ClackUI, ClackSpinner wrap @clack/prompts; commands never import the library
directly. StubPrompts/StubUI for tests with scripted answers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
One Cli/Command token with many implementations; CommandRegistry collects
them lazily via resolveAll on first access. menu() filters hidden commands,
get() matches on the first token of the yargs command string.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… dispatch

Move commands/run/ to commands/transfer/; wrap all 5 commands as Command
implementations (transfer visible, init/init-project/process-segment/
update-skills hidden). New src/cli.ts registers all commands via the
CommandRegistry, adds a $0 [folder] default that preserves yarn transfer
<folder> and yarn transfer --config --preset, and falls back to a clack
select menu when invoked with no arguments. Cancel exits 130.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
StepOutcome<T> discriminated union (ok/cancelled/refused) for guided flow
control. selectProject discovers projects and prompts or validates --project.
selectSystem prompts source/target with DDB+region+OS hints. confirmSystem
shows a summary note and asks for confirmation (--yes skips the prompt).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
guardV6 scans L rows to find a CMS entry and checks for root data object
(v6) vs flat fields (v5); refuses v5 tables before the confirm. selectMode
offers dry-run/live menu (live disabled without prior dry-run), confirms
with last-run summary. format helpers for count grouping and timestamps.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Full flow: selectProject → loadConfig → bootstrap → selectSystem →
guardV6 → confirmSystem → selectMode → runTable per DDB/OS →
recordDryRun/recordLiveRun → summarise. Resolves DdbLiveFieldRunner or
OsLiveFieldRunner directly. Registered in cliContainer as fix-live (visible
in menu after transfer). Exit 0/1/130.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Commands guide: add menu section, fix-live section with flags/report/state.
Troubleshooting: add published-not-showing-as-live entry. Hard-won decisions:
7 new entries for fix-live reconciler and CLI patterns. AGENTS.md: update
runtime flow for menu, mark fix-live as implemented, add open work items.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…in TransferWizard

TransferWizard now receives Prompts + UI via constructor injection.
All select/input/confirm calls use the abstraction; cancel returns null
instead of throwing ExitPromptError. Console output replaced with UI
methods. process.exit(1) replaced with thrown errors. Tests use
StubPrompts/StubUI with scripted answers.

@inquirer/core and @inquirer/prompts removed from dependencies.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread src/features/FixLive/LiveFieldReconciler.ts Fixed
brunozoric and others added 5 commits September 4, 2026 16:48
FixLiveCommand: 8 tests covering cancel at each step, --live without
dry run, --yes --dry-run flow, --table=os without OS, live with state.
TransferCommand: 4 tests covering --config+--preset, wizard null, wizard
result, name/hidden properties.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…, statements 81)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@brunozoric
brunozoric merged commit 9ea3519 into main Sep 7, 2026
5 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.

1 participant