# SDK operational completion and acceptance

This change adds a runnable company host to the existing Spring project runtime,
Connector Runtime and company-engine stores. It does not deploy the platform,
restore AWS, publish the package, or claim that a connected provider journey has
run merely because isolated tests pass.

## Start the company worker

Install the SDK wheel and authenticate with the normal `lightbulb` CLI device
flow against the intended control plane (`LIGHTBULB_URL`). On an expired session,
the worker reloads the configured/cached credential once, re-verifies the same
tenant and user, re-authorizes the selected company/project and retries. The
deployment must keep that cached identity renewable through its existing auth
mechanism. Keep a stable service identity: source evidence binds tenant,
selected company, user and project.

Prepare a compiled cadence bundle, a source-binding JSON array, and a host
receipt key file containing at least 32 random bytes. Keep the key file readable
only by the trusted host account. Do not put it in a bundle, MCP arguments,
checkpoint, repository or worker environment. Open the named protected cost,
demand, listing and content engine records using the central operator surface
before starting intake.

```bash
lightbulb-company-worker \
  --bundle /etc/lightbulb/company-bundle.json \
  --sources /etc/lightbulb/company-sources.json \
  --growth-config /etc/lightbulb/company-growth.json \
  --company-id "$COMPANY_ID" \
  --worker-ref company-worker-01 \
  --receipt-key-file /run/secrets/company-receipts \
  --receipt-key-id company-receipts-v1 \
  --register
```

Use `--once` for one supervised invocation. The normal process keeps polling
its own due checkpoint. Registration does not resume a company that an operator
paused. The exact selected project route must authorize the authenticated
company before the host creates stores, signs artifacts or dispatches reads.

The worker claims only its own `run_ref`. Spring owns the lease and revision;
the host authenticates the scheduling document and all child journals. A
project-checkpoint writer cannot alter the intake watermark, substitute a
provider read, manufacture a completed write or move an artifact to another
company. Replaying an older authentic journal cannot revoke an already executed
provider effect; stable server idempotency keys remain the recovery authority.
An unsigned legacy scheduler checkpoint must be explicitly migrated/re-registered
under a new reviewed operation; the worker does not silently trust it.

The worker follows the owner's amendments of the project's stored bundle (a
mandate, a plan):

- **Started with a replaced version.** A worker given a version the owner has
  since replaced runs the project's current bundle, validated against the same
  configuration.
- **Replaced while running.** The worker ticks nothing under the replaced
  version. It hands the checkpoint back due at once and reports
  `bundle_amended`, and the process rebuilds itself on the amendment.
- **Earlier records stay its own.** Records signed under an earlier version the
  project keeps are still this company's.
- **Keys don't move.** Journal keys stay rooted at the bundle the company's
  journals were first written under (`journal_root_digest` in the checkpoint).
  So a frozen sales touch, a queued signal, a billing ledger or a checkout
  carries on instead of starting over.

A worker given a bundle the project never kept runs it as given, and refuses
journals written under a bundle it neither runs nor keeps
(`HOST_JOURNAL_BUNDLE_NOT_ACCEPTED`). A wind-down's approvals bind the bundle it
was compiled against: after an amendment, compile it again and take both
approvals again.

## Recurring source bindings

`RecurringObservationBinding` is the executable configuration contract. Examples
below use placeholders for company-owned connector references and provider
objects. These are host configuration, never model-authored receipt claims.

```json
[
  {
    "source_ref": "google-media",
    "kind": "channel_spend",
    "tool": "google_ads.get_metrics",
    "connector_account_ref": "connected-google-ads",
    "arguments": {"customer_id": "1234567890", "segment": "campaign_daily"},
    "target_entity_ref": "company-costs-current-period",
    "centre_ref": "growth_engine",
    "channel": "paid_search_google",
    "demand_registry_ref": "demand-current-period",
    "pacing_controls": {}
  },
  {
    "source_ref": "measured-marketing-clicks",
    "kind": "marketing_touches",
    "tool": "posthog.query_events",
    "connector_account_ref": "connected-posthog",
    "arguments": {"project_id": "12345", "event": "marketing_click"},
    "event_bindings": {"marketing_click": {"channel": "paid_search_google"}},
    "identity_links": {}
  }
]
```

Populate `identity_links` from the company's authenticated identity mapping:
PostHog distinct-ID SHA-256 → the customer commitment used by the underlying
settled business record. Unmatched identities stay explicit; UTM strings and
aggregate metrics never create customer identities or revenue. Each normalized
touch is signed over the source request, result, journal, row and mapping, and
attribution re-verifies that evidence every time it replays a ledger. Legacy
unsigned touches are refused.

Populate `pacing_controls` before enabling demand-controlled media. Its keys
are provider campaign commitments; values are exact pause arguments:
`customer_id` + `resource_name` for Google, or `ad_account_id` + `campaign_id`
for Meta. The host verifies both account and campaign commitments against the
observed spend and durable reservation. Overspend is recorded honestly, new
reservations stop, and provider pauses enter the ordinary approval queue. A
missing target or unresolved approval prevents a claim of completed control.

Supported intake includes Google/Meta spend; PostHog touches; Business Profile
location, verification and performance; Search Console content observations;
and Shopify first-purchase cohort counts. Daily reports use closed UTC days
with explicit conversion to providers' inclusive end dates. A bundle with intake
must start at UTC midnight; partial days are refused during worker construction.
Missed days drain
in order, one frozen window at a time. A restart reuses completed reads and
never double-posts protected cost or demand consumption. Current profile reads
do not advance the listing watermark past historical performance still being
processed. Verification that is still pending is observed again on the next
day; loss of previously observed verification requires reconciliation.

Provider completeness is a separate contract from SDK-state pagination. PostHog
reads follow authenticated, query-bound cursors in ascending timestamp order,
overlapping page boundaries and deduplicating immutable event IDs. Each page is
a separately authenticated recovery checkpoint; a crash reuses completed reads.
A window is complete only after the terminal page. Reads exceeding 100 pages or
10,000 returned rows, non-progressing cursors, changed duplicate events and dense
timestamp boundaries that the provider cannot page safely are explicitly refused.
Other incomplete/truncated provider reports are likewise refused. Source
configuration and identity mappings must remain
stable for a retained operation; changes need explicit reconciliation and a new
operation identity rather than quietly replacing historical evidence.

## Growth periods and budget decisions

`--growth-config` accepts `periods` and `reallocations` arrays, with unique `ref`
values. `CompanyGrowthHost` documents the executable shape; the integrated
fixtures in `test_company_growth_host.py` run the complete contracts.

A period names its sealed `portfolio`, `register_ref`, `revenue_engines`,
`acquisition_engines`, and `required_source_refs`. It may name a
`cohort_source_ref`, `holdout_units`, `content_asset_refs` and explicit
`content_allocations`. The host loads every persisted record from each declared
revenue engine, replays settled sources, loads authenticated daily observations,
attributes conversions and folds the protected cost register. Disjoint verified
first-purchase counts can be combined for the exact period; this does not
invent retention or LTV.

The retained report evaluates these acceptance criteria:

- Every declared source covers every day in the period.
- Touch lookback is complete and all credited touches verify under the host's
  exact company scope.
- First-purchase history is verified before reporting CAC. Verified zero new
  customers leaves CAC undefined.
- The protected cost register is closed with replayed bank coverage, including
  the explicit zero-outflow case; no parallel media/inference total is added.
- Named content assets have explicit, checked allocations from protected cost
  sources; remaining unallocated cost stays visible.

An operating source census establishes coverage of declared inputs. It cannot
prove that all external liabilities, accounts or historical customers were
imported. The report retains `external_liabilities_proven_complete: false`.
Company acceptance therefore also requires the operator's account/source census
and reconciliation against external books. A successful PR does not supply that
business evidence.

A reallocation names a future/current portfolio, an accepted
`economic_period_ref`, persisted `campaign_refs`, authenticated
`return_checkpoint_refs`, optional active experiment `designs`, provider
`objects` and `account` read specifications per channel, `object_entries`,
`connector_account_refs`, and `identifiers_by_envelope`. Each read specification
contains `tool`, `arguments` and `connector_account_ref`. Only independently
verified incremental returns can qualify a receiving channel. Missing evidence
produces a retained hold decision. A returned proposal cannot create authority.

The host reads exact provider targets and account currency, checks their age,
compiles review candidates without inventing a business approval, then opens
actual per-unit provider approvals. Decreases and pauses finish before
increases. Stable request identity and retained execution proofs reconcile each
unit after retries. Every unfinished write rechecks the candidate period and
the 24-hour source-evidence deadline. Expired decisions retain partial proofs
and require a fresh decision; they do not stop independent company cadence.
Pending approvals also let independent cadence continue. A complete
report requires every unit's exact target, amount, result and approval proof.

## Credentials and code execution

Native OpenAI administration and Document AI now use reference-only grants.
Spring rechecks current custody at dispatch; workers do not receive the provider
key or Google service-account JSON. Provider object ownership is tracked and
checked independently from key custody, including references inside model
requests. Existing unknown provider objects require deliberate migration/import;
a worker cannot claim them simply by knowing their IDs.

The production workspace opt-in is `docker-compose.workspace-execution.yml`.
It requires digest-pinned broker/sandbox images, the canonical local workspace
volume, a dedicated file credential, an internal sandbox network and readiness
checks. Writable work uses a bounded tmpfs copy; reconciliation rejects escaped,
conflicting or oversized output and retains failed export evidence. The runner
has no Docker socket. Limits, cancellation, admission and artifact reconciliation
are executable broker controls, not a trusted shell command string in a worker.

Cursor admission additionally binds the canonical approved Project execution
grant and current provider custody. The cloud SDK does not expose enforceable
hard token/cost ceilings for the canonical grant. Cloud readiness therefore
remains unavailable for that contract; no operator flag invents enforcement.
The local constrained broker is the implemented command-execution path. Its
Docker/kernel behavior and real provider account journeys still need an enabled
validation environment before deployment certification.

## Release acceptance

The distribution verifier builds wheel and sdist twice and compares bytes, then
runs isolated clean-install and exact previous-wheel upgrade journeys. The
acceptance workflow tests Python 3.10–3.13 and executes public sync/async clients,
CLI version, company-worker help, and actual MCP stdio initialize/tool listing.
The checks found and fixed Python 3.10 `tomllib` and `typing.Self` compatibility.
The local matrix passed all eight clean/upgrade journeys. Public mirroring and
package publication remain explicit release actions; this change does not
automatically trigger either.

Local validation covers authenticated source tampering, wrong company/project,
parent watermark tampering, stale writes, crash recovery, exact approvals,
budget-decrease ordering, provider-pause reconciliation, more than 200 durable
states, credential rotation/revocation, provider-object isolation and constrained
workspace boundaries. The checked-in tests use real application functions and
HTTP request shapes with controlled transports. Real provider approvals,
Docker execution and deployed install/upgrade acceptance must be recorded
separately when the infrastructure and configured accounts are available.
