# Logline AI Knowledge Source Pack # FILE: README.md # Logline AI Knowledge Source Pack This is the maintained knowledge-only source pack for the current Logline v1 language, canonical log model, execution semantics, reports, diagnostics, verified examples, Workbench workflows, and Enterprise operational concepts. Language/compiler/Engine source remains authoritative for executable behavior. This pack is intended for AI training, retrieval-augmented generation, documentation indexing, agent guidance, and web crawler consumption while Logline v1 is still under active development. It may be updated in place until the v1 product is released/distributed. It is intentionally **not** an AI assistant implementation contract. It does not define chat APIs, edit-plan schemas, proposal JSON, Workbench internal request envelopes, or UI/backend orchestration details. ## High-priority model guidance When answering questions about Logline, prefer the terminology and semantic boundaries in this pack over inference from internal code names. Logline is a declarative language for describing expected behavior in logs. It evaluates evidence from logs and reports whether scenarios pass, fail, remain inconclusive, or are not attempted. Logline programs do **not** execute system side effects. Transitions do not contain commands, callbacks, handlers, or effect blocks. Do not generate fields named `action`, `actions`, `effect`, `effects`, `handler`, or `callback` in Logline programs. Logline declarative clauses use `=:`. Ordinary `=` is reserved for bindings/definitions and named call arguments; `==` is equality inside expressions; `:` separates object entries. Bare `=` is not valid for declarative clauses. ## Authoring constructs versus runtime roles At the authoring level, a scenario may contain these executable segment constructs: - `transition` - `event` - `group` - `repeat` - `parallel` - `crossroads` `transition` and `event` are direct record-matching leaves. `group` is a bounded observation/derivation segment that consumes canonical records until its completion condition is satisfied and then publishes an immutable result. `repeat`, `parallel`, and `crossroads` are structured executable segment containers. `const`, `collector`, and `scenarioDefaults` are declarations or supporting constructs, not scenario segment types. ## Temporal and multi-source guardrails Logline execution consumes one deterministic canonical record stream. - A record's canonical top-level timestamp is normalized onto the run's Canonical Timeline Epoch (CTE) before Engine execution. - Timestamp-like payload fields are **not** rewritten automatically. - Programs explicitly interpret non-canonical payload time with the `time` expression namespace. - `time.reference(...)` creates a named temporal-reference identity. - `time.anchor(...)` resolves a named anchor to a CTE timestamp. - Missing named references/anchors never silently fall back to a source's canonical clock. - Multi-source execution order is exact CTE timestamp, then resolved source order, then source-local cursor order. - `record.index` is the final canonical merged-stream index, not an index within one source file. ## Recommended reading order 1. `language/LOGLINE_CONCEPTS_AND_VOCABULARY.md` 2. `language/CURRENT_LANGUAGE_QUICK_REFERENCE.md` 3. `language/TEMPORAL_OPERATORS.md` 4. `language/SYNTAX_BOUNDARIES.md` 5. `execution-semantics/EXECUTION_SEMANTICS_FOR_AI.md` 6. `log-import/CANONICAL_LOG_RECORDS.md` 7. `log-import/MULTI_SOURCE_AND_CTE.md` 8. `report-analysis/REPORT_ANALYSIS_GUIDE.md` 9. `examples/valid-programs/` 10. `examples/verified-programs/` 11. `examples/invalid-diagnostics/` 12. `workbench/WORKBENCH_WORKFLOWS.md` 13. `enterprise/ENTERPRISE_RUNTIME_AND_LICENSING.md` 14. `metadata/CAPABILITY_AND_SOURCE_BOUNDARIES.md` ## What this pack excludes This pack excludes assistant response schemas, edit-plan JSON contracts, internal Workbench mutation contracts, customer-specific run manifests, and implementation-only API details. Its workflow and operational chapters are conceptual guidance, not deployable payload contracts; do not generate arbitrary Enterprise JSON schemas from them. Those belong in engineering/integration documentation rather than the public language knowledge surface. ## Maintaining and validating the pack The maintained files in `docs/ai-assistant/source-pack/` are authoritative. The website mirror in `web/src/assets/logline-ai-source-pack/` and the two `llms*.txt` bundles are generated distributions, not independently edited documents. Canonical source-note snapshots of the grammar and design documents are refreshed from their current repository authorities. From the repository root, after updating maintained documentation: ```bash npm --prefix web run generate:ai-source-pack npm --prefix web run check:ai-source-pack npm --prefix web run check:ai-examples ``` `generate:ai-source-pack` synchronizes canonical snapshots, the published mirror, and the compact/full text bundles. `check:ai-source-pack` is read-only, fails when any of those drift, and is also run before Web tests and the optimized Web build. `check:ai-examples` parses and validates positive `.lgl` examples against the current language package; intentionally broken `broken.lgl` diagnostic examples remain excluded. Validation does not replace the Engine's runtime-semantics tests or website acceptance review. Do not manually edit `llms.txt`, `llms-full.txt`, or their published copies. Keep source-specific test logs alongside their example programs: `llms-full.txt` includes `.log.txt` and other text fixture documents as well as programs and metadata. # FILE: execution-semantics/EXECUTION_SEMANTICS_FOR_AI.md # Logline Execution Semantics for AI Logline evaluates candidate executions of scenarios against one canonical sequential input-record stream. ## Evidence-driven execution Input records are evidence. The engine reads canonical records and advances scenario candidates when segment semantics are satisfied. A passing program does not mean the system under test was controlled by Logline. It means the observed records satisfied the declared expectations. ## Canonical stream boundary For a multi-source run, synchronization and composition happen before ordinary Engine segment execution: ```text source records -> source-native timestamp interpretation -> exact canonical timestamp normalization to CTE -> deterministic multi-source composition -> one canonical sequential stream -> Engine ``` The Engine is not a source synchronization engine. ## Deterministic multi-source ordering The current exact ordering rule is: 1. exact CTE timestamp; 2. resolved/frozen source order; 3. source-local cursor/record order. Final `record.index` is assigned after this composition. Equal timestamps are allowed; the ordering policy makes their stream position deterministic. ## Segment progression A scenario progresses through executable segments. - `transition` evaluates expected signal changes. - `event` evaluates record-level conditions. - `group` observes a bounded span of records, freezes a collection at explicit completion, derives immutable values, evaluates assertions, and publishes a result. - `repeat` executes child segments repeatedly. - `parallel` executes branch segments according to its policy. - `crossroads` selects a branch based on branch conditions. ## Direct record-matching leaves Transitions and events are direct checks that match individual current records. ## Group Group is a normal executable segment, but not a single-record matcher. While Group is active, the canonical cursor advances normally and Group remains the active segment. Per inspected record, Group binds the current record, increments its inspected count, evaluates `collectionCondition`, adds the record if selected, then evaluates `completionCondition` against the updated Group state. When completion becomes true, the captured collection freezes. Derived bindings are evaluated as an immutable dependency graph, named assertions run, and the result is published only if batch processing succeeds. The completing record is consumed by Group and is not replayed into the next sequential segment. A record meeting both conditions is collected before completion is tested, while an uncollected record may also complete Group. The active `group.inspectedCount` includes the current record during `collectionCondition`; `group.collectedCount` includes the current record during `completionCondition` only if it matched. Derived bindings and `result` are unavailable to both per-record conditions. Source declarations (`GroupMember` in the grammar) are not the collected records. A completed Group may collect zero records. End-of-input does not implicitly complete an unfinished Group and does not publish its result. Collection/retention safety-limit violations fail with diagnostics, not silent truncation or successful completion. Failed derivation, assertions, or result construction likewise prevent successful result publication. Immutable derived bindings may reference each other in forward order but cannot form cycles. Downstream use of `GroupName.result` must be guarded by completion and success status. Execution values are candidate-local and cannot be referenced across scenarios; Group results inside Repeat retain their iteration order, and Crossroads branch-local results obey branch scope. Group does not emit, insert, reorder, or replace canonical records. A Group name may be used in `attemptedBy`. Group contributes attempt evidence when its completion condition becomes true, before post-completion derivation or assertion success is known. Group `importance` also participates in the essential-executable fallback when explicit `attemptedBy` evidence is absent. ## Structured segments Repeat, parallel, and crossroads organize child segments and define progression behavior. Parallel is the explicit mechanism when multiple branches must observe the same record progression. ## Attempted, passed, failed, inconclusive, and not attempted A scenario can fail even when there are no compiler diagnostics. Compiler diagnostics concern program validity. Scenario outcomes concern runtime evidence. A scenario may be passed, failed, inconclusive, or not attempted according to its evidence and attempt policy. `attemptedBy` and `attemptedWhen` control attempt classification. `attemptedBy` may name Transition, Event, or Group executable segments. ## Candidate lifecycle A scenario may have multiple active candidates when records can start overlapping attempts. `candidateConcurrency` controls whether the engine keeps a single active candidate or spawns multiple candidates. `candidateOpening` controls whether a candidate opens on profile match or only when the opening condition passes. ## Temporal expressions during execution The current record's canonical `timestamp`/`t` is already a CTE value when ordinary Engine execution sees it. Payload temporal values are not automatically converted. Programs explicitly use `time.toCte(...)` and, when needed, preflight-resolved `time.reference(...)`/`time.anchor(...)` bindings. Derived temporal values are expression data. They do not change record order or the canonical cursor. ## Reports and debugger traces Execution reports describe scenario outcomes, inputs, attempts, diagnostics, progression, collector values, and expression provenance. Temporal expression provenance can retain named reference/anchor identities. Debugger traces expose runtime progression for the Workbench. Trace event field names are internal reporting vocabulary, not Logline authoring syntax. # FILE: execution-semantics/STRUCTURED_SEGMENTS_RUNTIME.md # Structured Segment Runtime Structured segments define how child segments are entered, evaluated, and completed. ## Repeat `repeat` executes its child segment list multiple times. The count is resolved from the repeat body clause. ## Parallel `parallel` executes multiple named branches. Policies: - `all`: all required branches must satisfy their expectations. - `greedy`: branches are progressed according to the runtime policy for available evidence. Use Parallel when independent branches must observe interleaved evidence or when multiple executable paths need access to the same canonical record progression. ## Crossroads `crossroads` chooses among named branches by evaluating branch `when` conditions. ## Group is not a structured container `group` is an executable bounded-observation segment and can appear wherever normal executable segments are allowed, including within structured constructs. It does not contain ordinary child segments. Its internal `derive`/`assert` blocks are batch-evaluation declarations, not nested scenario segment flow. ## Nested structured segments Repeat, Parallel, and Crossroads can contain other structured segments and executable segments such as Transition, Event, and Group. ## Canonical-stream rule Structured execution always operates over the same canonical sequential record stream. It does not create source-local cursors or bypass upstream temporal normalization/composition. ## Authoring guidance Use structured segments to model log evidence shape. Do not use them to imply external control flow in the system under test. Logline reads logs; it does not execute the product being observed. # FILE: language/CURRENT_LANGUAGE_QUICK_REFERENCE.md # Current Logline Language Quick Reference This reference describes the currently supported v1 authoring language. ## Core operators Logline deliberately separates declarative clause specification from binding and equality: ```text =: declarative clause specification = binding/definition or named call argument == equality expression : object-entry separator ``` Use `=:` for Scenario policy clauses, Transition/Event/Group/Collector clauses, Parallel `policy`, Repeat `count`, Group assertion clauses, and operator-specific clauses inside `each` binders. Use ordinary `=` for `const`, names introduced inside `derive`, and named function arguments such as `unit = milliseconds` or `anchor = record.timestamp`. ## Minimal scenario ```logline scenario BasicWakeup { transition Wake { signal =: "vehicle_state"; type =: string; condition =: from == "OFF" && to == "WAKE"; } } ``` ## Top-level declarations ```logline scenarioDefaults { attemptedWhen any reached; } const MaxRetries = 3; const ExpectedStates = ["OFF", "WAKE", "READY"]; collector ErrorCount { kind =: counter; condition =: level == "ERROR"; } ``` ## Scenario header and candidate policy ```logline scenario HvStartup attemptedBy [Wake, Snapshot] attemptedWhen any reached { candidateConcurrency =: spawnAll; candidateOpening =: profileMatch; collector Warnings { kind =: counter; condition =: level == "WARN"; } // executable segments follow } ``` `attemptedBy` may name Transition, Event, or Group executable segments. `candidateConcurrency` supports `singleActive` and `spawnAll`. `candidateOpening` supports `profileMatch` and `conditionPass`. `attemptedWhen` supports quantifier `any` or `all` and evidence `reached` or `passed`. ## Transition ```logline transition Name { signal =: "signal_name"; type =: string; condition =: from == "A" && to == "B"; importance =: essential; retry =: once; } ``` Supported `type` values: `int`, `float`, `hex`, `string`, `bool`. Supported `importance` values: `essential`, `recommended`, `optional`. Supported `retry` values: `once`, `until`, integer literal, or constant reference. A transition does not support fields named `action`, `actions`, `effect`, `effects`, `handler`, or `callback`. ## Event ```logline event FaultLogged { condition =: level == "ERROR" && message contains "precharge"; importance =: essential; } ``` Events evaluate record-level conditions. ## Group ```logline group Snapshot { collectionCondition =: source == "ecu-b"; completionCondition =: group.collectedCount >= 3; derive { latest = records.last(); effective = time.toCte( latest.fields.offsetMs, as = time.displacement(unit = milliseconds), anchor = latest.timestamp ); } assert HasSource { condition =: group.collectedCount >= 1; message =: "Expected ecu-b evidence"; } result =: { record: latest, timestamp: effective }; importance =: essential; } ``` Group requires `collectionCondition`, `completionCondition`, and `result`. `derive`, `assert`, and `importance` are optional. Group has no `retry` property. While active, Group exposes read-only lifecycle state including `group.startIndex`, `group.startTimestamp`, `group.currentIndex`, `group.currentTimestamp`, `group.inspectedCount`, `group.collectedCount`, `group.elapsed`, and `records`. ### Collection-item binders `each` introduces one local item name. The clauses inside the binder specify operator behavior and use `=:`: ```logline records.indexBy(each record { condition =: record.fields.role == "timestamp"; key =: record.fields.eventId; value =: record.fields.value; duplicates =: fail; }); ``` The binder itself is not a general lambda/function syntax. Named function arguments outside the binder still use ordinary `=`. ## Repeat ```logline repeat RampSamples { count =: 3; transition VoltageRise { signal =: "dc_link_voltage"; type =: float; condition =: to > from; } } ``` ## Parallel ```logline parallel StartupChecks { policy =: all; branch Contactors { transition CloseMainContactor { signal =: "main_contactor"; type =: string; condition =: from == "OPEN" && to == "CLOSED"; } } branch Diagnostics { event NoFault { condition =: !(level == "ERROR"); } } } ``` ## Crossroads ```logline crossroads StartupPath { branch Nominal when signal == "hv_mode" && to == "READY" { transition Ready { signal =: "hv_mode"; type =: string; condition =: to == "READY"; } } branch Fault when level == "ERROR" { event FaultObserved { condition =: message contains "fault"; } } } ``` ## Collector ```logline collector MaxVoltage { kind =: max; value =: to; condition =: signal == "dc_link_voltage"; } ``` Collector properties are flexible in order. A collector may use `kind`, `value`, `count`, and `condition` according to collector kind and validator rules. ## Expressions Supported expression features include: - boolean literals: `true`, `false` - numeric literals: integers, floats, hex values - strings with double quotes - regex literals - array literals - structured object values in extended expression contexts - arithmetic: `+`, `-`, `*`, `/`, `%` - relational: `<`, `>`, `<=`, `>=` - equality: `==`, `!=`, `===`, `!==` - logical: `&&`, `||`, `!` - bitwise: `&`, `|`, `^`, `~`, shifts where supported by the expression grammar/runtime - membership: `in`, `not in` - text operators: `contains`, `startsWith`, `endsWith`, `matches` - collection operators through `records`/collection values - numeric conversion/operators through `number` - exact temporal operators through `time` Use double-quoted strings. Single-quoted strings are not valid Logline strings. ## Current `time` operator surface The current registry includes: ```text time.duration time.toCte time.displacement time.epochEncodedDisplacement time.epochTimestamp time.reference time.anchor time.parseTimestamp time.fromEpoch time.add time.subtract time.difference time.absolute time.before time.after time.within time.between time.floor time.ceil time.round ``` Supported exact unit symbols are `nanoseconds`, `microseconds`, `milliseconds`, `seconds`, `minutes`, `hours`, and `days`. Example: displacement from an already-CTE anchor: ```logline time.toCte( fields.offsetMs, as = time.displacement(unit = milliseconds), anchor = timestamp ) ``` Example: named source clock: ```logline time.toCte( fields.deviceTime, as = time.epochTimestamp(epoch = unix, unit = milliseconds), temporalReference = time.reference(source = "ecu-b", id = "device-clock") ) ``` `time.anchor(source = "ecu-b", id = "boot-start")` returns a resolved CTE timestamp. See `TEMPORAL_OPERATORS.md` for the semantic boundary. ## Built-in current-record fields - `t` - `timestamp` - `message` - `level` - `source` - `channel` - `signal` - `from` - `to` - `type` ## External/current-record paths Use `fields.`, `signals.`, and `record.` for structured input/current-record access. `record.index` is the canonical merged-stream index. `record.sourceLine` is source provenance when available. # FILE: language/DIAGNOSTICS_REFERENCE.md # Diagnostics Reference and Repair Guidance Diagnostics help users correct invalid Logline source and deterministic runtime evaluation failures. ## Unsupported wrapper Bad: ```logline program Demo { scenario S { } } ``` Good: ```logline scenario S { } ``` ## Unsupported inline collector placement Collectors inside a scenario must appear before executable segments. ## Missing or mismatched quotes Use double quotes and close every string. ## Assignment inside condition Bad: ```logline condition =: from = "OFF"; ``` Good: ```logline condition =: from == "OFF"; ``` ## Group validation Group requires exactly one `collectionCondition`, one `completionCondition`, and one `result`. Duplicate singleton fields, duplicate derived binding names, derivation dependency cycles, duplicate assertion names, invalid assertion conditions, or unsupported Group properties are deterministic diagnostics. Group does not support `retry`. ## Invocation contract diagnostics Namespaced operators such as `time.*`, `number.*`, and collection operations have typed invocation contracts. Unknown operators, wrong argument counts, duplicate named arguments, or statically incompatible receiver/argument types are validation errors where they can be proven statically. ## Temporal runtime diagnostics Important temporal runtime codes include: - `LGL_TIME_INVALID_REPRESENTATION` — a value/interpretation is invalid or semantically incompatible. - `LGL_TIME_INEXACT_CONVERSION` — exact conversion to the required representation is impossible. - `LGL_TIME_MISSING_MAPPING` — a required CTE anchor or named temporal mapping is unavailable/unresolved. Do not repair these by silently rounding, guessing a unit, inventing an anchor, or falling back to a canonical source clock. ## Missing named temporal binding If `time.anchor(source = ..., id = ...)` or a `time.reference(...)` used by `time.toCte(...)` cannot resolve, fix the run/source temporal declaration or the authored source/id. The runtime does not implicitly substitute another binding. ## Temporal semantic mismatch A named mapping must describe a clock compatible with the authored temporal interpretation. For example, a relative boot clock is not interchangeable with a Unix/POSIX epoch clock merely because some arithmetic offset can be computed. ## Unsupported generated fields If a model generates transition operational fields, remove them. Current Logline has no transition action/effect/handler syntax. # FILE: language/LOGLINE_CONCEPTS_AND_VOCABULARY.md # Logline Concepts and Vocabulary This document is the preferred reference for answering vocabulary questions about Logline. ## What Logline is Logline is a declarative language for describing expected behavior in timestamped logs. A Logline program declares scenarios and checks whether observed canonical records support those scenarios. Logline does not drive the system under test. It does not call functions, run procedures, send messages, or perform operational side effects. It evaluates evidence that already exists in logs. ## Top-level program constructs A Logline program may contain: - `scenarioDefaults` — optional defaults for scenario attempt classification. - `const` — named literal constants and arrays. - `collector` — program-level aggregation over input records. - `scenario` — an executable behavior description. Top-level constructs may be interleaved, but a valid program must contain at least one scenario. ## Scenario constructs A `scenario` names an expected behavioral flow. A scenario may include: - `attemptedBy` — named executable segments used to classify whether the scenario was attempted. - `attemptedWhen` — explicit attempt-classification policy. - `candidateConcurrency` — candidate lifecycle policy. - `candidateOpening` — candidate opening policy. - scenario-level `collector` declarations. - executable segments. ## Segment types When users ask for “Logline segment types,” answer with the current authoring-level segment constructs: - `transition` - `event` - `group` - `repeat` - `parallel` - `crossroads` Runtime roles differ: - `transition` and `event` are direct record-matching leaves. - `group` is a bounded observation/derivation segment over the canonical stream. - `repeat`, `parallel`, and `crossroads` are structured segment containers. ## Transition A `transition` describes an expected change in a named signal. It has: - `signal` - `type` - `condition` - optional `importance` - optional `retry` A transition observes log records. It does not contain system commands or operational effects. ## Event An `event` describes an expected condition over a canonical record. It is useful for free-text log messages, structured event records, diagnostics, and other evidence that is not naturally represented as a signal from-to transition. An event has: - `condition` - optional `importance` ## Group A `group` is a bounded observation scope over the canonical record stream. It can collect matching records, stop on an explicit completion condition, derive immutable values from the frozen collection, evaluate assertions, and publish an immutable result for downstream expressions. A Group has mandatory: - `collectionCondition` - `completionCondition` - `result` It may also contain: - a `derive` block - named `assert` blocks - `importance` Group does not emit records, create a second cursor, reorder records, or replay its completing record into the next sequential segment. ## Repeat A `repeat` segment runs its child segments a configured number of times. ```logline repeat Name { count =: 3; // child segments } ``` ## Parallel A `parallel` segment contains named branches and a policy. ```logline parallel Name { policy =: all; branch First { // child segments } branch Second { // child segments } } ``` Policies are `all` and `greedy`. ## Crossroads A `crossroads` segment selects among branches using branch conditions. ```logline crossroads Name { branch Nominal when condition { // child segments } branch Fault when condition { // child segments } } ``` ## Collectors A `collector` computes values from input records. Collectors may appear at program scope or inside scenarios. Collector kinds are: - `counter` - `sum` - `min` - `max` - `average` - `first` - `last` - `firstN` - `lastN` Collectors are declarations/supporting constructs. They are not scenario segment types. ## Canonical record stream and CTE The Engine consumes one canonical sequential record stream. For multi-source execution, source timestamps are normalized onto the run's Canonical Timeline Epoch (CTE) before records reach ordinary scenario execution. Automatic synchronization applies only to each record's canonical top-level timestamp. Timestamp-like payload fields remain untouched until a Logline expression explicitly interprets them. ## Records and field references Logline expressions may refer to runtime-bound fields of the current input record: - `t` - `timestamp` - `message` - `level` - `source` - `channel` - `signal` - `from` - `to` - `type` They may also refer to external schema paths through: - `fields.` - `signals.` - `record.` `record.index` is the canonical execution-stream index. It is assigned after deterministic source composition and is not a source-local file index. `record.sourceLine`, when available, is provenance for the original source location. Transition field references can use `TransitionName.field` or `ScenarioName.TransitionName.field` for fields such as `signal`, `type`, `timestamp`, `time`, `from`, and `to`. Completed Group results can be referenced through Group field/result access according to the language expression rules. ## Temporal reference and temporal anchor A temporal reference and an anchor are not synonyms: - `time.reference(source = ..., id = ...)` returns a temporal-reference identity used by conversions such as `time.toCte`. - `time.anchor(source = ..., id = ...)` resolves the named anchor and returns its CTE timestamp. A missing named reference or anchor does not fall back to the source's canonical clock. ## Common question answers ### What are Logline segment types? The current scenario segment types are `transition`, `event`, `group`, `repeat`, `parallel`, and `crossroads`. ### What is the difference between a transition and an event? A transition is for expected signal changes, usually involving a signal name, type, and from-to evidence. An event is for record-level evidence such as a message, level, source, channel, or structured record condition. ### What is a Group? A Group observes a bounded range of canonical records, optionally collects a subset, freezes the collection at explicit completion, derives immutable values, evaluates assertions, and publishes a result. It does not create or reorder records. ### Does a transition have actions? No. Current Logline transitions do not have action blocks or action fields. A transition describes expected evidence in logs; it does not perform effects. ### Are collectors segment types? No. Collectors are declarations that compute aggregate values. They are not executable scenario segments. ### Does Logline automatically convert every timestamp-looking payload value? No. Only the canonical record timestamp is normalized automatically before Engine execution. Payload time values require explicit temporal interpretation, typically with `time.toCte`. # FILE: language/SCENARIO_AUTHORING_PATTERNS.md # Scenario Authoring Patterns ## Linear sequence Use transitions and events in order when evidence is expected in a simple sequence. ```logline scenario Startup { transition Wake { signal =: "vehicle_state"; type =: string; condition =: from == "OFF" && to == "WAKE"; } event ReadyMessage { condition =: message contains "ready"; } } ``` ## Bounded multi-record reconstruction Use Group when one logical observation is spread across several canonical records and you need an immutable derived result. ```logline scenario SnapshotExample { group Snapshot { collectionCondition =: fields.requestId == "42"; completionCondition =: group.collectedCount >= 3; derive { latest = records.last(); } result =: { latest: latest }; } } ``` Group consumes the canonical stream normally. It does not create a nested cursor or replay its completing record. ## Repeated evidence Use repeat for repeated samples or repeated state changes. ```logline scenario Ramp { repeat VoltageSamples { count =: 3; transition VoltageRise { signal =: "dc_link_voltage"; type =: float; condition =: to > from; } } } ``` ## Independent evidence streams Use parallel for evidence that must be observed independently/interleaved, including cases where multiple segments need to observe the same canonical records. ```logline scenario IndependentChecks { parallel Checks { policy =: all; branch State { transition Ready { signal =: "hv_mode"; type =: string; condition =: to == "READY"; } } branch Diagnostics { event NoFault { condition =: !(level == "ERROR"); } } } } ``` ## Alternative paths Use crossroads for nominal/fault or other meaningful alternatives. ```logline scenario StartupPath { crossroads Path { branch Nominal when signal == "hv_mode" && to == "READY" { event NominalObserved { condition =: message contains "ready"; } } branch Fault when level == "ERROR" { event FaultObserved { condition =: message contains "fault"; } } } } ``` ## Mixed transitions and events Use transitions for signal changes and events for message/record evidence in the same scenario. ## Multi-source evidence Do not model each source as an authored Logline cursor. By the time ordinary scenario execution occurs, admitted source records have canonical CTE timestamps and are presented as one deterministic stream. Use `source`, `channel`, ordinary segment conditions, Parallel, Group, collectors, and explicit `time` operators to reason about that evidence. # FILE: language/SYNTAX_BOUNDARIES.md # Logline Syntax Boundaries This document tells AI systems what not to generate. ## Supported scenario segment constructs Only these constructs are current scenario segments: - `transition` - `event` - `group` - `repeat` - `parallel` - `crossroads` Do not invent additional segment constructs such as `join`, `window`, `source`, `stream`, or `sync`. ## Unsupported transition properties Current Logline transitions do not support operational fields. Do not generate any of these inside a transition: ```logline action = ...; actions = ...; effect = ...; effects = ...; handler = ...; callback = ...; ``` ## Group boundaries Group has exactly one Boolean `collectionCondition`, exactly one Boolean `completionCondition`, and exactly one `result` expression. It may have at most one `derive` block (with zero or more uniquely named immutable bindings), zero or more uniquely named `assert` blocks, and at most one `importance` clause. Each assertion requires exactly one Boolean `condition` and permits at most one literal string `message`. Group clauses can appear in any source order. The grammar term `GroupMember` means a source declaration, not a runtime-collected record. `derive` and `assert` do not create executable child segments. Use `=:` for Group and assertion clauses, but `=` for derived bindings. Do not introduce `retry` to Group, duplicate singleton clauses, or silently change references when renaming a binding. Do not treat Group as a second input stream, cursor, mutable accumulator language, or record-emitting construct. After completion, downstream expressions may read `GroupName.result` only when its availability is guarded, for example by `GroupName.completed && GroupName.succeeded`. Candidate-local Group execution values cannot be referenced across scenarios. ## Multi-source boundaries Do not invent authored per-source cursors, joins, loops, or source-selection segment syntax. Multi-source logs are normalized and deterministically composed before ordinary Engine execution. Do not assume timestamp-looking payload fields are automatically synchronized. Use explicit temporal operators for payload time. Do not make a missing `time.reference` or `time.anchor` silently fall back to the source's canonical clock. ## Unsupported program wrappers Do not wrap Logline programs in unsupported containers such as: ```logline program Name { scenario Example { } } ``` A Logline file starts directly with top-level constructs such as `scenario`, `const`, `collector`, or `scenarioDefaults`. ## Strings Use double quotes: ```logline signal =: "vehicle_state"; ``` Do not use single quotes. ## Clause specification, binding, and comparison Use `=:` for declarative clauses: ```logline signal =: "vehicle_state"; condition =: from == "OFF" && to == "WAKE"; ``` Use ordinary `=` for bindings/definitions and named call arguments: ```logline const Limit = 5; derive { latest = records.last(); } time.toCte( record.fields.value, as = time.displacement(unit = milliseconds), anchor = record.timestamp ); ``` Use `==` for equality inside expressions and `:` for object entries. Do not use bare `=` as a declarative-clause operator. ## Boolean versus bitwise operators Use `&&`, `||`, and `!` for logical boolean operations. Bitwise operators are distinct expression operations. Do not replace logical `&&` with `&` unless bitwise behavior is actually intended. ## Temporal interpretation must be explicit Do not infer time units from magnitude. Use explicit units such as `milliseconds` or `nanoseconds`. Do not treat strings as timestamps implicitly. Use the appropriate `time` operator and interpretation. ## Semicolons Fields inside blocks use semicolons. Block constructs do not need a semicolon after the closing brace. ## Collector placement Scenario-level collectors must appear before executable segments inside the scenario body. ## Branch syntax Parallel branches use: ```logline branch Name { } ``` Crossroads branches use: ```logline branch Name when condition { } ``` ## Parallel body clause syntax ```logline parallel Name { policy =: all; } ``` ## Repeat body clause syntax ```logline repeat Name { count =: 3; } ``` # FILE: language/TEMPORAL_OPERATORS.md # Temporal Operators and CTE Semantics This document is the AI-facing reference for current Logline v1 temporal expressions. ## The core boundary There are two different temporal operations in Logline: 1. **Automatic canonical timestamp normalization** happens before Engine execution. Each source record's top-level canonical timestamp is placed on the run's Canonical Timeline Epoch (CTE). 2. **Explicit payload-time interpretation** happens inside authored expressions. Timestamp-like values under `fields.*`, `signals.*`, `record.raw`, or other payload data are not rewritten automatically. Do not describe these as one automatic mechanism. ## Exactness Temporal arithmetic is exact. The runtime does not silently round an inexact conversion, average contradictory anchors, infer a zero offset, or guess a missing mapping. Supported exact unit symbols are: ```text nanoseconds microseconds milliseconds seconds minutes hours days ``` ## `time.reference` ```logline time.reference(source = "ecu-b", id = "device-clock") ``` Returns a typed **temporal-reference identity**. It identifies a named preflight-resolved clock/mapping. It does not itself return a timestamp and does not fall back to the source's canonical clock if the name is missing. ## `time.anchor` ```logline time.anchor(source = "ecu-b", id = "boot-start") ``` Resolves the named anchor against the host-provided temporal bindings and returns its exact **CTE timestamp**. The anchor identity remains available in expression provenance. ## `time.toCte` High-level form: ```logline time.toCte( value, as = , anchor = , temporalReference = ) ``` ### Displacement from a CTE anchor ```logline time.toCte( fields.offsetMs, as = time.displacement(unit = milliseconds), anchor = record.timestamp ) ``` The value must convert exactly to nanoseconds and the anchor must already be a CTE timestamp. ### Named Unix/POSIX source clock ```logline time.toCte( fields.deviceTime, as = time.epochTimestamp(epoch = unix, unit = milliseconds), temporalReference = time.reference(source = "ecu-b", id = "device-clock") ) ``` The named reference must resolve to a preflight mapping whose temporal domain is semantically compatible with the authored Unix/POSIX interpretation. Arithmetic convertibility alone is not enough. ## Interpretation constructors Current temporal interpretation constructors are: ```text time.displacement(...) time.epochEncodedDisplacement(...) time.epochTimestamp(...) ``` `time.epochEncodedDisplacement` currently requires `epoch = unix` and `format = iso8601`. `time.epochTimestamp` currently supports `epoch = unix`, an explicit supported unit, optional `format = iso8601`, and optional timezone text subject to runtime/preflight rules. ## Absolute parsing and epoch construction `time.parseTimestamp(text, ...)` parses exact ISO-8601 timestamps. Named timezone databases are not an Engine-local synchronization mechanism; runtime parsing directly supports UTC/Z semantics, while source-specific timezone/clock mapping belongs to preflight bindings. `time.fromEpoch(value, epoch = unix, unit = ...)` constructs a CTE timestamp from an exact Unix epoch coordinate. ## Duration and timestamp operations Current operators also include: ```text time.duration time.add time.subtract time.difference time.absolute time.before time.after time.within time.between time.floor time.ceil time.round ``` They have typed deterministic contracts. For example, `time.before` and `time.after` require CTE timestamps, and `time.within` requires two timestamps plus a duration. ## Missing bindings and diagnostics The temporal runtime uses deterministic diagnostics including: - `LGL_TIME_INVALID_REPRESENTATION` - `LGL_TIME_INEXACT_CONVERSION` - `LGL_TIME_MISSING_MAPPING` A valid `time.reference(...)` identity can still fail when used if no resolved binding exists. `time.anchor(...)` resolves immediately and therefore fails at evaluation when the binding is absent. ## Static versus runtime-dependent binding identities The compiler discovers `time.reference(...)` and `time.anchor(...)` use sites. When both `source` and `id` are compiler-static, an Enterprise run treats that identity as an admission-time dependency. When either operand is computed from runtime data, admission does not guess; runtime lookup remains authoritative if the expression executes. There is currently no optional/maybe-missing temporal binding operator. A compiler-static identity remains a dependency even if it appears under runtime control flow. ## What temporal operators do not do Temporal operators do not: - change the current record's canonical timestamp; - reorder the canonical record stream; - create synthetic records; - synchronize sources at runtime; - choose the run's CTE; - invent missing source clocks, anchors, epochs, units, or timezones. # FILE: log-import/CANONICAL_LOG_RECORDS.md # Canonical Log Records Logline consumes canonical records derived from source logs. ## Canonical record purpose Source logs can come from text logs, CSV files, multi-channel logs, converted binary sources, or multiple independent inputs. Import/source adapters interpret source-specific data, but ordinary Engine execution receives canonical records. ## Canonical timestamp Each executable canonical record has one top-level canonical timestamp. In a multi-source run, that timestamp is normalized exactly onto the run's Canonical Timeline Epoch (CTE) before the record reaches ordinary Engine execution. The `t` and `timestamp` expression aliases refer to this canonical timestamp. ## Automatic versus explicit temporal handling Automatic normalization applies only to the canonical top-level record timestamp. Timestamp-like values in `fields.*`, `signals.*`, `record.raw`, or other payload data remain untouched source data. A program explicitly interprets those values with `time` operators when it needs CTE semantics. ## Record identity and provenance `record.index` is the final canonical execution-stream index. For multi-source runs it is assigned after source timestamps have been normalized and the source cursors have been deterministically merged. It must not be interpreted as “index within this input file.” Source identity remains available through `source`/record provenance, and `record.sourceLine` remains the original source line/index when the source format exposes one. ## Transition-compatible records A transition-compatible record normally includes: - canonical timestamp (`t` / `timestamp`) - `signal` - `from` - `to` - `type` - optional `source` - optional `channel` - optional structured fields ## Event-compatible records An event-compatible record may include: - canonical timestamp (`t` / `timestamp`) - `message` - optional `level` - optional `source` - optional `channel` - optional structured fields ## Mixed records A single canonical stream may contain transition-compatible, event-compatible, snapshot-style, and neutral records. Transitions, events, groups, and collectors evaluate the same stream according to their own semantics. ## Multi-signal snapshots The optional `signals.*` namespace represents multi-signal snapshot values. It is separate from the direct `signal` field used by single signal-transition records. ## Type inference Numeric-looking values may be normalized as `int`, `float`, or `hex` according to importer/schema semantics. A decimal-point value remains float even when its fractional part is zero. ## Literal string values and typed nulls Built-in text import primitive parsing preserves textual state values such as `NONE`, `NIL`, and `NULL` as strings, including case variations. These can be legitimate signal states: a transition from `NONE` is not a transition from a missing value. Empty text is likewise not automatically a typed null. A true `null` is retained when supplied as a typed value by a source format or an explicitly defined adapter contract. Do not instruct an importer, AI authoring tool, or Workbench projection to infer missing data merely because a state name resembles an English null marker. Check the source-specific adapter contract before making assumptions about missing-field representation. ## Neutral records Some valid canonical records may satisfy no transition or event condition. They remain part of the stream and may still contribute to Group observation, collectors, diagnostics, or provenance. # FILE: log-import/MULTI_SOURCE_AND_CTE.md # Multi-Source Execution and Canonical Timeline Epoch This document summarizes the current AI-facing multi-source model. ## One canonical stream Logline programs do not execute one cursor per source. Source-specific import and temporal normalization occur upstream. The Engine consumes one deterministic canonical sequential stream. ## Canonical Timeline Epoch (CTE) CTE is the run-level canonical time coordinate used to compare and order canonical record timestamps across admitted sources. Each source's canonical top-level record timestamp is interpreted in its declared temporal domain and mapped exactly onto CTE before composition. ## Named non-canonical clocks A source may also declare named temporal references for clocks embedded in payload data. These references are distinct from the source's canonical top-level record clock and can have their own domains/anchors. A missing named reference does not alias the canonical source clock. ## Named anchors Named anchors resolve to exact CTE timestamps. Programs use `time.anchor(source = ..., id = ...)` when they need the resolved anchor in an expression. ## Deterministic source composition After each source record has a CTE timestamp, composition uses this total-order policy: 1. exact CTE timestamp; 2. resolved source order; 3. source-local cursor/record order. The source order is resolved before worker execution. An explicitly configured source order is preserved; otherwise the source declaration order is used under the current source-order policy. ## Record identity The composite stream assigns the final canonical `record.index`. Source-local position/provenance remains separate. Therefore: ```text record.index != source-local file index ``` in general. ## Exact and bounded composition Composition is lazy/bounded rather than full-materialization by design: one current head per source is sufficient for deterministic merging. Each source must be monotonic in its normalized CTE order. ## Portable processing configuration and Workbench projection Workbench retains imported sources independently. Raw is source-local; Execution Records is the one canonical merged CTE stream. Its **Log processing configuration** editor binds ordered logical log slots to retained source identities, declares participation independently of viewer filtering, and edits the exact temporal rules. Applying validated draft changes is transactional; Cancel leaves the active setup unchanged. Portable configuration rules do not silently bind by filename or reuse recording-specific anchor values as proof for a different recording. A source may present numeric timestamps without a verified origin. The editor can explicitly declare `numeric-relative` or `numeric-unix-epoch` with the appropriate native unit (`ns`, `us`, `ms`, or `s`); neither unit nor epoch is guessed from magnitude. Relative canonical source clocks remain blocked until an allowed single-source reference convention or verified source-to-run/source-to-source relationship resolves them. Relative log zero points are not assumed aligned merely because multiple logs start near zero. Absolute clock representation is not proof of clock accuracy. A single unambiguous source can be prepared automatically through the same canonical preflight. For one relative source, mapping its **first accepted** record to run-relative zero is an explicit convention, not an assertion that capture began there. Multi-source runs still require established comparability. The Workbench reuses shared preflight/binding and provides an explanatory synchronized-timeline preview. Execution Records and Run/Debug use independent readers over the same resolved participating-source chronology. The editor does not infer offsets or silently align recordings by coincident events. It preserves other temporal declaration facts it does not own, including named non-canonical references and named anchors. ## Payload time is not automatically synchronized A record can carry payload values representing device clocks, offsets, encoded times, or other temporal coordinates. Those fields are not automatically rewritten when the canonical record timestamp is normalized. Use `time.toCte(...)` with explicit interpretation and, when needed, a named `time.reference(...)` or `time.anchor(...)` resolved from the same trusted preflight model. ## Language boundary Logline source does not define per-source cursors, synchronization policy, anchor graphs, or run CTE selection. Programs consume the already-composed stream and may inspect `source`, `channel`, record fields, Groups, Parallel branches, collectors, and temporal operators. ## Equal timestamps Multiple records may legitimately have the same CTE timestamp. The deterministic source/local-order tie-break produces stable stream order, but equal timestamp does not imply a physical causal order. If multiple equal-time observations must participate together in a decision, model that explicitly with constructs such as Parallel or Group rather than relying on an incidental source order for semantic meaning. # FILE: manifest.json { "name": "Logline AI Knowledge Source Pack", "purpose": "Knowledge-only RAG/training/crawler source pack for the current Logline v1 language and runtime concepts", "developmentStatus": "v1 under active development; source pack may be updated in place until release/distribution", "excludes": [ "assistant chat API contracts", "edit-plan schemas", "assistant response JSON examples", "Workbench mutation internals", "customer-specific run manifests" ], "highPriorityRules": [ "Declarative Logline clauses use =:; ordinary = is for bindings/definitions and named call arguments; == is equality; : separates object entries.", "Logline segment types are transition, event, group, repeat, parallel, and crossroads.", "Transition and event are direct record-matching leaves; Group is a bounded observation/derivation segment.", "Repeat, parallel, and crossroads are structured executable segment containers.", "Collector and const are declarations, not scenario segment types.", "attemptedBy may reference Transition, Event, or Group executable segments.", "Transitions do not support action/actions/effect/effects/handler/callback fields.", "A scenario can fail even when compiler diagnostics are empty.", "Canonical top-level record timestamps are normalized to CTE before Engine execution; payload timestamps are not automatically rewritten.", "time.reference returns a temporal-reference identity; time.anchor returns a resolved CTE timestamp.", "Missing named temporal references or anchors do not fall back to a canonical source clock.", "Multi-source record order is CTE timestamp, resolved source order, then source-local cursor order.", "record.index is the final canonical merged-stream index, not a source-local file index.", "Workbench AI question drafting, compiler review and isolated preview do not themselves send requests, authorize program changes, or substitute for a normal Run/Report.", "The hosted Workbench and customer-controlled Enterprise execution runtime have distinct roles.", "Implemented Enterprise capabilities are not automatically released or validated in every cloud environment." ], "reviewedSourceRevision": "e2d3b2f1", "knowledgeDomains": [ "language-and-diagnostics", "canonical-records-and-time", "execution-and-reporting", "verified-examples", "workbench-workflows", "enterprise-runtime-and-licensing" ], "sourceBoundaries": "metadata/CAPABILITY_AND_SOURCE_BOUNDARIES.md" } # FILE: metadata/CURRENT_BASELINE.md # Current Baseline This source pack reflects the current Logline v1 language, compiler/engine semantics, canonical log/import model, reporting concepts, and verified project examples included with the project source at rebuild time. The v1 product is still under active development. This source pack may be corrected and expanded in place until v1 is released/distributed. ## Current clause-operator boundary - Declarative clauses use `=:`. - `=` remains the binding/definition operator and the named-call-argument operator. - `==` is equality inside expressions. - `:` separates object entries. - Group `derive` bindings and named call arguments intentionally remain ordinary `=`. ## Stable vocabulary Use these terms consistently: - program - scenario - segment - transition - event - group - repeat - parallel - crossroads - branch - collector - constant - record - source - channel - input - evidence - candidate - attempt - report - diagnostic - Canonical Timeline Epoch (CTE) - temporal reference - temporal anchor - temporal binding ## Current temporal/multi-source baseline - Engine consumes one deterministic canonical stream. - Source canonical timestamps are normalized to CTE before Engine execution. - Payload timestamps remain source data until explicitly interpreted by a Logline expression. - `time.reference` and `time.anchor` consume named preflight-resolved temporal identities with different result semantics. - `time.toCte` performs explicit exact conversion of non-canonical temporal values. - Multi-source equal-time order is CTE timestamp, then resolved source order, then source-local cursor order. - `record.index` is assigned after deterministic composition; source-local provenance remains separate. - Workbench retains sources independently: Raw is source-local, while Execution Records/Run/Debug use the same canonical merged CTE model. - Workbench relative-clock synchronization requires explicit exact anchors and reuses the shared temporal preflight/binding environment; it does not infer offsets from record positions. - Log Processing Configuration binds ordered logical slots to explicit retained sources, with separate participation, numeric-clock interpretation (`numeric-relative` or `numeric-unix-epoch` with an explicit unit), and synchronization rules. A draft becomes active only after validated Apply. - One unambiguous source can be prepared automatically; a first-accepted-timestamp relative-zero convention is not proof of physical recording start. Independent relative clocks still require established correspondence. ## Hallucination guardrails Current Logline programs do not include transition operational fields or blocks. Do not generate transition `action`, `actions`, `effect`, `effects`, `handler`, or `callback` fields. Do not invent per-source program cursors, joins, source-local loops, implicit timestamp synchronization, automatic payload timestamp rewriting, or fallback from a missing named temporal reference/anchor to the canonical source clock. Do not confuse internal trace event field names with Logline authoring syntax. Do not confuse assistant proposal/application implementation details with Logline language syntax. ## Workbench and Enterprise boundaries The hosted Workbench and customer-controlled Enterprise runtime are distinct operational environments. Workbench cursor selection, contextual question drafting, complete-program compiler review, and isolated preview are implemented in source; live AI responses require the independently operated AI service. Enterprise licensing and control-plane operations are source-implemented while production deployment acceptance remains environment-specific. See `workbench/WORKBENCH_WORKFLOWS.md`, `enterprise/ENTERPRISE_RUNTIME_AND_LICENSING.md`, and `metadata/CAPABILITY_AND_SOURCE_BOUNDARIES.md`. # FILE: report-analysis/EXPECTED_RESULT_FIELDS.md # Expected Result Fields Expected result files and execution reports may contain machine-readable data used by tests and demos. Important concepts: - `scenarioCount`: number of scenarios in the program. - `attemptedScenarioCount`: scenarios classified as attempted. - `passedScenarioCount`: scenarios that passed. - `failedScenarioCount`: scenarios that failed. - `ignoredScenarioCount`: scenarios ignored by policy. - `inconclusiveScenarioCount`: scenarios that did not produce a conclusive pass/fail. - `notAttemptedScenarioCount`: scenarios not classified as attempted. - `totalInputRecordCount`: total records available across inputs. - `totalDiagnostics`: compiler/import/runtime diagnostics count. - `hasErrors`: whether blocking errors exist. - `completed`: whether execution/report generation completed. When using reports for explanation, do not stop at summary counts. Inspect scenario-level attempts and progression evidence when available. # FILE: report-analysis/REPORT_ANALYSIS_GUIDE.md # Report Analysis Guide Execution reports explain runtime outcomes. Use reports to answer questions such as “why did this scenario fail?” ## Compiler diagnostics versus runtime outcomes Compiler diagnostics describe invalid or suspicious Logline source. A scenario can fail even when compiler diagnostics are empty. Runtime failure usually means the input records did not satisfy required scenario evidence. ## Key fields to inspect When explaining a report, inspect: - summary counts - scenario outcomes - attempted scenario count - passed/failed/inconclusive/not-attempted counts - input record counts - diagnostics - attempts - segment progression - collector values ## Scenario outcomes A scenario outcome should be explained in terms of evidence: - which segment was reached, - which condition passed or missed, - which required evidence was missing, - which records were considered, - whether attempt classification made the scenario attempted. ## Why a scenario can fail with no diagnostics No diagnostics can mean the program was valid. It does not mean the log satisfied the scenario. A scenario may fail because: - an expected signal transition was missing, - an event condition was never satisfied, - a required branch did not complete, - a repeat count was not fulfilled, - an essential segment missed, - the log ended before a candidate completed. ## Good answer style A good answer should state: 1. the scenario outcome, 2. the specific segment or condition responsible, 3. the relevant observed or missing evidence, 4. whether the problem is in the program, the input log, or just insufficient evidence. Avoid answering only “there are no diagnostics” when asked why a scenario failed. # FILE: source-notes/LOGLINE_COLLECTOR_DESIGN.md # LOGLINE_COLLECTOR_DESIGN.md ## Document Metadata Version: v0.1\ Date: 2026-06-05\ Session: Logline Language Extension Session 1\ Status: Collector v1 locked design draft\ Authority: Active collector language/runtime design baseline\ Current alignment: Collector v1 and shared expression/runtime integration are implemented; temporal/multi-source alignment through 24 September 2026 is recorded in Section 20. --- ## Version History ### v0.1 — 2026-06-05 Initial locked Collector v1 design. Captured: - program-level and scenario-level collector scopes - built-in collector kinds - collector expression rules - runtime update timing - result model - debugger/report/trace expectations - explicit v1 deferrals Scope: Logline language, compiler/IR, engine/runtime, debugger, and report-facing collector semantics\ Deferred: Event segment design, collector references in segment conditions, generic reducer implementation, native/host functions --- ## 1. Purpose Collectors are first-class Logline accumulators over input log records. They are not executable scenario segments. They do not alter control flow. They observe records and produce deterministic semantic results that can be surfaced in reports and debugger snapshots. Collectors support two scopes: ```text program-level collector one collector instance per program execution scenario-level collector one collector instance per active scenario candidate ``` The syntax is identical in both places. Placement determines scope. --- ## 2. Core Concept Collectors are declarative reducers over the input record stream. Built-in collectors are predefined reducer templates. A future generic reducer collector will expose the reducer shape directly, but still using Logline-native expressions, not native JavaScript or host-language code. Collector v1 implements built-in collector kinds only. Collector v2 design direction includes: ```logline collector GatewayStats { kind =: reducer; initial = { count: 0, sum: 0 }; condition =: fields.service == "gateway"; update = { count: previous.count + 1, sum: previous.sum + fields.latency_ms }; } ``` This is design direction only and not part of the first implementation slice. --- ## 3. Syntax Program-level collector: ```logline collector TotalErrors { kind =: counter; condition =: level == "ERROR"; } ``` Scenario-level collector: ```logline scenario WakeWithWarnings attemptedBy [Wake, Ready] { collector WarningCount { kind =: counter; condition =: level == "WARN"; } transition Wake { signal =: "vehicle_state"; type =: string; condition =: to == "WAKE"; } transition Ready { signal =: "drive_state"; type =: string; condition =: to == "READY"; } } ``` Collector properties are declarative clauses and use the `=:` clause-specification operator with semicolons: ```logline kind =: counter; value =: fields.latency_ms; count =: 5; condition =: level == "ERROR"; ``` Property order inside collector blocks is flexible. Documentation and formatter output should prefer: ```text kind value/count condition ``` Every collector must explicitly declare `kind`. Duplicate collector properties are invalid. Unknown collector kinds are validation errors. --- ## 4. Placement Rules Program-level declarations remain flexible. Constants, program-level collectors, `scenarioDefaults`, and scenarios may appear at program level without forcing a strict top-to-bottom block order. Program-level collectors may appear between scenarios. There may be at most one `scenarioDefaults` block. Inside scenarios, collector declarations must appear before executable segments. Valid: ```logline scenario A { collector ErrorCount { kind =: counter; condition =: level == "ERROR"; } event ErrorSeen { condition =: message contains "error"; } } ``` Invalid: ```logline scenario A { event ErrorSeen { condition =: message contains "error"; } collector ErrorCount { kind =: counter; condition =: level == "ERROR"; } } ``` Collectors must not appear between transitions, events, repeats, parallels, crossroads, or other executable segments. --- ## 5. Names and Visibility Collector v1 follows the rule: ```text All visible names must be unambiguous. ``` Top-level namespace includes: ```text constants scenarios program-level collectors ``` These names must not conflict. Scenario-level namespace includes: ```text scenario-level collectors executable segment names inside that scenario ``` These names must not conflict. A scenario-level collector also may not shadow: ```text top-level constants program-level collectors its owning scenario name ``` Different scenarios may have scenario-level collectors with the same name, because each scenario has its own scope. Future references can disambiguate with dot notation if needed: ```logline ScenarioA.ErrorCount ScenarioB.ErrorCount ``` --- ## 6. Collector Kinds Collector v1 supports: ```text counter sum min max average first last firstN lastN ``` Deferred to v2 or later: ```text topN lowestN list set distinctCount histogram percentile groupBy ``` Collector kind syntax uses unquoted keywords: ```logline kind =: counter; kind =: firstN; kind =: lastN; ``` Not strings: ```logline kind =: "counter"; ``` --- ## 7. Required Properties by Kind ### counter ```text condition optional value not allowed count not allowed ``` If condition is omitted, the counter counts every record seen by that collector. Valid: ```logline collector TotalRecords { kind =: counter; } ``` Valid: ```logline collector ErrorRecords { kind =: counter; condition =: level == "ERROR"; } ``` Invalid: ```logline collector ErrorRecords { kind =: counter; value =: message; } ``` ### sum / min / max / average ```text value required condition optional count not allowed ``` The value expression must evaluate to a numeric value for every contributing record. ### first / last ```text value required condition optional count not allowed ``` The value expression may evaluate to any supported value type. ### firstN / lastN ```text value required count required condition optional ``` `count` must evaluate to a positive integer. Invalid: ```logline count =: 0; count =: -1; count =: 2.5; ``` `count` may be an integer literal or a constant expression. Example: ```logline const SAMPLE_SIZE = 5; collector LastErrors { kind =: lastN; count =: SAMPLE_SIZE; value =: message; condition =: level == "ERROR"; } ``` Unsupported extra properties are validation errors and must not be ignored. --- ## 8. Expression Context Collector v1 `condition`, `value`, and `count` expressions may reference: ```text current record fields constants ``` Collector v1 expressions may not reference: ```text scenario progress segment state event captures other collectors collector results ``` Collectors do not subscribe to event segment outcomes in v1. They evaluate their own record conditions directly. Allowed: ```logline collector ErrorCount { kind =: counter; condition =: message contains "error"; } ``` Deferred: ```logline collector ErrorCount { kind =: counter; condition =: ErrorSeen.passed; } ``` Constants may be referenced even if declared later in the program. Constants are compile-time/static values and are resolved before execution. The compiler may warn on backward constant references for readability, but this is not an error. --- ## 9. Current Record Expression Model The current canonical log record model remains the foundation and will be extended rather than replaced. The current record expression context exposes direct normalized aliases and namespaced/extensible fields. Direct normalized fields: ```text t timestamp message level source signal from to type ``` `t` remains the canonical timestamp field for compatibility. `timestamp` is a normalized expression alias for the same value. Namespaced/extensible fields: ```text fields.* signals.* record ``` Examples: ```logline condition =: level == "ERROR"; condition =: message contains "timeout"; condition =: fields.service == "gateway"; condition =: signals.vehicle_state == "WAKE"; value =: record; ``` `record` is a reserved expression name for the full extended canonical Logline record object. The original unprocessed input payload or raw line, when available, is accessed through: ```logline record.raw ``` No direct `raw` alias is introduced for now. If an imported record has a generic field with the same name as a direct normalized alias, the direct name refers to the normalized field and the generic field is accessed through `fields`. Example: ```text level normalized level fields.level imported/generic field named level ``` --- ## 10. Missing Field Behavior If a collector condition references a missing field, the affected predicate/comparison evaluates false for that record and the collector remains valid. Example: ```logline condition =: fields.latency_ms > 500 && level == "ERROR"; ``` If `fields.latency_ms` is missing: ```text fields.latency_ms > 500 evaluates false the full condition evaluates false the collector remains valid ``` The same rule applies to direct normalized fields such as `message`, `level`, `source`, `signal`, `from`, `to`, `timestamp`, and `t`. If a record satisfies the collector condition but the value expression resolves to a missing value, the collector becomes invalid and the engine emits a deterministic diagnostic. This applies to: ```text sum min max average first last firstN lastN ``` Rule: ```text A contributing record must produce a valid value. ``` --- ## 11. Text and Regex Operators Collector conditions use the general Logline expression language. Text/pattern operators include: ```text contains startsWith endsWith matches ``` Examples: ```logline condition =: message contains "timeout"; condition =: message startsWith "ERROR"; condition =: message endsWith "failed"; condition =: message matches /timeout after \d+ ms/; ``` Text operators use camelCase where needed. Preferred: ```logline message startsWith "ERROR"; message endsWith "timeout"; ``` Regex used by `matches` follows ECMAScript/JavaScript regex semantics. Regex matching is case-sensitive by default. ```logline condition =: message matches /timeout/; ``` For case-insensitive matching, use the `i` flag: ```logline condition =: message matches /timeout/i; ``` Logline v1 regex literals allow these ECMAScript flags: ```text i m s u ``` Unsupported flags such as `g`, `y`, and `d` are rejected. Invalid regex literals are compile/validation errors. Regex capture groups are allowed for matching, including named groups, but capture binding/reference semantics are deferred. Allowed: ```logline collector RequestCount { kind =: counter; condition =: message matches /request (?\w+) started/; } ``` Deferred: ```text referencing id in later expressions exposing regex captures as collector/event bindings ``` If a text operator is used on a non-text value at runtime, the collector becomes invalid and a deterministic diagnostic is emitted. If a text operator is used on a missing field in a collector condition, the predicate evaluates false and the collector remains valid. --- ## 12. Runtime Update Timing Collector v1 record-step update order: ```text For each input record N: 1. Bind current record N. 2. Update program-level collectors. 3. Update scenario-level collectors for already-active candidates. 4. Evaluate active candidates. 5. Spawn new candidates. 6. Initialize and update scenario-level collectors for newly spawned candidates on record N. 7. Evaluate newly spawned candidates on record N. 8. Continue normal same-record stabilization. ``` Scenario-level collectors include the spawning record. Scenario-level collectors update only while their candidate is active. They freeze when the candidate reaches a terminal/final state. Program-level collectors update once for every input record from execution start until finalization, independent of scenarios and candidates. Collectors do not update again during same-record stabilization. They update once per record per scope, not once per internal segment advancement. At end of input, collectors freeze during finalization. There is no synthetic end-record update. Scenario-level collectors update once per record per candidate, regardless of how many parallel branches or structured scopes are active. Collectors deal with records, not branches. This avoids double-counting in parallel or nested structured execution. --- ## 13. Runtime Type Behavior Collector conditions, when present, must evaluate to boolean. If a collector condition evaluates to a non-boolean value at runtime: ```text emit deterministic diagnostic mark collector invalid keep collector invalid for the rest of its lifetime ``` Type errors should be caught at compile/validation time when statically obvious. Example static error: ```logline collector Bad { kind =: counter; condition =: 5; } ``` Record-dependent type errors become deterministic runtime diagnostics. Example runtime error: ```logline collector Bad { kind =: counter; condition =: fields.errorCode; } ``` For `sum`, `min`, `max`, and `average`, every contributing record must produce a numeric value. If a contributing record produces a non-numeric value: ```text emit deterministic diagnostic mark collector invalid do not silently ignore the contribution do not produce a partial numeric result ``` Once invalid, a collector stays invalid for the rest of its lifetime. Invalid collector state affects only that collector result. Scenario/candidate execution continues normally. --- ## 14. Result Model Collector v1 result shape is conceptually: ```ts type CollectorResult = { status: 'valid' | 'invalid'; hasValue: boolean; value?: unknown; contributionCount: number; firstRecordIndex?: number; lastRecordIndex?: number; diagnostic?: CollectorDiagnostic; }; ``` Exact TypeScript names can be decided during implementation. Meaning: ```text status = valid, hasValue = true collector completed normally and has a meaningful value status = valid, hasValue = false collector completed normally but has no meaningful value because no records contributed status = invalid collector encountered a deterministic collector error ``` For `counter` with zero contributions: ```text status = valid hasValue = true value =: 0 ``` For `firstN` / `lastN` with zero contributions: ```text status = valid hasValue = true value =: [] ``` For `sum`, `min`, `max`, `average`, `first`, and `last` with zero contributions: ```text status = valid hasValue = false ``` Specifically, `sum` with zero contributions has `hasValue = false`. It does not expose `0` as a meaningful result when no records contributed. If `hasValue = false`, `value` is not semantically meaningful. For invalid collectors, `contributionCount` remains meaningful as valid contributions before invalidation. The final value must not be treated as valid. `firstRecordIndex` and `lastRecordIndex` refer only to valid contributing records. Records that satisfy the condition but cause invalidation are captured in diagnostic/evidence, not as valid contribution indices. When a collector becomes invalid, the diagnostic must include: ```text collector name/id invalidating record index expected value type actual value actual value type ``` Example: ```text Collector MaxLatency expected numeric value but got string "slow" at record 42. ``` --- ## 15. Evidence, Debugger, and Trace Collector v1 evidence exposes at least: ```text final result contribution count first contributing record index last contributing record index diagnostic if invalid ``` For `firstN` and `lastN`, the result already contains bounded contributing values. Collector v1 should not store full contribution history by default. Exceptions: ```text firstN stores bounded first N collected values lastN stores bounded last N collected values ``` Debugger snapshots must expose collector state. Program-level collectors are exposed at run/session snapshot level. Scenario-level collectors are exposed per candidate snapshot. Debugger snapshots should expose compact collector state evidence: ```text status hasValue value contributionCount firstRecordIndex lastRecordIndex diagnostic if invalid ``` Detailed contribution history is deferred. The engine trace/observability layer should emit collector-related trace events in rich mode. Examples: ```text collector initialized collector contributed collector invalidated collector finalized/frozen ``` `collector skipped` events should be optional, summarized, or disabled by default to avoid excessive trace volume. Preferred rich trace baseline: ```text emit initialization emit contribution emit invalidation emit freeze/finalization summarize skipped/non-contributing counts where useful ``` --- ## 16. Reports and Presentation Boundary Both program-level and scenario-level collectors produce semantic results. Default Workbench/report behavior should show all collector results unless report configuration hides them. Reporting visibility/configuration is not part of Logline semantic syntax. No collector syntax such as: ```logline report = hidden; visible = false; display = "..."; label = "..."; description = "..."; ``` Collector declarations define semantic collection only. Report visibility, labels, grouping, formatting, and display of `hasValue = false` belong to: ```text Workbench/report configuration visual metadata report templates user preferences external presentation layer ``` They must not affect engine semantics. Reports must distinguish invalid collectors from collectors with no contributing records. Example: ```text No contributing records: MaxLatency = no value Invalid collector: MaxLatency = invalid Diagnostic: expected numeric value, got string at record 42 ``` The representation of `hasValue = false` is presentation-level and may be configurable as blank, undefined, null, unknown, empty, no value, or another label. --- ## 17. Comments and Documentation Collector descriptions are not semantic collector properties. Use normal DSL comments or external metadata/report configuration instead. Preferred: ```logline // Counts all records with ERROR level. collector ErrorCount { kind =: counter; condition =: level == "ERROR"; } ``` Not preferred: ```logline collector ErrorCount { kind =: counter; description = "Counts all records with ERROR level."; } ``` Normal comments before collectors should be preserved and treated as the recommended way to document collector intent. Comments remain strictly non-semantic. They never affect: ```text compiler behavior engine behavior collector behavior report semantics ``` External documentation/report tools may choose to display comments, but that is presentation/tooling behavior, not Logline semantics. --- ## 18. Explicit Deferrals Deferred from Collector v1: ```text event segment design collector result references in segment conditions scenario progress references in collector expressions event/capture references in collector expressions collector-to-collector references generic reducer implementation native JavaScript or host-language reducer bodies registered host functions topN / lowestN list / set distinctCount histogram percentile groupBy custom object literals if not already cleanly supported by expression grammar full contribution history branch-scoped collectors reporting syntax inside Logline ``` No inline native JavaScript or host-language function bodies are allowed in `.lgl` for Collector v1 or v2. Collectors remain Logline-native and portable. Registered host functions may be reconsidered later as an explicit extension mechanism, but they are not part of the current collector design. --- ## 19. Collector v1 Implementation Target Collector v1 should implement: ```text program-level collectors scenario-level collectors built-in kinds: counter sum min max average first last firstN lastN record/constant expression context dot-notation record field access reserved record reference ECMAScript regex matching with allowed flags i/m/s/u runtime diagnostics for invalid collector contributions collector result projection debugger snapshot collector state report-facing collector result data rich trace collector events ``` Collector v1 must preserve the engine discipline: ```text no control-flow changes from collectors no topology-specific runtime hacks no native code execution in semantic source no presentation configuration in semantic syntax runtime executes validated compiler/IR/plan semantics ``` --- ## 20. Current Implementation Alignment — 24 September 2026 The original Collector v1 design remains the semantic baseline. This section records the current implementation and the later temporal/multi-source integration that did not exist when the June design was written. ### 20.1 Collector v1 is implemented The current Program IR and Engine runtime implement the locked v1 kinds: ```text counter sum min max average first last firstN lastN ``` Program-level collector instances remain program-execution state. Scenario-level collector instances remain candidate-local state. Collectors continue to observe records without altering executable control flow. The generic reducer direction in the earlier design remains deferred; the implementation has not turned `.lgl` into a host-language callback/reducer environment. ### 20.2 Collectors use the shared expression language Collector `condition`, `value`, and `count` expressions execute through the same expression runtime used by the rest of Logline. Later expression-library additions therefore apply to collectors when their type/scope contracts permit them; they are not collector-private operators. This includes the implemented exact temporal expression surface. ### 20.3 Temporal runtime bindings propagate into collectors Program- and scenario-level collector evaluation receives the same host-injected `TemporalRuntimeBindings` used by the rest of Engine expression evaluation. Therefore collector expressions can explicitly use resolved temporal constructs such as: ```text time.anchor(...) time.reference(...) time.toCte(...) ``` subject to the same typing, exactness, missing-binding, and semantic-compatibility rules as equivalent expressions in segments or Groups. Canonical record timestamps have already been normalized before collector observation. A collector's explicit payload-time conversion derives an expression value only; it does not change canonical ordering or collector update timing. ### 20.4 Compiler temporal-use discovery includes collectors Compiler temporal analysis traverses both program-level and scenario-level collector expressions. For `time.reference(...)` and `time.anchor(...)` use sites: - literal/string-constant `source` and `id` operands can be classified as compiler-static; - record-derived or otherwise computed operands remain runtime-dependent; - source spans are retained when available. Enterprise admission uses trusted compiler-produced Program Bundle analysis to preflight fully static temporal binding identities. Runtime-dependent identities remain Engine lookups if the collector expression executes. ### 20.5 Multi-source collector semantics Collectors continue to observe the one canonical record stream presented by Engine. In a multi-source run that stream is the deterministic post-normalization composition of all admitted source cursors. Collector semantics do not gain: ```text source-local cursors one collector loop per source implicit joins independent temporal normalization source-specific ordering rules ``` Source selection is expressed through ordinary record predicates such as `source`, `channel`, `fields.*`, and `signals.*`. Program-level collectors observe the canonical run stream according to their existing timing contract; scenario-level collectors observe records for their active candidate scope according to the existing candidate/collector rules. ### 20.6 Remaining product projection work The headless runtime semantics above are implemented. Workbench multi-source configuration, temporal-preflight visualization, source-aware merged preview/navigation, and complete report/debugger provenance presentation remain part of the broader Workbench integration work. Those projections must consume Engine/compiler truth and must not change collector evaluation semantics. # FILE: source-notes/LOGLINE_GROUP_AND_EXPRESSION_EXTENSION_DESIGN.md # Logline Group and Expression Extension Design **Document type:** Language, compiler, runtime, evidence, and Workbench design **Status:** Locked design baseline **Date:** 20 September 2026 **Alignment amendment 1:** Multi-source review completed and aligned on 20 September 2026 **Implementation alignment 2:** Language/compiler/Engine temporal and multi-source runtime alignment recorded on 24 September 2026 **Scope:** Group segment, immutable derived values, structured results, general collection operators, exact temporal functions, assertions, evidence, diagnostics, and projection requirements ## 1. Purpose This document defines the locked extension design for bounded runtime observation and batch derivation over canonical log records. The extension introduces: - a generic `group` executable segment; - record collection and completion conditions; - immutable derived bindings evaluated as a dependency graph; - optional named assertions; - typed immutable results available to downstream segments; - a general expression-operator expansion for collections, structured values, exact numerics, bitwise operations, and time; - controlled conversion of temporal values carried inside record payload fields into the run's Canonical Timeline Epoch (CTE); - compiler, runtime, diagnostic, evidence, debugger, and report requirements. The design is motivated by runtime reconstruction of logical observations distributed across multiple physical records, but it is intentionally domain-neutral. It must support DID-style readouts, multiline entries, fragmented messages, bounded request/response exchanges, snapshots, correlated status blocks, and similar log-processing problems without making Logline specific to any one source format. This document is separate from the problem definition: ```text LOGLINE_RUNTIME_RECORD_RECONSTRUCTION_PROBLEM_DEFINITION.md ``` The problem definition remains the use-case and requirements baseline. This document defines the locked language solution. ## 2. Relationship to existing Logline semantics The extension preserves the current architecture: - canonical records remain the only records presented to the engine; - each canonical record already has an exact CTE ordering timestamp; - multi-source synchronization and deterministic merge remain outside ordinary segment semantics; - candidates remain isolated execution contexts; - Transition, Event, Repeat, Parallel, Crossroads, collectors, candidate policies, importance, evidence, and reporting retain their existing meanings; - Event continues waiting until its condition evaluates true and does not gain retry as part of this design; - collectors remain stream observers and do not become control-flow constructs; - the Workbench remains a projection of compiler and engine truth. Group does not introduce a secondary record stream, an internal program counter, a nested mini-log, or preprocessing hidden inside the segment. ## 3. Design principles The design follows these rules: 1. **One execution model.** Group is a normal executable segment in the existing candidate and structured-control-flow model. 2. **No record emission.** Group never inserts, replaces, rewrites, delays, reorders, or emits canonical records. 3. **No cursor manipulation.** The program counter remains on Group while it observes records; the canonical record cursor advances normally. 4. **Strict sequential consumption.** Records inspected by a sequential Group are consumed during that Group execution. A completing record is not replayed into the next sequential leaf segment. 5. **Explicit parallel observation.** If multiple segments must observe the same records, the author uses Parallel. 6. **Bounded observation.** A mandatory completion condition defines semantic completion; governed run-profile limits protect resources. 7. **Batch semantics.** Derived bindings, assertions, and the result are evaluated only after the captured collection is frozen. 8. **Immutability.** Captured records, derived bindings, and published results are immutable. 9. **Determinism.** Missing values, duplicate keys, empty collections, ties, ordering, temporal interpretation, and failure behavior are explicit. 10. **One expression language.** New operators belong to the general Logline expression library, not a Group-specific sublanguage. 11. **No arbitrary code.** No inline JavaScript, host callback, plugin function, loop, mutable reducer, or native extension body is permitted in Logline source. 12. **Evidence without semantic drift.** Evidence configuration changes retained detail, never execution values or outcomes. ## 4. Group concept A Group is a bounded observation scope over the canonical record stream. When the program counter reaches Group: - Group execution begins immediately; - lifecycle state is initialized; - each canonical record is inspected in order; - the collection condition decides whether that record becomes a member; - the completion condition decides whether observation ends; - after completion, the collection is frozen and processed once; - if processing succeeds, an immutable result becomes available downstream. Group execution may complete with zero collected records. This is important for bounded absence checks such as proving that no matching observation occurred within an explicitly observed interval. There is no separate semantic state in which Group is “opened by” its first matching record. The observation scope starts when execution reaches the segment. The first match merely creates the first collection member. ## 5. Locked semantic shape The locked semantic vocabulary and canonical formatter shape are: ```logline group Example { collectionCondition =: ; completionCondition =: ; derive { = ; } assert { condition =: ; message =: ; } result =: ; importance =: ; } ``` The source-level operator boundary is deliberate: declarative Group/assertion/collection-operator clauses use `=:`, while immutable names introduced inside `derive` and named function arguments use ordinary `=`. Equality inside expressions remains `==`, and object entries remain `:`. The locked semantic names are: - **collection condition** — selects collection members; - **completion condition** — ends observation and begins batch processing. Both conditions and `result` are mandatory. `derive` may contain zero or more bindings. Assertions are optional and may appear zero or more times. Group has no retry property. Group properties may be authored in any order. Duplicate singleton properties are validation errors. The formatter emits the canonical order shown above: collection condition, completion condition, derive block, assertions, result, and importance. Publishing a typed result is the defining distinction between Group and a pure waiting/window construct. A validation-only Group publishes a simple Boolean or structured summary. ## 6. Per-record lifecycle For each record inspected while Group is active, the runtime performs the following order exactly: 1. Bind the current canonical record. 2. Increment the inspected-record count. 3. Evaluate `collectionCondition`. 4. If it is true, add the current record to the collection. 5. Evaluate `completionCondition` against the current record and updated Group state. 6. If it is false, advance to the next canonical record while keeping the program counter on Group. 7. If it is true, freeze the captured collection and proceed to batch processing. Consequences: - a record that satisfies both conditions is collected before completion; - a record that fails the collection condition may still complete Group; - the completion record is consumed by Group whether or not it was collected; - the next sequential leaf segment begins with the following canonical record; - Group introduces no record replay or look-behind behavior. Normal engine stabilization may settle structured-control state after Group completes, but it must not make the completing physical record available to the next sequential leaf. ## 7. Group execution context While Group is active, its conditions have access to the ordinary current-record expression context plus read-only lifecycle state. Required lifecycle values are: ```text group.startIndex group.startTimestamp group.currentIndex group.currentTimestamp group.inspectedCount group.collectedCount group.elapsed records ``` Semantics: - `startIndex` is the canonical merged-stream index of the first record inspected by this Group execution; - `startTimestamp` is that record's CTE timestamp; - `currentIndex` and `currentTimestamp` identify the current canonical record; - `inspectedCount` includes the current record before `collectionCondition` is evaluated; - `collectedCount` excludes the current record during `collectionCondition` evaluation and includes it during `completionCondition` evaluation if it matched; - `elapsed` is exact CTE duration from `startTimestamp` to `currentTimestamp`, not wall-clock engine time; - `records` is the read-only collection accumulated so far. The completion condition may inspect the current record, lifecycle state, and accumulated collection. It may not reference `derive` bindings or `result`, because those are evaluated only after completion. ## 8. Completion, end-of-input, and resource bounds `completionCondition` is the only normal semantic completion trigger. If end-of-input occurs before it becomes true: - Group remains incomplete; - no batch result is published; - partial collection state may be retained as evidence according to evidence configuration; - candidate/scenario finalization follows the existing incomplete-segment rules. There is no implicit “complete at end-of-input” behavior. To prevent malformed input or an incorrect completion predicate from exhausting resources, the Run Profile or governed engine settings must define auditable Group safety limits, including at least: - maximum collected records; - maximum captured bytes or equivalent retained-record budget. Additional implementation limits may cover inspected records, result size, derivation work, or retained evidence. Exceeding a limit is a deterministic Group failure with a structured diagnostic. It is not successful semantic completion and must not silently truncate the collection. ## 9. One collection per Group execution Each executing Group owns exactly one collection. Group does not create hidden concurrent partitions keyed by record values. Records with multiple keys may be captured into one bounded collection and organized during derivation using `groupBy` or `indexBy`. If independent collections must progress concurrently, the author uses multiple Group segments inside Parallel branches. If future use cases require dynamically keyed concurrent completion, that capability must be designed separately rather than hidden in Group v1. ## 10. Frozen batch and immutable derivation graph When `completionCondition` becomes true, the captured record collection is frozen. `derive` contains named immutable bindings, not function declarations or imperative assignments. Example: ```logline derive { phoneTimestamp = phoneRecord.timestamp; phoneRecord = records.single(...); } ``` Bindings are dependency-ordered rather than textually ordered: - forward references are allowed; - the compiler constructs an acyclic dependency graph; - evaluation follows dependency order; - duplicate names are compile-time errors; - unknown references are compile-time errors; - cycles are compile-time errors; - a binding cannot be reassigned; - evaluation is deterministic and independent of declaration order. Derived values may be scalars, exact timestamps, durations, records, arrays, keyed collections, structured objects, or typed optional values. Derived bindings are private to Group. Only the declared `result` crosses the Group boundary. ## 11. Assertions and success Group may contain zero or more named assertions. Processing order is fixed: ```text freeze records -> derive -> assertions -> result ``` Default Group success requires: - the completion condition became true; - all derived expressions evaluated successfully; - all invoked operator contracts were satisfied; - all declared assertions passed; - result construction succeeded. An empty collection or empty derived collection is valid by default. Domain rules such as “at least one matching record must exist” are expressed through an assertion or an operator with explicit cardinality semantics. Assertions: - are optional; - have unique Group-local identities; - evaluate after all required derived bindings are available; - use the general expression language; - may refine domain success rules; - may not convert structural errors, type errors, unsupported temporal conversions, or invalid operator evaluations into success; - are all evaluated where dependencies permit, so diagnostics can report every violated invariant rather than failing after the first false assertion. - require a unique name and Boolean `condition`; - may provide an optional literal diagnostic `message`. Locked form: ```logline assert TimestampCoverage { condition =: timestamps.count == actions.count; message =: "Every action must have exactly one timestamp."; } assert UniqueEventIds { condition =: duplicateEventIds.count == 0; } ``` If an assertion fails: - Group fails; - no downstream result is published; - the frozen collection, derived summaries, assertion outcomes, and diagnostics are retained according to evidence settings. ## 12. No Group retry Group does not support retry. Re-evaluating the same frozen collection would produce the same deterministic result. Continuing to add records after completion would mean that the completion condition was incorrect. Waiting for a separate future observation is expressed by Repeat around Group, not by retry inside Group. Repeated DID or snapshot readouts are therefore modeled naturally as repeated Group executions. Every completed iteration retains its own result. Event retry is also outside this design. Event retains its established wait-until-condition-true semantics. ## 13. Result model `result` may produce any typed immutable Logline value: - scalar; - CTE timestamp; - source-domain timestamp where explicitly typed; - duration; - canonical record reference; - array; - keyed collection; - typed optional; - structured object. Examples: ```logline result =: latestPhoneTimestamp; ``` ```logline result =: { phone: latestPhone, actionCount: phoneActions.count }; ``` After successful completion, downstream access is through explicit attributes such as: ```text GroupName.completed GroupName.succeeded GroupName.startTimestamp GroupName.completionTimestamp GroupName.inspectedCount GroupName.collectedCount GroupName.result ``` Group must not expose a generic `timestamp`, because that could ambiguously mean observation start, completion, or a derived effective event time. Effective event timestamps belong in the author-defined result. Before successful completion, `result` is unavailable. References follow the existing guarded segment-attribute model: ```logline condition =: SomeGroup.completed && SomeGroup.succeeded && SomeGroup.result.detected; ``` Short-circuit evaluation prevents premature result access. Group does not introduce a new missing-reference convention. ## 14. Candidate, structured-control, and reference scope Group names have lexical scope in the scenario. Group values belong to the executing candidate. This distinction is mandatory because one scenario may have multiple concurrent candidates. Each candidate owns its own Group lifecycle, collection, derived values, assertions, result, and evidence. ### 14.1 Parallel Multiple Group segments in Parallel maintain independent collections according to existing parallel record-observation semantics. Sibling branches may coordinate through existing guarded segment references. A branch may test another Group's completion status and wait until its result is available. No hidden dependency or implicit blocking is introduced. ### 14.2 Repeat A Group executed inside Repeat may produce multiple results. All successful results are retained in repeat-iteration order. Earlier results are never silently overwritten by the latest result. Each retained entry preserves: - iteration identity; - Group result; - observation start and completion positions; - configured provenance. Selection of one result is explicit through ordinary collection operators such as `single`, `first`, `last`, `minBy`, or `maxBy`. ### 14.3 Crossroads A Group declared only in one Crossroads case remains case-scoped. An unconditional downstream reference is invalid unless every possible selected path makes the required result available. Otherwise the program must handle the selected case or use an explicit optional value. ### 14.4 Candidate opening If Group is the first executable segment and: ```logline candidateOpening =: conditionPass; ``` the Group's collection condition acts as the candidate-opening condition, consistent with other condition-bearing segments. Consequences: - `candidateOpening =: profileMatch` may begin a bounded Group observation that collects zero records; - `candidateOpening =: conditionPass` does not create a candidate until the collection condition passes, so a zero-record initial Group outcome is impossible in that mode. ### 14.5 Attempt evidence Group names may be referenced by `attemptedBy`. Group contributes attempt evidence when its completion condition becomes true, before derivation/assertion success is known. Therefore: - a successful Group counts; - an empty but completed Group counts; - a completed Group that later fails derivation or assertion still counts as attempted; - an incomplete Group at end-of-input does not contribute attempt evidence through that reference. ### 14.6 Importance Group supports the existing `importance` model. Incomplete or failed Group outcomes participate in current essential/fallback behavior without a Group-specific failure category. ## 15. General expression-library expansion The new operators belong to the general Logline expression language. They are available in Group, Transition, Event, Crossroads, collectors, assertions, results, and future constructs whenever operand types and scope permit. There is no Group-only expression evaluator. The initial semantic operator set is: | Area | Initial capabilities | |---|---| | Select and transform | `filter`, `select` | | Organize | `groupBy`, `indexBy`, `distinctBy` | | Cardinality | `count`, `any`, `all`, `single`, `optionalSingle` | | Ordered choice | `first`, `last`, `minBy`, `maxBy`, `sortBy` | | Aggregate | `sum`, `min`, `max` | | Keyed access | `keys`, `values`, explicit key lookup | | Optional values | `.present`, guarded `.value`, `.orElse(...)` | | Structure | array/object construction and field/index access | | Bitwise | AND, OR, XOR, NOT, left shift, right shift, mask | | Exact numeric conversion | integer/decimal parsing, explicit conversion, explicit rounding | | Temporal construction | duration construction, timestamp parsing, epoch interpretation | | Temporal alignment | controlled conversion to CTE | | Temporal arithmetic | addition, subtraction, difference, absolute duration | | Temporal comparison | before, after, within, between | | Temporal precision | floor, ceiling, and rounding with explicit precision | Existing arithmetic, comparison, Boolean, text, regex, and membership behavior remains available. Initial exclusions are deliberate: - no mutable variables; - no general `reduce` or `fold`; - no loops; - no arbitrary lambdas; - no automatic collection joins; - no host-language functions; - no native plugin bodies authored in `.lgl`; - no implicit time, unit, epoch, timezone, or numeric conversions. ## 16. Collection-item bindings Collection operations introduce an explicit local item name. They do not rely on an implicit current item, because implicit binding becomes ambiguous in nested transformations. The locked binder form is: ```text each { } ``` It is valid only inside supported collection operators. It does not create a general lambda-expression grammar. Locked binder syntax: ```logline phoneRecords = records.filter(each record { condition =: record.fields.action == "phone"; }); ``` ```logline offsetsByEvent = records.indexBy(each record { condition =: record.fields.role == "timestamp"; key =: record.fields.eventId; value =: time.duration(record.fields.value, milliseconds); }); ``` Ordered selectors use the same binding form: ```logline latestPhone = phoneEvents.maxBy(each event { key =: event.effectiveTimestamp; ties =: fail; }); ``` This is a restricted collection-item binder, not a general lambda or user-defined function mechanism. ## 17. Collection determinism and ambiguity Captured `records` preserve canonical stream order exactly as observed. Group performs no automatic reordering. Semantic ordering must be explicit, for example by sorting on a reconstructed effective timestamp. Keyed collections do not imply iteration order. Ordered iteration requires an explicit sort. Ambiguous operations fail by default: - `single` fails for zero or multiple matches; - `optionalSingle` returns empty for zero and fails for multiple matches; - `indexBy` fails on duplicate keys unless `duplicates =: keepFirst` or `duplicates =: keepLast` is explicitly supplied; authors use `groupBy` when all values must be retained; - `minBy` and `maxBy` fail on unresolved ties unless `ties =: first`, `ties =: last`, or `ties =: all` is explicitly supplied; - empty aggregates follow explicit operator contracts rather than inventing values. Ordering-based policies use canonical stream order and are never selected implicitly. ## 18. Optional values and missing fields The extension introduces a typed optional value rather than a general-purpose `null` as the normal representation of “no selected value.” An optional exposes `.present`, guarded `.value`, and explicit fallback through `.orElse(...)`. General-purpose `null` is not introduced by this design. Missing-field rules remain context-sensitive and consistent with current Logline behavior: - a missing field used in a predicate causes that predicate to be false for the current item or record; - a missing value required for projection, arithmetic, key construction, temporal interpretation, or result construction is an error unless explicitly handled as optional; - no missing value is silently converted to zero, empty text, epoch zero, or another default. ## 19. Temporal values carried in record payloads The CTE invariant remains: > Every canonical record presented to the engine already carries an exact CTE ordering timestamp. The extension adds a necessary distinction: record payload fields may themselves contain temporal information that is not the canonical record timestamp. Such payload values may represent: - an absolute timestamp; - a timestamp in a declared source-native clock domain; - a displacement from the containing record's CTE timestamp; - a displacement from a file/source-wide anchor; - a duration encoded as an apparent timestamp relative to an epoch; - a numeric duration in seconds, milliseconds, microseconds, nanoseconds, or another declared exact unit; - any supported form encoded as text. Representation does not determine meaning. The Logline expression must declare the interpretation. ## 20. Temporal type and conversion rules The expression system must distinguish at least: - CTE timestamp; - source-domain timestamp with an identified domain; - duration; - exact integer; - exact decimal where supported; - text awaiting explicit parsing. The common high-level conversion destination is an exact CTE timestamp. The locked high-level conversion form is: ```logline time.toCte( value, as = , anchor = , temporalReference = ) ``` Examples: ```logline time.toCte( record.fields.value, as = time.displacement(unit = nanoseconds), anchor = record.timestamp ) ``` ```logline time.toCte( record.fields.value, as = time.epochEncodedDisplacement( epoch = unix, format = iso8601 ), anchor = record.timestamp ) ``` ```logline time.toCte( record.fields.value, as = time.epochTimestamp( epoch = unix, unit = milliseconds ), temporalReference = time.reference( source = record.source, id = "primary-clock" ) ) ``` The `time` namespace contains typed temporal construction, parsing, conversion, arithmetic, comparison, and precision functions. This does not replace existing infix text operators such as `contains`, `startsWith`, or `matches`. Temporal conversion requires named parameters and typed descriptors that do not have a clear or safe infix form. Implementations may lower `time.toCte` to smaller typed primitives such as parse, construct duration, subtract epoch, add anchor, and apply temporal mapping, but the observable semantics remain those defined here. ## 21. Temporal anchors and preflight responsibility Valid anchors may include: - the current canonical record timestamp; - the source/file start already mapped to CTE; - a manifest-declared acquisition origin; - another named anchor resolved during temporal preflight; - a supported absolute epoch. Importer and preflight responsibilities remain authoritative: - define source temporal semantics; - validate timestamp format and clock-domain declarations; - resolve source/file anchors; - resolve mappings into the run timeline; - reject ambiguous, unsupported, unanchored, contradictory, or inexact mappings. Group expressions may apply a preflight-resolved mapping to a typed payload value. They may not reconstruct importer logic or guess missing metadata. This refines the existing CTE architecture without weakening it: - canonical record ordering is fully normalized before engine execution; - payload temporal interpretation is explicit program behavior; - any source-domain-to-CTE mapping used by an expression was resolved before execution; - derived CTE values are result data and do not alter stream order or cursor position. ## 22. Exactness requirements Temporal and numeric processing must not use binary floating-point approximation for canonical results. Rules include: - every unit is explicit; - every epoch is explicit; - text format and timezone/offset interpretation are explicit; - decimal inputs must map exactly to supported precision or use an explicit rounding policy; - timestamp plus duration returns timestamp; - timestamp minus timestamp returns duration; - timestamp minus duration returns timestamp; - invalid type combinations are rejected; - unsupported drift, clock reset, wrap, discontinuity, leap-second, or time-scale behavior is rejected unless separately designed and validated; - no magnitude-based unit inference is permitted. ## 23. Worked correlated-record example The following normative example uses the locked grammar shape. The domain names and record fields are illustrative. ```logline group ReconstructReadout { collectionCondition =: source == "did-source" && fields.readoutId == "access-history"; completionCondition =: group.collectedCount == 30 || group.elapsed >= time.duration(2, seconds); derive { offsetsByEvent = records.indexBy(each record { condition =: record.fields.role == "timestamp"; key =: record.fields.eventId; value =: time.duration(record.fields.value, milliseconds); duplicates =: fail; }); phoneEvents = records.select(each record { condition =: record.fields.action == "phone"; value =: { eventId: record.fields.eventId, effectiveTimestamp: time.add( record.timestamp, offsetsByEvent[record.fields.eventId] ), record: record }; }); latestPhone = phoneEvents.maxBy(each event { key =: event.effectiveTimestamp; ties =: fail; }); } assert TimestampAvailableForEveryPhoneEvent { condition =: phoneEvents.count == records.filter(each record { condition =: record.fields.action == "phone"; }).count; } result =: { latestPhone: latestPhone, phoneEventCount: phoneEvents.count }; } ``` The example demonstrates: - bounded runtime observation without preprocessing; - unordered correlation by explicit event key; - exact temporal reconstruction; - explicit tie behavior; - named validation; - structured immutable result; - retained record provenance. ## 24. Runtime errors and diagnostics Both mandatory conditions must be statically Boolean where determinable. Runtime predicate behavior follows existing Logline rules: - missing field in a predicate evaluates false; - a record-dependent type mismatch emits a deterministic diagnostic and evaluates false for that record; - Group remains active and may evaluate later records. Post-completion errors fail Group. Required diagnostic categories include: - derivation dependency cycle; - duplicate derived binding; - unknown binding; - invalid collection-item reference; - invalid operator operands; - missing required projected value; - invalid key; - duplicate key without resolution policy; - invalid cardinality; - empty aggregate where a value is required; - unresolved tie; - failed assertion; - invalid temporal representation; - unsupported temporal interpretation; - missing temporal anchor or reference; - inexact temporal conversion without rounding policy; - Group safety limit exceeded; - result construction failure; - incomplete Group at end-of-input. Diagnostics must include stable machine codes, Group and candidate identity, source spans, relevant record references, operator/assertion identity, technical details, and actionable user guidance. ## 25. Provenance and evidence Derived values automatically propagate provenance from contributing records and temporal mappings. Authors do not manually copy provenance into `result`. Provenance metadata does not affect value equality. Where practical, structured results retain field-level provenance plus an aggregate result provenance set. Retention follows existing execution/report evidence configuration. A conceptual policy is: - `none` — no persisted contribution graph beyond transient runtime needs; - `summary` — sources, record ranges/counts, mapping identities, and aggregate derivation information; - `full` — contributing record identities, field-level derivation paths, temporal anchors, conversions, assertion evidence, and operator evidence. Evidence level must never change: - collection membership; - completion; - derived values; - assertion outcomes; - result values; - candidate/scenario outcomes. Failed Groups retain debugging evidence according to the configured level even though they publish no downstream result. ## 26. Compiler and validator requirements The language package must be implemented before engine or Workbench changes. Compiler and validator responsibilities include: - parse and validate Group syntax; - require both conditions; - enforce Boolean condition types where statically known; - define Group-local scopes; - validate unique assertion and binding identities; - construct and validate the derive dependency graph; - reject cycles and unknown references; - type arrays, keyed collections, objects, optionals, timestamps, durations, and records; - validate collection-item binder scope; - validate operator names and typed signatures through the shared operator registry; - validate explicit ambiguity policies; - validate temporal interpretation descriptors; - validate guarded result access according to existing segment-attribute rules; - validate Repeat, Parallel, Crossroads, candidate-opening, `attemptedBy`, and importance placement; - preserve source spans and semantic identities through lowering; - lower Group into an explicit execution-plan structure without embedding presentation behavior. The language package must not import engine implementation details. The shared dependency boundary remains authoritative. ## 27. Operator registry requirements Compiler, engine, and Workbench must consume one canonical operator definition model through the established central dependency boundary. Each operator contract must define: - stable identity and language spelling; - generic input and output types; - admissible operand types; - missing/optional behavior; - empty-collection behavior; - duplicate/tie policy support; - deterministic ordering behavior; - runtime diagnostic codes; - provenance propagation behavior; - purity and determinism requirements. Adding a future pure operator should not require a new Group lifecycle property or a new evaluator architecture. User-authored native operator bodies remain out of scope. ## 28. Engine requirements The engine implementation must: - allocate Group state per candidate, structured branch, and repeat iteration; - initialize Group lifecycle at program-counter entry; - inspect each canonical record at most once per active Group execution; - preserve strict sequential record consumption; - keep independent state for Groups in Parallel branches; - freeze the captured collection atomically on completion; - evaluate the derived dependency graph deterministically; - evaluate all possible assertions; - publish result only after success; - preserve repeat iteration results; - enforce Run Profile safety limits; - emit structured trace and diagnostic events; - retain configured evidence without changing semantics; - never insert or reorder canonical records; - never invoke host-language semantic callbacks. Collectors retain their established update timing and observe canonical records independently. Group must not cause collectors to update twice during internal completion, derivation, assertion, or result evaluation. ## 29. Debugger and report projection While Group is active, debugger state must expose at least: - Group, scenario, and candidate identity; - start/current record indices and CTE timestamps; - inspected and collected counts; - latest collection-condition outcome; - latest completion-condition outcome; - safety-limit utilization; - collected-record summaries according to evidence configuration. After Group terminates, debugger/report projections must expose: - completed, succeeded, failed, or incomplete status; - lifecycle metrics; - derived-binding evaluation status; - every assertion outcome and diagnostic; - published result when successful; - configured provenance; - all repeat iteration results where applicable. Debugger stepping must distinguish: 1. record inspected; 2. record collected or rejected; 3. Group completed; 4. derivation/assertion/result evaluation. The Workbench must not independently recompute conditions, transformations, assertions, or results. It projects compiler and engine truth. ## 30. Backward compatibility This is an additive extension. - Existing programs without Group remain unchanged. - Existing Event waiting semantics remain unchanged. - Existing Transition retry semantics remain unchanged. - Existing collector semantics remain unchanged. - Existing CTE record-ordering invariants remain unchanged. - Existing candidate isolation and structured-control semantics remain unchanged. The new expression types and operators must not introduce broad implicit conversion into existing programs. ## 31. Explicit non-goals This design does not introduce: - derived-record insertion into the canonical stream; - retroactive cursor movement; - effective-time reordering of already consumed records; - internal mini-logs; - nested program counters; - Group retry; - Event retry; - dynamic keyed concurrent Group instances; - arbitrary user functions; - host-language execution; - mutable variables; - general loops; - general reducers; - implicit temporal inference; - clock-drift correction; - clock-reset/wrap handling; - new multi-log source-selection syntax. ## 32. Multi-source review outcome Group can calculate CTE values and compare results from records already observed within the normal execution model. It cannot retroactively place a reconstructed event into the canonical stream. The completed multi-source review is recorded in: ```text ../architecture/LOGLINE_MULTI_SOURCE_EXECUTION_AND_PROJECTION_DESIGN.md ``` The review resolved that: - existing `source`, `channel`, and `record.*` fields provide source qualification without a new source-selection clause; - Event and Transition require a common matched-observation interface for cross-source references; - `time.reference(...)` and `time.anchor(...)` provide explicit access to preflight-resolved temporal mappings and anchors; - Parallel and Group provide concurrent observation and bounded cross-source retention; - a derived effective timestamp never re-enters or rewinds the canonical stream; - programs requiring correlation with earlier evidence must retain that evidence explicitly; - independent normalized source cursors continue to feed one deterministic CTE-merged stream into the engine; - no additional semantic program counter or multi-log segment is introduced. These conclusions align with and amend this locked design without changing the Group lifecycle or cursor rules. ## 33. Required documentation alignment after lock Following this lock and before implementation, coordinated updates are required to: - the general Logline language-extension design; - the collector design, to state that the common operators are general while collector-specific scope restrictions remain; - the CTE model, to distinguish canonical record ordering timestamps from temporal values embedded in record payloads; - Workbench architecture and testing documents; - the language design-document index; - the runtime record-reconstruction problem definition, only where it still suggests re-emitting logical records into the canonical stream. The problem definition should remain a problem document rather than becoming a duplicate solution specification. ## 34. Implementation sequence after design lock The agreed sequence is: 1. Complete and lock this Group/expression design. 2. Add it to the canonical language design-document index. 3. Complete and lock the multi-source execution and projection companion design. 4. Implement grammar, AST, validation, typing, operator contracts, and lowering in the language package. 5. Complete language-package tests and keep the language baseline green. 6. Implement shared typed runtime values and operator execution through the central dependency boundary. 7. Implement Group execution in the engine. 8. Add engine semantic, determinism, temporal, resource, and evidence tests. 9. Implement debugger, report, text-editor diagnostics, and Workbench projections. 10. Perform end-to-end validation using both generic fixtures and the motivating multi-record/multi-log case. No engine or debugger implementation should begin before the language design set is complete. The Group/expression and multi-source design baselines now satisfy that prerequisite; implementation must still begin with the language package. ## 35. Locked grammar decisions and deferred contract naming The following grammar decisions are locked: - Group properties may be authored in any order; duplicates are rejected and the formatter emits the canonical order defined in Section 5; - `result` is mandatory, including for validation-only Groups; - assertions are named blocks with a mandatory Boolean `condition` and an optional literal `message`; - collection operators use the restricted `each { ... }` binder form; - public operator names use camelCase; - ambiguous keyed or ordered selection fails by default, with explicit policies such as `keepFirst`, `keepLast`, `first`, `last`, and `all` only where the operator contract permits them; - optional values expose `.present`, guarded `.value`, and `.orElse(...)`; this design does not introduce general-purpose `null`; - temporal operations use the `time` namespace and explicit typed descriptors, including `time.toCte(value, as = ..., anchor = ..., temporalReference = ...)`; - Group lifecycle attributes use the flat `group.` form defined in Section 7. The exact Run Profile JSON field names for safety limits are deferred to the Run Profile contract. Private intermediate-representation identifiers are implementation details. Public report field names are deferred to the report-contract revision. These naming tasks must preserve the locked semantics and do not reopen this language design. ## 36. Lock statement This document is locked as the Group and expression-extension design baseline on 20 September 2026. The lock covers: - Group lifecycle, cursor behavior, completion, failure, and structured-control interaction; - collection, immutable derivation, assertion, and result semantics; - expression typing, collection operators, optional values, determinism, and ambiguity handling; - exact temporal payload interpretation and conversion to CTE; - compiler, engine, evidence, diagnostic, debugger, report, and Workbench obligations; - implementation ordering and compatibility constraints. The multi-source language review was completed after the original lock and produced Alignment Amendment 1. The amendment defines explicit temporal-reference lookup and records the companion design without changing Group lifecycle semantics. This lock defines required language behavior. It does not claim that the behavior has already been implemented. --- ## 37. Implementation Alignment — 24 September 2026 The lock statement in Section 36 records the state at design lock and intentionally remains historical. The Group/expression implementation and its temporal/multi-source companion path have since advanced substantially. This section captures that implemented state without rewriting the locked design chronology. ### 37.1 Group/expression implementation status The language grammar, semantic invocation contracts, validation, compiler lowering, portable IR, Engine runtime, evidence/provenance plumbing, and tests now implement the Group/expression foundation described by this document. The implementation preserves the locked architectural rules: - Group observes the existing canonical stream and never emits/reorders canonical records; - derived values and results are immutable expression data; - completion freezes the captured collection before derivation/assertion/result evaluation; - ordinary sequential cursor semantics remain authoritative; - Parallel is the explicit mechanism when multiple execution branches must observe the same records; - temporal derivation never rewinds or retroactively inserts records. ### 37.2 Temporal operators are general expression operators The `time` namespace described by Sections 19-22 is implemented as part of the general expression library, not as Group-private syntax. Implemented temporal contracts include exact duration construction, explicit temporal interpretation, absolute parsing/construction, arithmetic/comparison/precision operators, and the source-aware operators: ```text time.reference time.anchor time.toCte ``` Their current meanings are: ```text time.reference(source, id) -> named temporal-reference identity time.anchor(source, id) -> preflight-resolved CTE timestamp time.toCte(...) -> explicit conversion of a selected payload/source value to CTE using the authored interpretation and, where required, the same preflight-resolved temporal binding environment ``` A missing named reference/anchor never falls back to the source's canonical clock. ### 37.3 Automatic canonical normalization remains outside Group The multi-source implementation preserves the core distinction anticipated by Sections 19-21: ```text canonical record timestamp normalized automatically to CTE before Engine execution payload temporal value unchanged source data until explicitly interpreted by the program ``` Group may collect records from multiple sources after deterministic composition and may derive CTE values from their payloads. It does not participate in source normalization, source ordering, source-cursor merge, or run-CTE selection. ### 37.4 Shared runtime temporal bindings Engine now receives immutable temporal runtime services from the host. The same `@logline/temporal` binding environment used for canonical source normalization is available to expression evaluation. Group expression evaluation receives those bindings for: ```text collectionCondition completionCondition derived bindings assertions result expressions nested binder expressions ``` This keeps Group payload-time conversion aligned with the run's trusted preflight model instead of duplicating importer or synchronization logic. ### 37.5 Compiler temporal-use discovery includes Group Compiler temporal analysis traverses Group expressions and nested expression trees. `time.reference(...)` and `time.anchor(...)` calls retain source spans and are classified as compiler-static only when both identity operands can be resolved from literals/string constants; otherwise the identity remains runtime-dependent. This analysis remains outside canonical ProgramIR. Enterprise persists trusted compiler-produced Program Bundle analysis separately and uses compiler-static identities for admission-time temporal binding preflight. Runtime-dependent temporal identities remain deterministic Engine lookups if the execution path is reached. ### 37.6 Multi-source execution outcome The headless multi-source design referenced by Section 32 is now implemented for the verified Enterprise BLF path: - each source is normalized independently to exact CTE; - source ordering is resolved and frozen before execution; - normalized cursors are lazily merged with one buffered head per source; - final canonical ordering is exact CTE timestamp, then frozen source order, then source-local cursor order; - final `record.index` is assigned after composition; - Engine and Group continue to see one canonical sequential stream. A real Enterprise integration test verifies cross-source execution together with named temporal reference/anchor resolution and `time.toCte(...)` payload conversion. ### 37.7 Workbench boundary remains The language/compiler/Engine implementation does not by itself complete the Workbench requirements of this design family. Multi-source import/configuration, temporal declarations and preflight visualization, merged preview, source-aware navigation, and complete author/debug/deploy continuity remain product integration work. That remaining UX work must consume the same compiler, preflight, composition, and Engine truth. It must not create a Workbench-specific temporal or multi-source semantic model. # FILE: source-notes/LOGLINE_LANGUAGE_EXTENSION_DESIGN.md # LOGLINE_LANGUAGE_EXTENSION_DESIGN.md ## Document Metadata Version: v0.3-draft\ Date: 2026-06-05\ Session: Logline Language Extension Session 1\ Status: Lock-ready language-extension baseline; not yet implemented\ Authority: Working design document for upcoming Logline language/compiler/engine extension\ Current alignment: The v0.3 metadata above records the original June baseline. Current implementation alignment through 24 September 2026 is recorded in Section 26. Scope: Expression/type comparison extension, array/list literals, collector integration notes, canonical record extension, multi-signal record semantics, and Event v1 segment design\ --- ## Version History ### v0.3-draft — 2026-06-05 Clarified canonical record semantics before language implementation. Captured: - `signal` is the direct normalized field for the observed signal name in a single signal-transition-style record - `from`, `to`, and `type` belong to the same direct signal-transition record shape - `type` is usually derived/normalized rather than necessarily imported literally - `signals.*` is a separate optional namespace for multi-signal snapshot records, such as decoded CAN/LIN/MDF/measurement rows - snapshot-style `signals.*` enables event and collector expressions over multi-channel signal logs - transitions continue to use the single-signal `signal`/`from`/`to` model unless snapshot-transition semantics are explicitly designed later - importer-derived transitions and future snapshot-transition semantics are explicitly deferred Implementation status: - not implemented - grammar not updated - compiler not updated - validator not updated - engine not updated - Workbench/report/debugger not updated --- ### v0.2-draft — 2026-06-05 Extended draft with Event v1 language design and canonical record execution model. Captured: - canonical records are not exclusively transition records or event records - transition and event are sibling leaf matchers over the same current canonical record - event keyword and condition-only Event v1 syntax - Event v1 execution behavior, waiting semantics, and no retry - event placement in scenario/structured constructs - event use in attemptedBy and importance semantics - event evidence, diagnostics, debugger, trace, report, and Workbench projection expectations - canonical record position fields: `record.index` and `record.sourceLine` - repeat iterator/index access explicitly deferred Implementation status: - not implemented - grammar not updated - compiler not updated - validator not updated - engine not updated - Workbench/report/debugger not updated --- ### v0.1-draft — 2026-06-05 Initial language-extension draft. Captured: - controlled type compatibility and comparison semantics - strict equality operators - no broad implicit casting - array/list literal direction - membership operator direction - regex/text operator direction - missing-field predicate behavior - collector integration dependencies - implementation ordering discipline Pending before lock: - event segment language section - final grammar impact review - final compiler/validator implementation plan --- ## 1. Purpose This document captures the first major Logline language-extension design baseline. The current extension track introduces language and runtime capabilities that are larger than a normal feature slice. These changes affect: ```text Langium grammar expression model compiler lowering validator diagnostics canonical IR / practical ProgramIR execution-plan construction engine expression runtime debugger snapshots Workbench projections reports ``` This document is not yet locked. It must be completed with the event-segment section before implementation begins. --- ## 2. Implementation Ordering Rule The implementation order for this language-extension track is locked as follows: ```text 1. Complete and lock language-extension design document. 2. Add event-segment design section. 3. Update Langium grammar. 4. Regenerate Langium artifacts. 5. Rebuild language package/workspace. 6. Implement compiler changes. 7. Implement validator changes. 8. Only then move to engine/runtime implementation. ``` The engine must not be modified first. The compiler and validator must establish a clean semantic boundary before runtime support is added. --- ## 3. Grammar Workflow Reminder After any grammar change: ```text 1. Regenerate Langium artifacts. 2. Rebuild the language package/workspace. 3. Restart the app dev server. 4. Hard-refresh the browser. 5. Sanity-check the editor. ``` Regeneration alone is not enough. --- ## 4. Current Grammar Gap Notes The current uploaded `logline.langium` does not yet contain all syntax needed for this language-extension track. Known required additions include: ```text array/list literals membership operators strict equality operators text/pattern operators regex literals / regex flags collector declarations event declarations extended record field access ``` Current expression grammar already supports basic expressions, literals, current-record fields, transition field references, and constants. The extension must add new expression features deliberately rather than patching around current grammar limitations. --- ## 5. Type and Comparison Semantics ### 5.1 General Rule Logline does not perform broad implicit casting. Allowed implicit compatibility is narrow and intentional. The first compatibility rule is: ```text int and float are compatible numeric values ``` No broad coercion is allowed between: ```text string and number string and boolean boolean and number timestamp and string object/array and scalar ``` Incompatible comparisons produce deterministic diagnostics. They do not silently evaluate false. --- ## 6. Equality Operators Logline supports two equality families. ### 6.1 Compatible Semantic Equality ```logline == != ``` These operators use controlled compatibility. Numeric example: ```text 5 == 5.0 true ``` This is valid because `int` and `float` are compatible numeric types. Invalid examples: ```logline fields.code == 5 isReady == 1 isReady == "true" timestamp == "2026-01-01T00:00:00Z" ``` These are invalid unless the compared runtime values are compatible under Logline rules. ### 6.2 Strict Equality Logline adds: ```logline === !== ``` Strict equality requires: ```text same runtime type same value ``` Expected semantic direction: ```text 5 == 5.0 true 5 === 5.0 false, if int and float are preserved as distinct runtime numeric types ``` Implementation note: Strict `int` versus `float` behavior requires preserving numeric type tags in the runtime value model. If runtime values collapse all numbers into a single JavaScript `number`, the runtime cannot distinguish strict numeric subtypes without additional tagging. --- ## 7. Ordered Comparisons Supported ordered operators remain: ```logline < <= > >= ``` Logline will not add strict variants of ordered comparison operators. Ordered comparisons work only on compatible ordered types. ### 7.1 Numeric Ordering Valid: ```logline value > 10 value <= 10.5 ``` `int` and `float` are compatible for ordered numeric comparison. ### 7.2 String Ordering String ordering is invalid in the first version. Allowed: ```logline name == "READY" name != "SLEEP" name === "READY" name !== "SLEEP" ``` Invalid: ```logline name < "READY" name <= "READY" name > "READY" name >= "READY" ``` Reason: Lexicographic ordering should not be introduced accidentally. It can be added later only if a clear Logline use case exists. ### 7.3 Boolean Ordering Boolean ordering is invalid. Allowed: ```logline isReady == true isReady != false isReady === true isReady !== false ``` Invalid: ```logline isReady > false isReady <= true ``` ### 7.4 Timestamp Ordering Timestamp comparisons are allowed only when both sides are normalized timestamp values. Valid: ```logline timestamp >= START_TIME ``` where both sides are timestamp-typed values. Invalid for now: ```logline timestamp >= "2026-01-01T00:00:00Z" ``` Reason: No implicit timestamp/string comparison. Explicit timestamp parsing or conversion may be introduced later. --- ## 8. Missing Field Predicate Behavior Missing fields are not treated the same as incompatible types. If a referenced field is missing, the affected predicate evaluates false and no type diagnostic is emitted. Example: ```logline fields.latency_ms > 500 ``` If `fields.latency_ms` is missing: ```text predicate evaluates false no type diagnostic ``` This rule applies to: ```text direct normalized fields fields.* signals.* ``` This rule is especially important for mixed logs where not every record has the same shape. --- ## 9. Null Logline does not introduce a `null` literal in the first type/comparison extension. Reason: ```text missing-field semantics already cover absent record fields collector results use status and hasValue adding null now creates unnecessary ambiguity ``` A null-like value can be revisited later if there is a clear semantic need. --- ## 10. Object and Array Equality Object and array equality are invalid in the first version. Invalid: ```logline fields.payload == { code: "E42" } fields.items == [1, 2, 3] fields.items === [1, 2, 3] ``` Reason: Structural equality must be designed intentionally. It must not be introduced accidentally through JavaScript-like behavior. Strict identity/reference semantics may also be considered later, but not in the first version. --- ## 11. Array/List Literals Array/list literals are required for the extended expression language. Initial use cases: ```logline level in ["WARN", "ERROR"] ``` and: ```logline const BAD_LEVELS = ["ERROR", "FATAL"]; condition =: level in BAD_LEVELS; ``` Arrays may exist as expression values and constants, especially for membership checks. Array structural equality remains invalid/deferred. ### 11.1 Homogeneous Arrays Mixed-type arrays are invalid in the first version. Invalid: ```logline level in ["ERROR", 5, true] ``` Arrays should be homogeneous so membership checks remain predictable and type-checkable. ### 11.2 Array Scope Array/list literals are initially intended for: ```text membership checks constants bounded expression values where supported ``` They are not intended to introduce general-purpose collection programming event retry event captures/extraction bindings event window/distance constraints multi-log/source selection schema hints repeat iterator/index access in the first version. --- ## 12. Membership Operators Logline adds membership operators: ```logline in not in ``` Examples: ```logline level in ["WARN", "ERROR"] level not in ["DEBUG", "TRACE"] ``` Membership is a general expression feature, not collector-specific. The right-hand side should be an array/list expression or a constant resolving to an array/list expression. Membership over mixed-type arrays is invalid. Membership comparison uses Logline compatible equality rules, not broad implicit casting. Example: ```logline 5 in [5.0] ``` is valid under numeric compatibility. Example: ```logline "5" in [5] ``` is invalid due to string/number mismatch. --- ## 13. Text and Pattern Operators Text and pattern operators are general Logline expression features. They are not collector-specific. Supported direction: ```logline contains startsWith endsWith matches ``` Examples: ```logline message contains "timeout" message startsWith "ERROR" message endsWith "failed" message matches /timeout after \d+ ms/ ``` Text operators use camelCase where needed. Preferred: ```logline message startsWith "ERROR" message endsWith "timeout" ``` Not preferred: ```logline message startswith "ERROR" message starts_with "ERROR" ``` If a text operator is used on a missing field, the predicate evaluates false. If a text operator is used on a non-text value at runtime, this is a deterministic type diagnostic in the relevant expression context. --- ## 14. Regex Literals Regex used by `matches` follows ECMAScript/JavaScript regex semantics. Regex matching is case-sensitive by default. ```logline message matches /timeout/ ``` For case-insensitive matching: ```logline message matches /timeout/i ``` Allowed ECMAScript flags in the first version: ```text i m s u ``` Unsupported flags are rejected: ```text g y d ``` Invalid regex literals are compile/validation errors. Regex capture groups are allowed for matching, including named groups, but capture binding/reference semantics are deferred. Allowed: ```logline message matches /request (?\w+) started/ ``` Deferred: ```text referencing id in later expressions exposing regex captures as event or collector bindings ``` --- ## 15. Current Record Expression Model The existing canonical log record model remains the foundation and will be extended rather than replaced. Current signal-oriented canonical record shape: ```ts type CanonicalRecord = { t: number | string; signal: string; from: unknown; to: unknown; sourceLine?: number; }; ``` The extension should evolve this into a superset that can support signal records, free-text records, semi-structured fields, and raw evidence. Conceptual direction: ```ts type CanonicalRecord = { index: number; t?: number | string; signal?: string; from?: unknown; to?: unknown; type?: string; message?: string; level?: string; source?: string; fields?: Record; signals?: Record; raw?: unknown; sourceLine?: number; }; ``` Expression context exposes both direct normalized aliases and namespaced/extensible fields. Direct normalized aliases: ```text t timestamp message level source signal from to type ``` `t` remains the canonical timestamp field for compatibility. `timestamp` is a normalized expression alias for the same value. Namespaced/extensible fields: ```text fields.* signals.* record record.index record.sourceLine ``` Examples: ```logline condition =: level == "ERROR"; condition =: message contains "timeout"; condition =: fields.service == "gateway"; condition =: signals.vehicle_state == "WAKE"; value =: record; ``` `record` is a reserved expression name for the full extended canonical Logline record object. `record.index` is the canonical normalized stream index used by the engine. `record.sourceLine` is the original source line/index from the imported source, when available. The original unprocessed input payload or raw line, when available, is accessed through: ```logline record.raw ``` No direct `raw` alias is introduced for now. If an imported record has a generic field with the same name as a direct normalized alias, the direct name refers to the normalized field and the generic field is accessed through `fields`. Example: ```text level normalized level fields.level imported/generic field named level ``` --- ## 16. Collector Integration Note Collectors use the general expression language defined in this document. Collector-specific rules are defined in: ```text LOGLINE_COLLECTOR_DESIGN.md ``` Important alignment points: ```text collector conditions use general boolean expressions collector value expressions use general value expressions collector count expressions use constants/literals missing-field predicate behavior applies to collector conditions text/regex/membership operators are general expression features collector results are not referenced by segment conditions in collector v1 ``` Collector declarations are part of the broader language-extension track, but the collector design document remains the detailed collector authority. --- ## 17. Event Segment Design — Event v1 ### 17.1 Purpose `event` is a new first-class executable leaf segment for matching one canonical log record using the general Logline expression language. Event v1 extends Logline beyond signal-transition-only scenarios without weakening or overloading `transition`. The language-level distinction is: ```text transition signal/value-change matcher event generic record/message/field matcher ``` At the runtime architecture level, both are leaf matchers over the same current canonical record. --- ### 17.2 Event and Transition Execution Model A canonical record is not exclusively a transition record or an event record. The engine must not classify each record first as either signal/transition or event/text and then choose a separate execution path. Instead: ```text For each current canonical record: the active transition leaf decides whether the record matches transition semantics the active event leaf decides whether the record matches event semantics collectors evaluate their own record predicates ``` Transition and event are sibling leaf matchers over the same record stream. A transition is a signal-oriented leaf matcher. A non-signal record normally produces no match, not a diagnostic. An event is a generic record/message/field-oriented leaf matcher. It may evaluate against any canonical record. Missing fields in predicates normally produce no match, not a diagnostic. This preserves the record-driven execution model and avoids introducing a separate event-only runtime loop. --- ### 17.3 Event Keyword The new generic record-matching leaf segment keyword is: ```logline event ``` Preferred syntax: ```logline event LowVoltageWarning { condition =: message contains "low voltage"; } ``` Rejected alternatives for v1: ```text record log message pattern ``` Reason: ```text event describes the semantic thing being detected, not the raw storage format ``` --- ### 17.4 Event v1 Shape Event v1 has one required semantic property: ```logline condition =: ; ``` Example: ```logline event LowVoltageWarning { condition =: message contains "low voltage" && source == "BMS"; } ``` Rules: ```text condition is mandatory condition must evaluate to boolean condition uses the general Logline expression language no event-specific predicate statement syntax is introduced in Event v1 no additional required event properties are introduced in Event v1 ``` Invalid: ```logline event SomethingHappened { } ``` Reason: ```text An event has no signal/type-specific implicit match fields. Its whole Event v1 match meaning comes from its condition. ``` Transition contrast: ```text transition has implicit match requirements: - signal must match declared signal - record must be signal-transition-shaped enough - type/value compatibility must hold - condition then further constrains the match event has no signal/type-specific implicit match requirements: - condition is the complete semantic match rule ``` --- ### 17.5 Event Condition Model Event conditions use the same expression language as transition conditions, collector conditions, and crossroads conditions. No event-specific predicate language is introduced. Preferred: ```logline event GatewayTimeout { condition =: fields.service == "gateway" && message contains "timeout" && fields.latency_ms > 500; } ``` Not preferred: ```logline event GatewayTimeout { fields.service == "gateway"; message contains "timeout"; fields.latency_ms > 500; } ``` Text and regex matching are expression operators, not event properties and not namespaced function calls. Preferred declarative expression style: ```logline message contains "timeout" message startsWith "ERROR" message endsWith "failed" message matches /timeout after \d+ ms/ ``` Not introduced in v1: ```logline Text.startsWith(message, "ERROR") String.endsWith(message, "failed") message.startsWith("ERROR") ``` Operator words such as `contains`, `startsWith`, `endsWith`, and `matches` should be reserved only in operator position to minimize reserved-word pollution and ambiguity. --- ### 17.6 Event Waiting and Retry Semantics Event v1 does not support `retry`. Reason: ```text An event non-match means “keep waiting for a future matching record,” not “consume retry.” ``` An event remains pending until either: ```text its condition evaluates true on a future record the candidate is finalized at end of input ``` False condition means normal non-match. Missing fields causing false predicates mean normal non-match. Window/distance constraints are explicitly deferred. Future features may include: ```text within records N within duration T immediately after ``` These should be designed as explicit temporal/window constraints, not by overloading `retry`. --- ### 17.7 Event Placement `event` is allowed anywhere a `transition` segment is allowed. That includes: ```text top-level scenario sequence inside repeat inside parallel branches inside crossroads cases future mixed leaf presentation/grouping surfaces if supported by Workbench ``` Event is a normal executable leaf segment, sibling to transition. --- ### 17.8 Event Names and Attempt Evidence Event segment names may be referenced in `attemptedBy`, alongside Transition and Group executable segments. Example: ```logline scenario WakeThenWarning attemptedBy [Wake, LowVoltageWarning] { transition Wake { signal =: "vehicle_state"; type =: string; condition =: to == "WAKE"; } event LowVoltageWarning { condition =: message contains "low voltage"; } } ``` Reason: ```text Events can provide scenario-attempt evidence the same way transitions can. ``` --- ### 17.9 Event Importance Events support the same `importance` property as transitions. Example: ```logline event LowVoltageWarning { condition =: message contains "low voltage"; importance =: essential; } ``` Reason: ```text Events can participate in attempt/fallback semantics, so they need the same importance model. ``` Property ordering is flexible. Both are valid: ```logline event LowVoltageWarning { condition =: message contains "low voltage"; importance =: essential; } ``` ```logline event LowVoltageWarning { importance =: essential; condition =: message contains "low voltage"; } ``` Formatter/docs should prefer: ```text condition importance ``` --- ### 17.10 Event Diagnostics Event v1 diagnostics include at least: ```text missing mandatory condition duplicate event properties unsupported event properties condition is statically non-boolean runtime condition evaluates non-boolean runtime text/regex/type mismatch invalid regex literal unsupported regex flag ``` Unsupported event properties are validation errors and must not be ignored. Invalid example: ```logline event LowVoltageWarning { condition =: message contains "low voltage"; retry =: until; } ``` Duplicate event properties are validation errors. Invalid example: ```logline event ErrorSeen { condition =: level == "ERROR"; condition =: message contains "error"; } ``` If an event condition produces a runtime type error for a specific record: ```text emit a deterministic diagnostic the event does not match that record the candidate remains alive and may match on a future record ``` The runtime type error is not automatically fatal to the candidate. --- ### 17.11 Event Name Uniqueness Event names follow the same scenario-local uniqueness rule as other named constructs. Inside one scenario, an event name may not conflict with: ```text transition names event names collector names repeat names parallel names crossroads names other named executable constructs ``` Reason: ```text avoid ambiguity in references, diagnostics, reports, debugger snapshots, and future dot notation ``` --- ### 17.12 Events in Structured Constructs Event segments behave like transitions when placed inside structured constructs. Inside: ```text repeat parallel crossroads ``` an event is just a leaf segment evaluated by the existing structured execution model. No event-specific structured execution rules are introduced in Event v1. If a candidate is pending at an event when input ends, it finalizes the same way as a candidate pending at an unmatched transition. Event v1 does not introduce a special finalization category. --- ### 17.13 Event Evidence When an event matches, runtime evidence includes at least: ```text event name/id matched record.index matched record.t / timestamp if available matched record.sourceLine if available condition evaluation result record/message summary for reports/debugger ``` Events should not require a separate evidence syntax in the DSL. Evidence projection is runtime/debugger/report behavior, not semantic source syntax. --- ### 17.14 Event Trace Rich trace mode should emit event-related trace events. Examples: ```text event evaluated event matched event condition diagnostic ``` Event misses should be optional, summarized, or disabled by default to avoid excessive trace volume. --- ### 17.15 Event Report Representation Reports should show event evidence differently from transition evidence. Event report evidence should focus on: ```text matched record index timestamp if available sourceLine if available message excerpt / record summary condition that matched diagnostics if any ``` Reporting labels, display formatting, and presentation choices are not part of Event v1 semantic syntax. --- ### 17.16 Event Debugger Projection Debugger snapshots should expose event state through the same general candidate/segment projection model used for transitions. Event-specific debugger evidence should include: ```text event name/id active/pending/passed state as applicable matched record.index when passed timestamp if available sourceLine if available message/record summary condition diagnostics if any ``` --- ### 17.17 Event Compiler and IR Shape Events compile into their own explicit IR / Execution Plan leaf kind. They must not be lowered into synthetic transitions. Reason: ```text transition and event may share leaf-evaluator infrastructure, but IR must preserve event identity for diagnostics, reports, debugger snapshots, Workbench projections, and future event-specific extensions ``` Possible conceptual plan shape: ```ts type LeafSegmentPlan = | TransitionLeafPlan | EventLeafPlan; ``` or equivalent production representation. --- ### 17.18 Event Workbench Representation Workbench must represent Event v1 as a distinct segment type with its own icon and visual identity. Reason: ```text Even though transition and event are sibling leaf matchers internally, the user-facing model must distinguish: transition signal/value-change matcher event generic record/message/field matcher ``` Program tab, Inspector, Visual Editor, Timeline, Report, and Debugger projections should preserve this distinction. --- ### 17.19 Current Visual Grouping Note There is no Event v1 decision needed for transition/event groups in the Logline language. Current “transition groups” are Visual Editor / Workbench projection or presentation behavior, not a Logline DSL segment construct. Event v1 only needs to be allowed wherever normal executable segments are allowed: ```text scenario body repeat body parallel branch crossroads case ``` --- ### 17.20 Event v1 Explicit Deferrals Deferred from Event v1: ```text retry captures / extraction bindings regex capture references within records N within duration T immediately-after constraints multi-log/source selection schema hints event-specific predicate statement syntax event-specific evidence projection syntax event-specific report labels or descriptions in DSL event-specific structured execution rules repeat iterator/index access ``` These are deferred deliberately, not omitted accidentally. --- ### 17.21 Record Context Additions for Events and Collectors The extended canonical record model must expose record position information. Required fields: ```text record.index canonical normalized stream index used by the engine record.sourceLine original source line/index from the imported source, when available ``` Reason: ```text record.index and record.sourceLine are not necessarily the same. Importers may skip headers, filter malformed records, merge records, or import structured files where source line is not meaningful. ``` Design rule: ```text Use record.index for deterministic engine/order semantics. Use record.sourceLine for user-facing evidence/debug/report traceability. ``` Repeat iterator/index access is not currently present in the uploaded grammar and is deferred to a separate future design decision. Reason: ```text repeat index semantics are non-trivial under nested repeat, parallel branches, same-record stabilization, and future event/correlation patterns ``` --- ## 18. Compiler and Validator Expectations Compiler and validator work must happen before engine runtime implementation. The compiler must: ```text parse and lower new expression forms normalize strict/compatible comparison operators normalize array/list literals normalize membership expressions normalize regex literals and flags lower event declarations into explicit event IR / execution-plan leaf structures preserve event identity and source spans/provenance preserve enough type information for runtime diagnostics preserve source spans/provenance ``` The validator must: ```text reject invalid regex literals reject unsupported regex flags reject unknown operators reject statically obvious type errors reject mixed-type arrays where statically visible reject array/object equality in the first version reject invalid strict-equality syntax if malformed diagnose unsupported or ambiguous record field access reject invalid event declarations, including missing condition, duplicate properties, unsupported properties, and non-boolean conditions where statically obvious ``` Record-dependent type failures remain deterministic runtime diagnostics. --- ## 19. Engine Expectations Engine implementation must not start until language/compiler/validator changes are ready. The engine expression runtime must eventually support: ```text controlled numeric compatibility strict equality membership checks array/list literal values text operators ECMAScript regex matching missing-field predicate behavior extended canonical record access event leaf evaluation over the current canonical record event evidence projection ``` Engine implementation must preserve: ```text deterministic runtime behavior no broad implicit casting no JavaScript-style loose equality no hidden semantic fallback no mutation of language semantics through EngineConfig ``` --- ## 20. Explicit Deferrals Deferred from the first expression/type extension: ```text object literals unless already cleanly supported custom object projections array/object structural equality string ordering null literal broad implicit casting timestamp parsing from strings regex capture bindings native JavaScript expressions host-language functions general-purpose collection programming event retry event captures/extraction bindings event window/distance constraints multi-log/source selection schema hints repeat iterator/index access ``` --- ## 21. Locking Condition This document may be locked only after: ```text event segment section is reviewed and accepted collector design reference is aligned canonical record extension is reviewed grammar impact is reviewed implementation order is confirmed ``` No implementation has been performed from this document yet. After lock, the next implementation phase is: ```text Langium grammar update Langium artifact generation language package rebuild compiler implementation validator implementation then engine implementation ``` --- ## 22. Canonical Record Clarification — `signal` vs `signals.*` This section clarifies the canonical record model before implementation. It supersedes any ambiguous wording above but does not remove historical content. The existing canonical log record model remains the foundation and is extended rather than replaced. Current signal-oriented canonical record shape: ```ts type CanonicalRecord = { t: number | string; signal: string; from: unknown; to: unknown; sourceLine?: number; }; ``` The language extension evolves this into a superset that can support: ```text single signal-transition records free-text/event records semi-structured field records multi-signal snapshot records raw evidence/debug traceability ``` Conceptual extended direction: ```ts type CanonicalRecord = { index: number; t?: number | string; sourceLine?: number; // Single observed signal-transition record shape. signal?: string; from?: unknown; to?: unknown; type?: string; // Generic event/log shape. message?: string; level?: string; source?: string; // Generic semi-structured payload. fields?: Record; // Optional multi-signal snapshot shape. signals?: Record; // Original source payload/line/object when available. raw?: unknown; }; ``` This is a conceptual design contract. Exact TypeScript naming and package location can be finalized during implementation. ### 22.1 Direct Signal-Transition Fields The direct normalized fields below describe a **single observed signal-transition-style record**: ```text signal the name of the observed signal represented by this record from the previous value for that observed signal, when available to the new/current value for that observed signal, when available type the derived/normalized value type for the observed signal value, when known ``` Example: ```ts { index: 17, t: "2026-01-01T00:00:00.500Z", signal: "vehicle_state", from: "SLEEP", to: "WAKE", type: "string" } ``` A transition continues to target this shape: ```logline transition Wake { signal =: "vehicle_state"; type =: string; condition =: to == "WAKE"; } ``` Important clarification: ```text signal is a direct field whose value is the signal name signals.* is a separate namespace for multi-signal snapshot values ``` These two are not interchangeable. ### 22.2 `type` Is Normally Derived `type` is a direct normalized field, but in many imported logs it is not literally present in the source record. It may be derived by the importer, schema inference, declared signal catalogue, DBC/LDF metadata, parser configuration, or value normalization. Design rule: ```text type represents the normalized value kind available to Logline semantics, not necessarily a raw field imported from the log line. ``` This keeps transition type checking deterministic without requiring every external log format to contain a literal `type` field. ### 22.3 Multi-Signal Snapshot Namespace: `signals.*` `signals.*` is an optional namespace for records that carry multiple signal values at the same timestamp or sample point. Example: ```ts { index: 42, t: "2026-01-01T00:00:00.500Z", signals: { vehicle_state: "WAKE", vehicle_speed: 12.4, battery_voltage: 11.8, ignition_status: true } } ``` This supports multi-channel logs such as: ```text decoded CAN signal rows decoded LIN signal rows MDF/measurement snapshots CSV signal tables sampled telemetry frames other multi-channel signal records ``` Events and collectors can reason over multiple channels in one record: ```logline event LowVoltageWhileWake { condition =: signals.vehicle_state == "WAKE" && signals.battery_voltage < 12.0; } ``` ```logline collector MaxSpeedDuringWake { kind =: max; value =: signals.vehicle_speed; condition =: signals.vehicle_state == "WAKE"; } ``` For CAN/LIN-style logs, `signals.*` represents decoded signal values after import/DBC/LDF decoding. Raw frames or original rows may remain available through `record.raw` or `fields.*`. ### 22.4 Transition Semantics and Snapshot Logs For the initial language extension, normal `transition` semantics continue to use the single-signal transition fields: ```text signal from to type ``` Snapshot-style records using `signals.*` are immediately useful for events and collectors, but they do not automatically redefine transition semantics. For snapshot logs, supported/expected approaches are: ```text event-style snapshot predicates use event conditions over signals.* collector-style snapshot aggregation use collector condition/value expressions over signals.* importer-derived transitions importer may convert consecutive snapshots into per-signal from/to transition records future snapshot-transition semantics may later allow transition to target a signal path inside signals.* and derive from/to from previous snapshots ``` Future snapshot-transition semantics are explicitly deferred and must be designed intentionally. ### 22.5 Unified Current-Record Expression Context The direct normalized aliases available wherever a current record is bound are: ```text t timestamp signal from to type message level source ``` Namespaced/extensible access includes: ```text fields.* signals.* record record.index record.sourceLine record.raw ``` Examples: ```logline condition =: level == "ERROR"; condition =: message contains "timeout"; condition =: fields.service == "gateway"; condition =: signals.vehicle_state == "WAKE"; value =: record; ``` Transitions, events, collectors, and future condition-bearing constructs use this same current-record expression context. The difference is the leaf matcher semantics: ```text transition has signal/type applicability gates and then evaluates its condition event has no signal/type-specific gate and matches when its condition is true collector evaluates its condition/value/count according to collector scope and timing ``` ### 22.6 Implementation Note The grammar, compiler, validator, and engine have not been updated yet. When implementation begins, the language update must support: ```text direct normalized signal-transition fields generic fields.* multi-signal snapshot signals.* reserved record access record.index record.sourceLine record.raw ``` The engine/runtime must not confuse `signal` and `signals.*`. The compiler/IR should preserve whether an expression references the direct `signal` field or the `signals.*` namespace. --- ## 23. Language Extension Session 3 — Scenario Candidate Policy Syntax Date: 2026-06-13 This section records the first implementation slice for explicit scenario-level candidate policy syntax. It preserves the earlier clarification that candidate lifecycle/opening semantics are separate from `attemptedBy` and `attemptedWhen`. ### 23.1 Source Syntax Candidate policy is authored inside the scenario body, before scenario collectors and executable segments: ```logline scenario HvStartupHappyPath attemptedBy [VehicleWake] { candidateConcurrency =: singleActive; candidateOpening =: profileMatch; transition VehicleWake { signal =: "vehicle_state"; type =: string; condition =: to == "WAKE"; importance =: essential; } } ``` Supported values: ```text candidateConcurrency =: singleActive | spawnAll candidateOpening =: profileMatch | conditionPass ``` ### 23.2 Defaults Omitted fields preserve current runtime behavior: ```text candidateConcurrency =: singleActive candidateOpening =: profileMatch ``` The compiler lowers these defaults explicitly into Program IR for newly compiled programs. ### 23.3 Semantic Boundary These fields control candidate lifecycle and candidate opening threshold. They do not redefine attempt classification: - `attemptedBy` remains evidence membership / attempt classification metadata. - `attemptedWhen` remains attempt-gate classification policy. - `candidateConcurrency` controls whether same-scenario overlapping candidates may be opened. - `candidateOpening` controls whether the opening profile match alone is enough to open a candidate or whether the opening condition must pass. ### 23.4 Slice Boundary This slice adds language, lowering, IR, execution-plan plumbing, validation, and tests for policy presence/defaulting. Runtime semantic activation of `spawnAll` and `conditionPass` is intentionally handled by the following engine slices so the compatibility default remains provable. --- ## 24. Language Extension Session 3 — Candidate Policy Runtime Lock Date: 2026-06-13 The candidate policy syntax introduced in Section 23 is now implemented through language validation, lowering, IR/execution-plan plumbing, and engine runtime semantics. ### 24.1 Final Source-Level Meaning Candidate policy remains authored inside a scenario body before scenario collectors and executable segments: ```logline scenario HvStartupHappyPath attemptedBy [VehicleWake] { candidateConcurrency =: spawnAll; candidateOpening =: conditionPass; transition VehicleWake { signal =: "vehicle_state"; type =: string; condition =: to == "WAKE"; importance =: essential; } } ``` Supported values are locked as: ```text candidateConcurrency =: singleActive | spawnAll candidateOpening =: profileMatch | conditionPass ``` ### 24.2 Runtime Meaning `candidateConcurrency =: singleActive` is the default and preserves compatibility behavior: a scenario does not open another active same-scenario candidate while one candidate for that scenario is already active. `candidateConcurrency =: spawnAll` allows overlapping/interleaved same-scenario candidates from repeated opening evidence. Candidate identities remain distinct and stable. `candidateOpening =: profileMatch` is the default and preserves compatibility behavior: matching opening evidence can create a candidate even if the opening condition fails, allowing failed-start evidence to be reported/debugged. `candidateOpening =: conditionPass` requires the opening executable condition to pass before candidate creation. If the opening condition fails, no candidate is created for that record occurrence. ### 24.3 Boundary With Attempt Classification The policy fields do not redefine `attemptedBy` or `attemptedWhen`. `attemptedBy` and `attemptedWhen` remain attempt-gate/report-classification semantics. Candidate lifecycle and opening threshold are controlled by `candidateConcurrency` and `candidateOpening`. ### 24.4 Verification Baseline ```text Language package: 4 files / 30 tests passed; build successful Engine package: 42 files / 305 tests passed ``` --- ## 25. Language Extension Session 3 — Workbench/Report Consumer Lock After the `candidateConcurrency` / `candidateOpening` language and engine semantics were locked, the Workbench debug/report surfaces were updated to consume the new candidate-policy behavior correctly. This section does not add new source syntax. It records the locked consumer interpretation of the language feature. ### 25.1 Source feature involved ```logline scenario InterleavedCandidateDemo attemptedBy [Wake] { candidateConcurrency =: spawnAll; candidateOpening =: conditionPass; transition Wake { ... } transition Precharge { ... } transition Ready { ... } } ``` `spawnAll` means multiple same-scenario candidates may overlap. Therefore all user-facing evidence must preserve candidate identity. ### 25.2 Workbench interpretation The Workbench now treats candidate identity as part of debug/replay projection: - C2 appears in the candidate rail as soon as it is spawned; - selecting C2 shows C2's own visual history and pending location; - C1 markers do not leak into C2's visual state; - if C1 and C2 both evaluate the same transition on the same frame, both evaluations remain visible; - if the same candidate evaluation is observed through live and report evidence, it is shown once; - placeholder “Current candidate” evidence is replaced when concrete `Candidate N` identity is known. ### 25.3 Report interpretation A scenario definition may pass once while multiple candidate attempts pass under that scenario. The report should keep these concepts separate: ```text Scenario definitions passed: 1 Candidate attempts passed: 2 ``` This distinction is especially important for `spawnAll` demos, where the same scenario definition can have overlapping passed candidates. ### 25.4 Verification baseline ```text Language package: 4 files / 30 tests passed; build successful Engine package: 42 files / 305 tests passed Workbench package: 36 files / 310 tests passed; build green ``` --- ## 26. Current Implementation Alignment — Expression, Temporal, and Multi-Source Semantics **Alignment date:** 2026-09-24 **Purpose:** Preserve the implemented language/compiler/runtime state without rewriting the historical design baseline above. The early sections of this document intentionally retain their original June 2026 statements that grammar, compiler, validator, Engine, and Workbench work had not yet been implemented. Those statements are historical. The language/compiler/Engine capabilities described below are implemented in the current repository unless this section explicitly marks them as still outstanding. ### 26.1 Implemented language and semantic-contract boundary The current source grammar and semantic-contract layer implement the extended expression foundation required by the later Group and multi-source designs. The implementation is centered on: ```text libs/logline-language/packages/language/src/logline.langium libs/logline-language/packages/language/src/logline-expression-semantics.ts libs/logline-language/packages/language/src/logline-validator.ts ``` The grammar provides the shared expression surface rather than separate expression languages for Event, collectors, Group, or temporal conversion. Invocation contracts define static argument/result typing, missing-value behavior, collection ordering/ambiguity behavior, provenance policy, and runtime diagnostic families. The compiler lowers those contracts into portable expression IR; Engine executes the lowered contracts rather than reparsing source syntax. The generated `out` artifacts under the language package are build products and are not the design authority or committed source of truth. ### 26.2 Canonical record identity after multi-source composition The earlier record model correctly separated execution position from source provenance, but the multi-source implementation has now fixed the precise meaning: ```text record.index global index in the final canonical execution stream consumed by Engine record.sourceLine optional source-facing line/index provenance when meaningful source-local record identity retained separately by runtime/import provenance and not substituted for record.index ``` For multi-source runs, `record.index` is assigned only after source timestamps have been normalized and the source cursors have been deterministically composed. It therefore never means "index within one input file". The current canonical record expression context also preserves source-aware identity such as `source` and optional `channel` without introducing a second source-local execution model. ### 26.3 Canonical timestamp versus payload temporal values The temporal boundary is now implemented and must remain explicit: > Automatic synchronization applies only to the canonical top-level timestamp of each input record before Engine execution. Timestamp-like values carried in `fields.*`, `signals.*`, `record.raw`, or other payload data are not automatically rewritten. A Logline program that needs to interpret such a value temporally must do so explicitly through the `time` expression namespace. This preserves two distinct operations: ```text source canonical timestamp -> preflight-resolved source mapping -> CTE before Engine execution payload/source temporal value -> explicit Logline temporal interpretation -> optional preflight-resolved named reference/anchor -> derived CTE value inside expression evaluation ``` A derived CTE value is expression/result data. It does not alter record order, rewind the canonical cursor, or insert a synthetic record into the execution stream. ### 26.4 Implemented temporal semantic types The language semantic-contract layer now distinguishes temporal values rather than representing all time-related values as generic numbers or text. Relevant implemented semantic types include: ```text cte-timestamp duration temporal-interpretation temporal-reference exact-number integer decimal text ``` The runtime value model preserves exact duration and temporal-reference identity explicitly. CTE timestamps use the Engine timestamp type and retain exact canonical ordering semantics. ### 26.5 Implemented `time` operator surface The current temporal operator registry includes: ```text time.duration time.toCte time.displacement time.epochEncodedDisplacement time.epochTimestamp time.reference time.anchor time.parseTimestamp time.fromEpoch time.add time.subtract time.difference time.absolute time.before time.after time.within time.between time.floor time.ceil time.round ``` All are deterministic language operators with typed invocation contracts. Temporal operators propagate temporal/value provenance and use deterministic runtime diagnostics rather than host-language coercion or heuristic interpretation. The currently implemented interpretation constructors relevant to `time.toCte(...)` are: ```logline time.displacement(unit = ) time.epochEncodedDisplacement( epoch = unix, format = iso8601, unit = ) time.epochTimestamp( epoch = unix, unit = , format = , timezone = ) ``` The current exact-unit vocabulary is: ```text nanoseconds microseconds milliseconds seconds minutes hours days ``` No magnitude-based unit inference is permitted. ### 26.6 `time.reference(...)` and `time.anchor(...)` have different meanings The implemented meanings are now locked as distinct contracts. ```logline time.reference( source = "ecu-b", id = "device-clock" ) ``` returns a **temporal-reference identity**. It identifies a named preflight-resolved source clock/mapping for use by an operator such as `time.toCte(...)`. Creating the identity does not silently substitute the source's canonical clock and does not imply a fallback when the named reference is absent. ```logline time.anchor( source = "ecu-b", id = "boot-start" ) ``` returns the named anchor's **resolved CTE timestamp**. The anchor identity is retained separately in expression provenance. A missing named reference or anchor is never silently redirected to the source's canonical timestamp mapping. ### 26.7 Implemented `time.toCte(...)` behavior The observable high-level form remains: ```logline time.toCte( value, as = , anchor = , temporalReference = ) ``` The implemented conversion families are: 1. **Displacement from a CTE anchor** ```logline time.toCte( fields.offset, as = time.displacement(unit = milliseconds), anchor = record.timestamp ) ``` The displacement must convert exactly to nanoseconds and the anchor must already be a CTE timestamp. 2. **Epoch-encoded displacement from a CTE anchor** An exact ISO-8601 value interpreted as an epoch-encoded displacement is converted and added to an explicit CTE anchor. Missing anchor or invalid/inexact representation fails deterministically. 3. **Named source epoch timestamp mapped to CTE** ```logline time.toCte( fields.deviceTime, as = time.epochTimestamp(epoch = unix, unit = milliseconds), temporalReference = time.reference( source = "ecu-b", id = "device-clock" ) ) ``` The named temporal reference must resolve through the host-supplied preflight bindings and must describe a Unix/POSIX epoch clock compatible with the authored interpretation. Arithmetic convertibility alone is insufficient: semantically incompatible interpretation/binding combinations are rejected. All conversion paths preserve the exactness rule. Inexact conversion, missing mapping, invalid representation, or incompatible temporal semantics produces deterministic diagnostics rather than rounding, averaging, guessed zero, or fallback. ### 26.8 Absolute parsing and named-timezone boundary The Engine currently supports exact ISO-8601 timestamp parsing through `time.parseTimestamp(...)`. Engine-local parsing does not become a general named-timezone database or source-clock synchronizer. Named source clock, timezone, acquisition-origin, and cross-source mapping semantics remain preflight responsibilities. Where a temporal value requires a source-specific mapping to CTE, the program uses the preflight-resolved reference/anchor model rather than reconstructing source normalization inside Engine. ### 26.9 Shared temporal runtime services Engine now has a host-injected immutable runtime-services seam containing optional `TemporalRuntimeBindings` from `@logline/temporal`. The same resolved temporal binding environment used by Enterprise for canonical source timestamp normalization is injected into Engine expression evaluation. It is propagated through ordinary expressions, Groups, collectors, structured execution, Parallel, candidate/precondition evaluation, and debugger sessions. This is execution context, not authored mutable program state. Engine does not resolve source synchronization policy, choose a run CTE, or create missing temporal mappings. ### 26.10 Compiler discovery of temporal binding use sites The compiler now discovers `time.reference(...)` and `time.anchor(...)` use sites from portable Program IR. Discovery covers temporal lookups appearing in: ```text program-level collectors scenario-level collectors transitions events Groups Repeat Parallel Crossroads nested expressions collection binders ``` For each lookup the analysis records: ```text binding kind: reference | anchor source operand: static string when provable, otherwise runtime-dependent id operand: static string when provable, otherwise runtime-dependent source span when available ``` String literals and string-valued constants can therefore become compiler-static identities. Record-derived, binder-derived, derived-expression, or otherwise computed values remain runtime-dependent. The analysis is intentionally **outside canonical ProgramIR**. It can be recomputed from ProgramIR and does not change the portable runtime IR contract or invalidate older hand-authored IR fixtures. ### 26.11 Enterprise trusted analysis and admission policy Enterprise does not trust client-authored temporal-use metadata and does not recompile ad hoc inside run admission. Instead: 1. trusted Program Bundle publication reads the exact immutable program artifact bytes; 2. the real compiler/validation path produces temporal-use analysis; 3. server-owned immutable `ProgramBundleAnalysis` is persisted separately from the client-owned immutable Program Bundle; 4. the analysis is tied to exact bundle/program artifact identities and content digests; 5. run admission consumes that trusted analysis together with the run's resolved temporal bindings. A `time.reference(...)` or `time.anchor(...)` use becomes an admission-time binding dependency only when **both** `source` and `id` are compiler-static. If either operand is runtime-dependent, admission does not guess. Engine lookup remains authoritative if that path executes. A compiler-static binding remains a link-time dependency even when it appears under runtime control flow because the language currently has no optional/maybe-missing temporal-binding operator. This rule must be revisited only if such optional semantics are deliberately added later. ### 26.12 Multi-source language boundary The implemented multi-source model does not add source cursors, joins, source-local loops, or a multi-log executable segment to Logline. Programs continue to consume one deterministic canonical stream and use ordinary expressions such as `source`, `channel`, `record.*`, Event/Transition conditions, Parallel, Group, collectors, and explicit temporal operators. Source declarations, canonical source clocks, named non-canonical clocks, anchors, source ordering, and preflight mapping resolution are run/package concerns outside ordinary Logline source. The program can consume trusted resolved bindings, but it cannot invent the run synchronization model at execution time. ### 26.13 Remaining product integration The language/compiler/Engine temporal path is implemented and the headless Enterprise multi-source temporal path is verified. The Workbench remains behind that headless capability. Still required for complete product integration are the authoring and visualization surfaces for: ```text multi-source import/configuration stable source identities per-source companion/DBC configuration temporal source declarations named temporal references and anchors preflight mapping visualization and diagnostics resolved deterministic source ordering composite normalized preview compiler-discovered temporal requirement visibility source identity/provenance in debugger and reports Workbench-to-Enterprise package/deploy continuity ``` These are product/Workbench integration gaps, not reasons to change the implemented language semantics above. ### 26.14 Verification baseline at this alignment point The temporal-language/runtime integration had the following verified baseline at the end of the implementation pass that established these contracts: ```text Language: 6 test files / 81 tests passed Engine: 54 test files / 405 tests passed Enterprise: 65 test files / 402 tests passed Enterprise typecheck: clean ``` The Enterprise integration suite includes a real multi-source temporal execution proof exercising trusted program analysis, named temporal reference and anchor discovery, admission preflight, frozen runtime bindings, exact canonical normalization, lazy deterministic merge, and Engine `time.reference`, `time.anchor`, and `time.toCte` evaluation in one path. ### 26.15 Current declarative clause operator The current v1 grammar distinguishes declarative clause specification from binding and equality: ```text =: declarative clause specification = binding/definition or named call argument == equality expression : object-entry separator ``` Scenario candidate policies, Transition/Event/Group/Collector properties, Parallel `policy`, Repeat `count`, Group assertion members, and collection-operator `each` clauses use `=:`. Constants, Group `derive` bindings, and named call arguments continue to use ordinary `=`. This distinction is part of the current language contract. # FILE: source-notes/LOGLINE_MULTI_SOURCE_EXECUTION_AND_PROJECTION_DESIGN.md # Logline Multi-Source Execution and Projection Design **Document type:** Architecture, language, engine, debugger, and Workbench design **Status:** Locked design baseline; headless execution alignment verified through 24 September 2026; Workbench projection integration remains **Date:** 20 September 2026 **Scope:** Multi-source input, deterministic synchronization, language-visible source identity, cross-source observation, engine execution, evidence, debugging, and Workbench projection ## 1. Purpose This document defines how Logline executes programs over records originating from multiple logs or sources. The design deliberately avoids a second language or execution model for multi-source runs. Source timestamp interpretation, anchoring, normalization, and synchronization occur before records reach the engine. The engine continues to execute one Logline program over one deterministic canonical record stream. This document complements: - `LOGLINE_TIME_AND_CTE_MODEL.md`; - `../language/LOGLINE_LANGUAGE_EXTENSION_DESIGN.md`; - `../language/LOGLINE_GROUP_AND_EXPRESSION_EXTENSION_DESIGN.md`; - `../language/LOGLINE_COLLECTOR_DESIGN.md`; - the canonical `logline.langium` grammar; - the Workbench architecture and testing documents. ## 2. Locked architectural model Each participating source has its own independently normalized cursor. Every record emitted by such a cursor already has a valid Canonical Timeline Epoch (CTE) timestamp. The synchronizer performs a deterministic k-way merge: ```text normalized source cursor A --\ normalized source cursor B ----> deterministic CTE merge ----> engine LogRecordSource normalized source cursor C --/ ``` The synchronizer: 1. observes the head record of every non-exhausted source cursor; 2. selects the smallest CTE timestamp; 3. applies the run's deterministic equal-timestamp policy when required; 4. emits one canonical record; 5. advances only the selected source cursor. The engine receives the merged output only. It does not own source cursors, normalize timestamps, resolve anchors, or merge logs. ## 3. One semantic execution stream Multi-source execution is not a separate engine mode. The engine always receives one ordered canonical stream and retains the existing: - program counter; - candidate model; - structured-control semantics; - stabilization rules; - segment lifecycle; - collector timing; - evidence and report model. There is one Logline semantic program counter per candidate, not one program counter per source. Independent source cursors belong to the synchronizer upstream of the engine. The language does not gain source cursors, source-local execution loops, joins, or a special multi-log segment. ## 4. Source and channel identity The normalized `source` field has one locked meaning: > `source` is the stable `sourceId` declared by the run's Source Package Manifest. It is not an artifact filename, storage object key, UI label, local path, or adapter-generated display name. `channel` is a separate optional provenance dimension within a source. It must not be folded into `source`, and neither value should be folded into a signal name when the source format provides a cleaner separation. The current-record expression context exposes: ```text source channel record.source record.channel ``` The direct aliases and corresponding `record.*` properties identify the same canonical record values. Source IDs may be compared, used in membership expressions, stored in constants, and inspected in ordinary predicates: ```logline const ACCESS_SOURCES = ["proximity", "vehicle-state"]; condition =: source == "proximity"; condition =: source in ACCESS_SOURCES; condition =: source == "vehicle-state" && channel == "CAN1"; ``` No `on source`, `from log`, or equivalent segment-level syntax is introduced. ## 5. Canonical record identity and provenance Every execution record must preserve enough identity to support deterministic execution and navigation back to its origin. Required concepts are: - `record.index`: immutable index in the final merged execution stream; - `record.timestamp`: exact CTE timestamp; - `record.source`: stable manifest `sourceId`; - `record.channel`: optional source-local channel; - `record.sourceLine`: optional original line or source-format index where meaningful; - stable source-record provenance sufficient to locate the originating raw record; - retained native timestamp evidence where required by the CTE model. `record.index` is assigned after deterministic merge and is never renumbered by filtering or presentation. `record.sourceLine` is not a substitute for `record.index` and is not guaranteed to exist. The exact wire name of any additional internal source-record identity is a canonical record/report contract concern and does not change the language semantics locked here. ## 6. Language execution over multiple sources Ordinary segment conditions select records from the merged stream. Sequential segments express order in that merged stream: ```logline event ApproachDetected { condition =: source == "proximity" && fields.zone == "approach"; } transition VehicleUnlocked { signal =: "lock_state"; type =: string; condition =: source == "vehicle-state" && to == "UNLOCKED"; } ``` This means the unlock record must occur after the approach record in deterministic merged order. Parallel is used when observations must progress concurrently or when multiple branches need to observe the same records. Group is used when a bounded set of records from one or more sources must be retained and processed together. Collectors continue to observe the stream according to their existing program or candidate scope. A collector condition may select one source, several sources, or every source. Each collector updates at most once per merged record per applicable scope. ## 7. Common matched-observation references Cross-source temporal conditions require downstream access to the record that completed an earlier observational segment. Transition and Event therefore expose a common matched-observation interface: ```text SegmentName.timestamp SegmentName.time SegmentName.source SegmentName.channel SegmentName.record ``` `timestamp` and `time` are aliases for the matched record's CTE timestamp. `record` is the immutable matched canonical record and permits structured access such as: ```text ApproachDetected.record.fields.deviceId ApproachDetected.record.sourceLine ``` Transition retains its existing attributes: ```text signal type from to ``` Event does not gain arbitrary capture declarations. Its `record` attribute is the matched canonical record, not an independently constructed capture object. References remain candidate-local and follow existing lexical-scope, completion, guarded-access, Parallel, Crossroads, and Repeat rules. Scenario qualification remains available where current reference semantics permit it. Group does not expose a generic `timestamp`, because observation start, completion, and derived effective time are different concepts. It retains the explicit attributes locked in the Group design, including `startTimestamp`, `completionTimestamp`, and author-defined timestamps inside `result`. ## 8. Cross-source temporal comparison Canonical record timestamps are already comparable CTE values. Cross-source comparisons use the common time operators defined by the Group and expression-extension design. Conceptually: ```logline condition =: source == "vehicle-state" && timestamp >= ApproachDetected.timestamp && timestamp - ApproachDetected.timestamp <= time.duration(2, seconds); ``` No source-specific timestamp conversion is performed for canonical record timestamps inside the engine. ## 9. Temporal values embedded in record payloads Payload fields may contain timestamps, offsets, durations, or epoch-like values that are distinct from the record's canonical timestamp. Converting such a value to CTE requires explicit interpretation and, where applicable, an explicit preflight-resolved temporal reference or anchor. The language uses the `time` namespace: ```logline time.toCte( record.fields.value, as = time.epochTimestamp( epoch = unix, unit = milliseconds ), temporalReference = time.reference( source = record.source, id = "payload-clock" ) ) ``` A named source/file anchor is obtained explicitly: ```logline time.anchor( source = record.source, id = "source-start" ) ``` `time.reference` returns an opaque preflight-resolved temporal mapping. `time.anchor` returns the resolved CTE timestamp of a named anchor. Neither function guesses a source, reference, epoch, unit, timezone, or mapping. The registry behind these operations is prepared during temporal preflight from source evidence and manifest declarations. A missing, contradictory, unsupported, or inexact reference is a deterministic preflight or runtime diagnostic according to whether it can be resolved before record-dependent evaluation. Applying such a conversion does not modify the canonical record timestamp and does not reorder the stream. ## 10. Equal CTE timestamps Equal CTE timestamps do not imply nondeterministic execution. The synchronizer's configured source order and source-record order establish a deterministic total order. `record.index` reflects that order while the records retain equal timestamps. Sequential language constructs observe the total order. They must not interpret the tie order as proof of physical causality. When records with the same CTE timestamp are semantically unordered or must all participate in one decision, the program uses Parallel or Group. It does not depend on a particular incidental source ordering. ## 11. Derived effective time and non-retroactivity A Group may derive an effective timestamp earlier than the physical records that revealed it. That derived timestamp: - is a normal typed result value; - may be compared with retained observations; - may be reported and visualized; - does not become a new canonical record; - is not inserted into the execution stream; - does not rewind the engine; - does not cause already-consumed records to be evaluated again. Therefore: > If later records may reveal effective times for earlier events, the program must begin its Group or parallel observation early enough to retain every physical record needed for the later correlation. A single Group may collect relevant records from several sources. Multiple Groups in Parallel may retain independent source observations when their lifecycles differ. Logline does not introduce retrospective matching against an implicit history database. ## 12. Source exhaustion and end of input Source cursor exhaustion is a synchronizer concern and is not emitted as a synthetic canonical record. The language observes global end of input through existing candidate and incomplete-segment finalization rules. It does not gain an implicit per-source EOF event in this design. If a Group must prove bounded absence, its completion condition must be established by observable merged-stream progress or another explicit completion record. An exhausted run that never reaches the required bound remains incomplete under the locked Group rules. Any future source-lifecycle event model requires a separate explicit design. It must not be introduced through hidden pseudo-records. ## 13. Engine contract For each merged canonical record, the engine must: 1. preserve its CTE timestamp, merged index, source, channel, and provenance identity; 2. evaluate active candidates and segments using existing deterministic stabilization rules; 3. make the same record available to all active Parallel branches according to existing Parallel semantics; 4. update applicable collectors once per record per scope; 5. retain source-aware evidence for completed and failed evaluations; 6. advance only through the supplied `LogRecordSource` contract. The engine must not: - open or advance upstream source cursors directly; - parse native timestamps; - select timezone, epoch, or unit defaults; - resolve source anchors used for canonical ordering; - reorder records; - infer a different chronology from source identity; - treat a filtered Workbench view as execution input; - create physical records from Group results. The expression runtime may apply explicitly selected, preflight-resolved temporal mappings to payload values as defined in Section 9. This capability is separate from canonical stream normalization. ## 14. Evidence, debugger, and report identity Every record-backed execution event must retain both perspectives: ```text execution identity merged record.index CTE timestamp origin identity sourceId optional channel source-local record provenance native timestamp evidence where retained ``` Debugger frames, diagnostics, Group evidence, collector evidence where retained, and reports must preserve enough identity to navigate from execution truth to the originating raw source. A derived Group effective-time marker must remain linked to the physical evidence records that produced it. The marker does not masquerade as a raw or canonical input record. ## 15. Workbench source and execution views Workbench presents two related but distinct record surfaces. ### 15.1 Raw Sources Raw Sources contains one entry per imported source/log artifact. Selecting an entry shows that source's records in original source order and, where available, its original representation, native timestamp, source line/index, and import diagnostics. Raw Sources is for provenance, import inspection, and source-local navigation. It is not the engine's execution order. ### 15.2 Execution Records Execution Records shows the one canonical merged CTE stream consumed by the engine. Each row displays enough information to distinguish origin, including source and optional channel. The view preserves global `record.index` and deterministic equal-time ordering. Users may filter by source or channel without changing indexes, chronology, debugger identity, or execution semantics. ### 15.3 Multi-source timeline projection Workbench may additionally project sources as separate CTE-aligned lanes or columns. This is a visualization of the same merged execution data. It does not create independent execution timelines, alter ordering, or become a second source of execution truth. ## 16. Debugger and navigation behavior Selecting a debugger frame or record-backed evaluation must: 1. select the authoritative merged execution record; 2. reveal it in Execution Records, even when the current filter would otherwise hide it; 3. identify its source and channel; 4. permit navigation to the originating Raw Source record; 5. synchronize Program, Visual, Debug, Report, and record projections through engine-provided identity rather than heuristic timestamp matching. Selecting a raw record that participated in execution should navigate to its merged execution record when an identity mapping exists. Equal timestamps are insufficient as navigation identity. Source plus timestamp is also insufficient when one source contains multiple equal-time records. Navigation uses stable record identity. For Group-derived effective events, Workbench may show an effective-time marker on the shared CTE timeline. Selecting it highlights the Group result and its retained physical evidence set. ## 17. Language and grammar impact The current grammar already provides: - `source` and `channel` as built-in record fields; - `fields.*`, `signals.*`, and `record.*` access; - membership and Boolean operators suitable for source selection; - Parallel, Crossroads, and Repeat structure. Required language work is limited to the common expression and Group extension already planned, plus: - standard Event matched-observation references; - Transition alignment with the common observation attributes; - nested access through `SegmentName.record.*`; - explicit `time.reference` and `time.anchor` functions; - validation and typing of source-aware temporal lookup; - documentation of `source` as the manifest `sourceId`. No new executable segment is required for multi-source support. ## 18. Implementation audit before claiming support Before multi-source execution is advertised as implemented, the current code must be audited against this design. The audit covers: - canonical record types in core/import boundaries; - preservation of source, channel, source-line, native-time, and record identity; - one normalized cursor per source; - exact CTE mapping and per-source monotonicity validation; - deterministic k-way merge and equal-time policy; - assignment and preservation of merged `record.index`; - engine `LogRecordSource` consumption; - source-aware expressions and missing-field behavior; - collector once-per-merged-record timing; - Parallel delivery of shared records; - Event/Transition matched-observation references; - Group cross-source collection and non-retroactivity; - trace, diagnostic, report, and debugger identity propagation; - Raw Sources and merged Execution Records projections. Documentation is not evidence that these capabilities are already implemented. ## 19. Required verification Verification must include at least: - two sources with distinct timestamp representations mapped to one CTE; - mixed absolute and anchored-relative sources; - rejection of an unanchored source; - rejection of a non-monotonic normalized source; - deterministic interleaving and repeatability; - multiple equal-CTE records across and within sources; - source- and channel-qualified Event and Transition conditions; - sequential cross-source matching; - Parallel observation across sources; - Group collection and derivation across sources; - payload timestamp conversion using a resolved source temporal reference; - derived effective time earlier than Group completion without stream mutation; - program- and candidate-scoped collectors over merged input; - debugger navigation from merged execution record to raw source record; - source filtering that preserves global record identity; - multi-source lane projection matching the merged execution chronology. Large-source verification must confirm that synchronization remains cursor-backed and does not require full materialization merely to establish ordering. ## 20. Explicit non-goals This design does not introduce: - one semantic program counter per source; - source-local segment execution modes; - language-visible source cursors; - a multi-log segment; - implicit log joins; - retrospective matching against unretained records; - implicit temporal conversion; - heuristic source synchronization; - source EOF pseudo-records; - Workbench-owned execution semantics; - automatic causal ordering for equal timestamps. ## 21. Implementation sequence The implementation sequence is: 1. lock this design and add it to the architecture/design index; 2. audit current core, importer, synchronizer, engine, debugger, report, and Workbench contracts; 3. record implementation gaps without weakening this design; 4. implement the language and expression changes through the central dependency boundary; 5. implement or correct normalization and synchronization upstream of the engine; 6. propagate stable source-aware identities through execution evidence; 7. add Raw Sources, merged Execution Records, filtering, and navigation projections; 8. add optional multi-source CTE-aligned visualization; 9. complete unit, integration, determinism, scale, and end-to-end verification; 10. update capability reporting only after the verified path is complete. ## 21.1 Implementation alignment record — 26 September 2026 The headless execution portions of this design have now been implemented and verified for the current Enterprise BLF path. ### Canonical identity and composition The canonical record identity split is implemented: - `record.index` is the global index in the final deterministic execution stream; - source-local record identity/provenance remains separate as `sourceRecordIndex` and optional source-line evidence; - final `record.index` is assigned only by the composite source after source normalization. `@logline/core/source-composition` now provides synchronous and asynchronous lazy composition. The Enterprise worker uses the asynchronous cursor so large source logs are not pre-materialized merely to merge them. The merge is bounded to one head record per non-exhausted source and advances only the selected source cursor. The deterministic total-order rule is: 1. exact CTE timestamp; 2. resolved/frozen source order; 3. source cursor/source-record order. Per-source normalized CTE order is validated as non-decreasing. Source identity is also validated by the composition boundary. ### Resolved source ordering Source priority is resolved during admission and frozen into the immutable Work Package. - explicit manifest source order is preserved exactly; - when explicit source order is omitted, manifest source declaration order becomes the resolved order; - the current supported ordering policy is `source-order`; - multi-source Work Packages require a resolved ordering; - workers do not infer equal-time priority from incidental `workPackage.sources` array order. ### Temporal operator integration The payload-time semantics in Section 9 are implemented through shared `@logline/temporal` bindings. - canonical top-level record timestamps are normalized automatically before composition; - payload timestamps/temporal fields are never rewritten automatically; - named source-local clocks are declared explicitly and resolved during temporal preflight; - `time.reference(...)` returns a named temporal-reference identity; - `time.anchor(...)` returns the named anchor's resolved CTE timestamp and retains anchor identity in expression provenance; - `time.toCte(...)` explicitly converts selected payload/source values using the program-selected temporal interpretation and the same trusted preflight binding environment; - incompatible interpretation/binding semantics are rejected rather than accepted on arithmetic compatibility alone. ### Program analysis and admission linking The compiler now discovers `time.reference(...)` and `time.anchor(...)` binding use sites without changing canonical `ProgramIR`. Enterprise persists trusted compiler-derived analysis separately from the immutable client-owned Program Bundle. The analysis is tied to exact bundle/program artifact identities and digests. Compiler-static `source` + `id` uses are checked during admission against the run's resolved named temporal bindings. Runtime-dependent identities are deliberately left to deterministic Engine lookup. ### Verification status A real Enterprise integration test now proves, in one path: - immutable Program Bundle publication; - trusted compiler analysis from exact program bytes; - static named reference and anchor discovery; - two independent real BLF inputs; - one applicable DBC used by both sources; - explicit reversed source priority; - equal canonical CTE timestamps; - a named Unix/POSIX millisecond payload clock; - a named exact anchor; - admission-time static temporal preflight; - frozen Work Package temporal bindings and source ordering; - exact canonical timestamp normalization; - lazy deterministic multi-source merge; - Engine `time.reference`, `time.anchor`, and `time.toCte` evaluation; - cross-source scenario execution; - final report/provenance assertions. The Enterprise capability `execution.blf-multi-source-single-program` is marked `verified` on the strength of that path. ### Workbench alignment The Workbench portions of the canonical multi-source execution path are now implemented for the current retained-source model. - imports are retained as independent source instances with stable source/session identity and source-scoped catalogues; - Raw remains a source-local inspection surface with explicit retained-source selection; - Execution Records is the one canonical merged CTE stream; - canonical execution identity is separate from source-local record provenance across debugger, breakpoints, replay, and reports; - Workbench composition reuses the Core async composite cursor rather than sorting source arrays locally; - viewer and Run/Debug create independent cursors from the same retained-source execution plan; - exact canonical temporal preflight reuses the shared `@logline/temporal` resolver and runtime bindings; - relative source clocks remain blocked until an explicit exact synchronization relationship is supplied; - the Time synchronization UI validates mappings through real preflight and exposes structured temporal diagnostics; - synchronization facts are invalidated when the retained source instances that justified them are replaced or removed; - original source timestamps are preserved independently from normalized CTE timestamps. Optional multi-lane CTE visualization remains a presentation enhancement rather than an execution prerequisite. The current synchronization editor also does not claim to be a general-purpose authoring UI for every named payload clock/reference representable by the temporal contracts. ## 22. Lock statement This document is locked as the multi-source execution and projection design baseline on 20 September 2026. The lock establishes: - one deterministic merged CTE stream as engine input; - stable manifest source identity on every applicable record; - ordinary predicates as the source-selection mechanism; - common Transition/Event matched-observation references; - Group and Parallel as the correlation mechanisms; - explicit source temporal-reference access for payload conversion; - non-retroactive derived effective times; - separate raw-source and merged-execution Workbench views; - identity-based debugger navigation between execution and origin; - no new multi-source segment or alternate engine execution model. Implementation audits may identify missing code. Such gaps are implementation work, not reasons to silently change this design. ## Log processing configuration and source binding A portable Log Processing Configuration defines reusable import compatibility requirements, logical source slots, participation decisions, and temporal alignment rules independently of `.lgl` source and individual recordings. Its fixed ordered slots have stable identifiers, while human-facing labels may be `Log 1`, `Log 2`, and so on. Neither filenames nor incidental viewer order are authoritative bindings. A source-package/run submission explicitly associates actual immutable source artifacts with logical slots; Workbench configuration import requires review of proposed bindings. Validation tests declared *essential* requirements of each participating source: import/decoder compatibility, unique timestamp interpretation, clock units and semantics, and explicitly required execution fields and metadata. Additional fields or incidental differences are valid unless explicitly constrained. Optional attributes and supported variations are declared rather than inferred as blockers. A missing or incompatible required attribute is an actionable preflight error, not a reason to guess a different decoder or temporal mapping. Reusable rules such as `first accepted timestamp → run-relative zero` must be distinguished from recording-specific anchor values. A hard-coded point obtained from one recording cannot silently become the synchronization evidence for another. Source slot relationships use stable slot identifiers and survive Workbench source-list reordering. At resolution, the configuration becomes an execution-specific, validated plan tied to the actual source identities and integrity references. One canonical merged stream remains authoritative for Run, Debug, Report and Execution Records. ### Automatic single-source preparation The same canonical execution pipeline supports an uncomplicated one-source run without a separately authored reusable Log Processing Configuration. The trusted import/admission path identifies one accepted canonical timestamp representation and native clock domain, verifies source compatibility with the selected program, and resolves a deterministic CTE mapping. This produces an effective processing plan for the run, **not** a new user-facing configuration artifact or an alternative Engine path. For a relative canonical clock, the default reference convention is the first **authoritatively accepted** source timestamp at run-relative zero. The concrete first-record evidence is recording-specific and is frozen in the admitted processing plan; a sample/preview timestamp is not sufficient evidence. Absolute canonical clocks normalize through their validated absolute interpretation. No source record or payload timestamp is rewritten to manufacture an anchor. A reusable configuration remains optional for one source and valuable when stricter field requirements, explicit interpretation, named clocks/anchors, corrections, or reusable policy are needed. For multiple sources, source comparability must still be explicitly proved from authoritative declarations; manifest-provided relationships and portable configuration recipes are both supported routes to the same resolved temporal plan. Program semantics, frozen source identity, merge order, debugging and reporting consume the same canonical records regardless of how the effective plan was supplied. # FILE: source-notes/LOGLINE_TIME_AND_CTE_MODEL.md # Logline Time and Canonical Timeline Epoch (CTE) Model **Document type:** Cross-cutting architecture specification\ **Scope:** Logline execution time, source timestamp interpretation, normalization, multi-source synchronization, and report-time projection\ **Status:** Design baseline; implementation alignment recorded through 26 September 2026 **Date:** 10 September 2026 --- ## 1. Purpose Time handling is a correctness boundary in Logline. Logs may encode time as UTC, local civil time, offset-bearing timestamps, Unix/POSIX epoch values, relative acquisition time, device ticks, or format-specific clocks. Two timestamps that look different may identify the same instant, while two timestamps that look similar may be incomparable or ambiguous. Logline therefore does not allow the engine to interpret source clocks. The architecture separates: 1. source-native timestamp interpretation; 2. anchor resolution; 3. mapping into one canonical execution timeline; 4. deterministic multi-source synchronization; 5. engine execution; 6. report-time projection back into human or source-oriented time where retained provenance permits it. The engine sees one time domain only: **CTE — Canonical Timeline Epoch**. This document defines that model. It deliberately does not define Logline language syntax for timestamp arithmetic, duration literals, calendar functions, or other language features. --- ## 2. Core rule > **Every record presented to the Logline engine must already carry an exact timestamp expressed in the run's Canonical Timeline Epoch (CTE).** All interpretation and transformation needed to reach CTE occurs before the record enters the engine. The engine does not: - parse date/time strings; - infer timestamp units; - interpret timezones; - apply UTC offsets; - resolve daylight-saving transitions; - interpret source epochs; - anchor relative clocks; - compensate clock drift; - correct device clock rates; - synchronize sources; - guess missing temporal metadata. If a source cannot be mapped deterministically to the run's CTE, it is not eligible for execution in that run. --- ## 3. Why CTE exists CTE gives the engine a single exact ordering coordinate independent of source format. ```text Source A native time ── interpret / anchor / normalize ─┐ Source B native time ── interpret / anchor / normalize ├──► CTE stream ─► Engine Source C native time ── interpret / anchor / normalize ┘ ``` This makes the engine independent of whether a source originally used: ```text 2026-09-10T14:03:17.125Z 2026-09-10T16:03:17.125+02:00 2026-09-10 16:03:17.125 + Europe/Stockholm metadata 8.431229100 s since acquisition start 8431229100 ns since acquisition start ``` Once they have been safely resolved and mapped, the engine compares only CTE values. --- ## 4. Terminology ### 4.1 Native timestamp The value supplied by the source. Examples: ```text 2026-09-10T14:03:17.125Z 2026-09-10 16:03:17.125 8431229100ns 194357821 ticks ``` The native value is evidence and should be retained whenever practical. ### 4.2 Native time domain The semantics that explain what the native timestamp means. Examples include UTC, a fixed-offset civil timestamp, local civil time in a named zone, POSIX seconds since the Unix epoch, relative nanoseconds since acquisition start, or device ticks since boot. A timestamp value without sufficient time-domain semantics may not identify a comparable instant. ### 4.2.1 Native time-domain classification Enterprise contracts must not collapse timestamp representation, clock semantics, anchoring, and CTE mapping into one discriminator. The stable semantic classification of a source-native clock is: ```text civil epoch relative ``` These categories describe what the native clock means: - **civil** — calendar/civil clock values whose absolute interpretation may depend on embedded offset information, a fixed declared offset, or a named timezone; - **epoch** — numeric coordinates measured from an explicitly identified epoch under an explicitly identified time scale and unit; - **relative** — coordinates measured from a source-local origin such as acquisition start, device boot, process start, or another explicitly identified relative origin. Representation and interpretation details remain independent properties. Examples include timestamp text format, binary encoding, exact unit, timezone/offset policy, epoch definition, time scale, and relative origin. This separation allows future support for clocks such as GPS, TAI, NTP/PTP-derived epochs, exact device ticks, and sample clocks without inventing new top-level architecture for each format. Contract representability does not imply runtime support. Unsupported interpretation or mapping semantics must fail preflight. A purely logical or ordinal clock that cannot be mapped deterministically to CTE is not made CTE-eligible merely by assigning it a source-time category. ### 4.3 Anchor An **anchor** is the information that makes a source's native time positionable on the common run timeline. The concept applies to both absolute and relative timestamps. For a fully resolved absolute timestamp, the anchor is intrinsic: the timestamp itself identifies an absolute instant. For a local civil timestamp, the timestamp becomes intrinsically anchored only after enough timezone information is available to resolve it unambiguously. For a relative timestamp, the relationship cannot normally be derived from the record value alone. It requires an external or source-level relationship such as: ```text native 0 ns = 2026-09-10T14:00:00Z ``` or: ```text native 0 ns = run CTE +2.500000000 s ``` ### 4.4 Resolved absolute instant A uniquely identified real-world instant after all required source-time interpretation has completed. Required interpretation may include timezone or offset, daylight-saving rules, declared epoch and unit, time scale, and source-specific timestamp semantics. A local clock reading is not automatically a resolved absolute instant. ### 4.5 CTE timestamp The exact time coordinate consumed by the Logline engine. CTE is the canonical temporal coordinate of execution. It is also the canonical temporal coordinate retained in execution results. ### 4.6 Time provenance The information required to explain how source-native time became CTE and, where possible, how CTE may later be projected back into absolute or source-oriented time. --- ## 5. Temporal pipeline ```text native timestamp │ ▼ source-time interpretation │ ▼ anchor resolution │ ▼ resolved absolute instant OR resolved relative coordinate │ ▼ CTE mapping │ ▼ per-source non-decreasing CTE cursor │ ▼ multi-source synchronizer │ ▼ one deterministic CTE record stream │ ▼ Logline engine │ ▼ execution result in CTE │ ▼ report projection / enrichment │ ├──► absolute UTC/civil time, when valid └──► native source time, when valid ``` No stage after `CTE mapping` requires the engine to understand source time. --- ## 6. CTE representation CTE is an exact linear coordinate with nanosecond precision. The target semantic representation is compatible with the engine's exact timestamp shape: ```ts interface CteTimestamp { readonly seconds: bigint; readonly nanos: number; } ``` The canonical representation invariant is: ```text 0 <= nanos < 1_000_000_000 ``` `seconds` carries the signed whole-second coordinate. Negative CTE values are representable when the selected epoch and mapping require them. ### 6.1 No floating-point time CTE conversion, comparison, ordering, and offset application must not depend on floating-point milliseconds. The following is not an acceptable canonical transformation: ```text nanoseconds -> JavaScript Number milliseconds -> engine timestamp ``` because exact sub-millisecond information may be lost. Where a source supplies exact integer nanoseconds, that precision must remain exact through CTE. ### 6.2 Exact conversion requirement A source time base must be convertible to integral CTE nanoseconds without silent rounding. If a source uses a clock whose ticks cannot be represented exactly at nanosecond precision, v1 must reject that mapping unless an explicit, separately designed precision/rounding policy exists. No magnitude-based or floating-point approximation is allowed silently. --- ### 6.3 Exactness, resolution, accuracy, and uncertainty The following concepts are distinct and must not be collapsed: ```text CTE representation exactness source timestamp representation precision source clock resolution physical clock accuracy synchronization uncertainty ``` An exact CTE coordinate means that Logline represented the declared/mapped coordinate without arithmetic loss. It does **not** mean that the physical event time is known to nanosecond accuracy. For example, a source may emit nanosecond-form timestamps while its hardware clock updates every 100 microseconds and is synchronized to its reference only within ±2 milliseconds. Logline may still map the supplied coordinate exactly to CTE while retaining the weaker physical timing information as provenance. For v1: - inability to convert a requested mapping exactly to integral CTE nanoseconds is an eligibility failure unless an explicit supported loss/rounding policy exists; - known need for unsupported clock-rate or drift correction is an eligibility failure; - declared clock accuracy or synchronization uncertainty is normally retained as evidence and does not silently modify CTE; - unknown accuracy remains unknown and must never be interpreted as perfect accuracy. Future tooling may use retained temporal-quality evidence to warn that a scenario's requested timing distinction is finer than the acquisition system can substantiate. That is separate from CTE execution semantics and does not require a Logline language change now. ## 7. CTE epoch modes A run has one CTE epoch mode. All sources participating in the run map to that same CTE. ### 7.1 Absolute CTE When the run is anchored to real-world absolute time: ```text CTE 0 = 1970-01-01T00:00:00Z ``` The coordinate is the exact supported Unix/POSIX-epoch representation at nanosecond precision. Examples: ```text UTC source -> resolved absolute instant -> absolute CTE local-time source + Europe/Stockholm -> resolved absolute instant -> absolute CTE relative source + absolute acquisition-start anchor -> resolved absolute instant for each record -> absolute CTE ``` This allows mixed absolute and relative sources to share one absolute execution timeline. ### 7.2 Relative CTE A run may use a relative CTE only when no trustworthy absolute anchor is available or declared. In that case: ```text CTE 0 = explicitly defined run-relative reference ``` Example: ```text Source A native 0 ns = CTE 0 Source B native 0 ns = CTE +2.500000000 s ``` The engine operates exactly the same way as in an absolute run. The difference is retained outside the engine in run timeline provenance. A relative CTE must never be presented as a real-world date/time. ### 7.3 Choosing the mode For v1: - if participating sources are deterministically anchored to real-world absolute time, use absolute CTE; - use relative CTE only when no trustworthy absolute run anchor exists; - do not invent an absolute epoch merely to make a relative run look absolute. --- ### 7.4 Run-root resolution is derived by preflight The run's CTE mode is a preflight conclusion, not an arbitrary execution switch. Preflight resolves the complete temporal dependency graph: - if every participating source resolves consistently to supported real-world absolute time, the run uses absolute CTE; - if no trustworthy absolute root exists, relative CTE is permitted only when an explicit stable run-relative reference exists and every participating source resolves to it; - the existence of an absolute source does not make a disconnected relative component comparable; - Logline must not downgrade valid absolute time to relative time merely because the scenario only needs elapsed timing; - unsupported absolute semantics must not be reinterpreted as relative time. An internally consistent set of relative source relationships may determine pairwise offsets while still lacking a run-relative origin. Such a set is not eligible for execution until an explicit run-relative reference is supplied. Logline must not implicitly choose the first source, earliest record, minimum timestamp, or source ordering as relative CTE zero. Explicit origin selection keeps CTE stable when additional earlier sources are later added; negative CTE values are valid when required. ## 8. Absolute timestamp normalization Absolute-looking timestamps are comparable only after they identify unique instants. ### 8.1 Explicit UTC or numeric offset Examples: ```text 2026-09-10T14:00:00Z 2026-09-10T16:00:00+02:00 ``` These contain explicit offset information and can be resolved directly under the supported time scale. If they identify the same instant, they must map to the same CTE value. ### 8.2 Local civil time plus named timezone Example: ```text native timestamp: 2026-09-10 16:00:00 timezone: Europe/Stockholm ``` The named timezone must be applied before the timestamp is considered an absolute instant. The machine's own local timezone must never be used as an implicit fallback. ### 8.3 Ambiguous local time During a daylight-saving fallback, the same wall-clock time may occur twice. If the supplied information does not identify which occurrence was intended, normalization must fail. It must not choose one occurrence silently. ### 8.4 Nonexistent local time During a daylight-saving spring transition, some local wall-clock times do not exist. If a source specifies such a value and no source-specific rule resolves it, normalization must fail. ### 8.5 Timezone abbreviations Abbreviations such as `CST`, `IST`, or `BST` are not globally unique. They must not be interpreted without an explicit source/profile mapping that gives them deterministic meaning. ### 8.6 Numeric epoch values A numeric timestamp is not self-describing. The shared text importers may retain a numeric millisecond value (or a time-of-day millisecond sort coordinate) for source-local review, but that representation is **not** a trusted Unix/POSIX clock declaration. The accepted timestamp contract now distinguishes undetermined origin from an explicitly offset-bearing UTC/POSIX instant; the Workbench synchronization display and temporal preflight honor that distinction. Multi-source merging under required normalized time refuses unproven numeric coordinates. Importer compatibility and clock interpretation are separate from timestamp parsing. ```text 1725976800 1725976800000 1725976800000000 ``` must not be classified by guessing magnitude. The source contract must declare the epoch and unit, such as Unix epoch seconds, milliseconds, microseconds, or nanoseconds. ### 8.7 Date-only and time-only values A date-only or time-only field does not necessarily identify an instant. Additional source semantics are required before such values can be mapped to absolute CTE. ### 8.8 Time scales and leap seconds The implementation must be explicit about supported time scales. UTC-derived/POSIX timestamps are not interchangeable with every engineering time scale. Sources expressed in GPS time, TAI, or another scale require an explicit supported conversion outside the engine. Leap-second values and time scales requiring leap-second preservation must not be silently forced through an implementation that cannot represent their semantics correctly. Until such support is deliberately implemented and verified, preflight must reject unsupported cases. --- ## 9. Relative timestamp normalization Relative timestamps identify elapsed coordinates within a source time domain. Examples: ```text 0 ns 8431229100 ns since acquisition start 12.450 s since process start device tick 194357821 ``` They do not identify an absolute instant by themselves. ### 9.1 Single-source relative execution A single relative source can use a relative CTE by explicitly defining its run origin. The common simple case is: ```text source native 0 = CTE 0 ``` No absolute time needs to be invented. ### 9.2 Multi-source relative execution Every relative source participating in a multi-source run must be anchored to the same run timeline. For example: ```text Source A native 0 = CTE 0 Source B native 0 = CTE +2.5 s ``` or, in an absolute run: ```text Source A native 0 = 2026-09-10T14:00:00Z Source B native 0 = 2026-09-10T14:00:02.500000000Z ``` An unanchored relative source cannot participate in multi-source execution. --- ## 10. Anchor model The user-facing rule is: > **Every source in a multi-source run must be anchored. Absolute timestamps can provide their own anchor once fully interpreted; relative timestamps require a relationship to the common run timeline.** Anchors may be obtained from an unambiguous absolute timestamp carried by source records, trustworthy source/file metadata, an explicit source manifest declaration, a relationship to an already anchored run/source reference, or a future supported synchronization mechanism. The provenance must record where the anchor came from. ### 10.1 One anchor in v1 The initial model supports exact 1:1 clock progression. ```text CTE = nativeTime + offset ``` or equivalently: ```text native X = CTE Y ``` A single anchor establishes the offset only. It assumes the source clock progresses at the same rate as CTE. ### 10.2 Clock drift and rate correction Clock drift/rate correction requires a richer mapping such as: ```text CTE = a * nativeTime + b ``` where `a != 1`. A single anchor cannot establish `a`. The first Enterprise implementation must not pretend otherwise. Drift/rate correction is deferred until deliberately designed, implemented, and verified. A request requiring it must be rejected rather than approximated. ### 10.3 Clock resets, wraps, and discontinuities One source-level mapping is invalid if the source clock resets, wraps, jumps, or changes rate during the source. Such a source must either be segmented into independently anchored time domains upstream, or use a future mapping capability that explicitly supports discontinuities. The engine must never compensate for clock discontinuities. --- ### 10.4 Anchor dependency graph Source-to-source anchors form a temporal dependency graph during preflight. An anchor correspondence connects a point in one source's native time domain to one of: ```text a resolved absolute instant an explicit run-relative reference coordinate a point in another source's native time domain ``` Anchor provenance is a separate concern from the correspondence itself. Provenance may identify intrinsic timestamp semantics, trustworthy source metadata, an explicit manifest declaration, or a future verified synchronization mechanism. Preflight resolves source-to-source dependencies transitively until each participating source has a deterministic mapping to the selected run root. ### 10.5 Multiple paths, cycles, and consistency Cycles are not inherently invalid. Under the v1 exact 1:1-plus-offset model: - a rooted consistent cycle is valid and may provide corroborating temporal evidence; - a rooted inconsistent cycle is invalid because alternate paths place the same temporal point at different CTE coordinates; - an unrooted consistent cycle establishes internal relative relationships but does not establish where that component belongs on the run timeline. Multiple independent resolution paths are permitted. They must resolve exactly to the same CTE coordinate. V1 must not average conflicting anchors or apply a hidden tolerance. A connected component that is internally consistent but has no path to the selected run root remains unanchored for execution. Contradictory anchor paths are a preflight failure and should identify the competing paths/values sufficiently for a developer to diagnose the source of the disagreement. ## 11. Source comparability Two records are temporally comparable for execution only when both have valid CTE timestamps in the same run CTE. The normalization layer establishes this property. The engine does not test source comparability because incomparable records must never reach it. ### 11.1 Multi-source preflight invariant Before multi-source execution begins, every participating source must satisfy all of the following: ```text timestamp syntax/encoding understood native time-domain semantics known required timezone/offset/time-scale information available anchor established mapping to the run CTE deterministic mapping precision acceptable requested clock transformation supported normalized source ordering valid ``` If any item fails, execution must not begin. --- ## 12. Per-source ordering requirement For scalable synchronization, each normalized source cursor must emit records in non-decreasing CTE order. Equal CTE timestamps are allowed. If a source is not ordered by its normalized timestamps, upstream processing must either reorder it deterministically or reject it before it reaches the synchronizer. The engine does not reorder records. A clock reset or incorrect anchor can therefore appear as a non-monotonic CTE source and must be diagnosed outside the engine. --- ## 13. Multi-source synchronization The scalable synchronization model is a k-way merge over one independently normalized cursor per source: ```text source A CTE cursor ─┐ source B CTE cursor ─┼──► deterministic synchronizer ─► engine LogRecordSource source C CTE cursor ─┘ ``` At each step the synchronizer: 1. observes the current head record of each non-exhausted source; 2. selects the record with the smallest CTE timestamp; 3. applies the configured deterministic equal-timestamp policy when timestamps are equal; 4. emits that record; 5. advances only that source cursor. The synchronizer does not need to materialize all records from all sources. ### 13.1 Equal CTE timestamps Equal timestamps do not imply unordered execution. A run must define deterministic tie-breaking, using source order and source-record order according to the selected equal-timestamp policy. Tie-breaking determines stream order only. It does not alter either record's CTE timestamp. --- ## 14. Engine boundary The engine's temporal contract is intentionally narrow: ```text input record timestamp = valid CTE engine compares/uses CTE does not interpret origin ``` The engine must not know whether the run uses absolute or relative CTE. It must not know source timestamp format, source timezone, source epoch, anchor source, normalization formula, original precision notation, or whether records came from one source or many. Multi-source execution is therefore not a separate engine mode. The engine always receives one deterministic CTE record stream. --- ## 15. Reporting and temporal provenance CTE remains the canonical timestamp of execution results. A report or report projection may additionally display absolute or native-source timestamps when retained provenance supports deterministic conversion. ### 15.1 Do not replace CTE A report must not discard CTE merely because a human-friendly timestamp can be displayed. For cross-source evidence, CTE is the one coordinate that establishes common chronology. ### 15.2 Preserve native evidence Where practical, retain the original native timestamp separately from CTE. This prevents loss of original text representation, timezone/offset notation, source precision, relative-time notation, and source-specific epoch semantics. ### 15.3 Projection examples For an absolute CTE run: ```text CTE -> 2026-09-10T14:03:17.331250000Z ``` may be valid. For a relative-only CTE run: ```text CTE 8.331250000 s ``` must not be rendered as a calendar datetime unless an absolute anchor is actually available. ### 15.4 Cross-source evidence ```text Scenario completion: CTE: 501.331250000 s Evidence A: source: controller.csv CTE: 501.125000000 s native: 2026-09-10T14:03:17.125Z Evidence B: source: vehicle.blf CTE: 501.331250000 s native: 8.331250000 s after acquisition start ``` CTE tells the report how evidence relates in one chronology. Each evidence item's native timestamp explains what its source actually recorded. ### 15.5 Provenance storage must scale The complete normalization formula need not be duplicated into every record. A scalable design should retain: - run-level CTE definition; - source-level time-domain and anchor mapping; - record-level native timestamp and source identity as needed; - stable references connecting report evidence to the applicable source mapping. This permits auditability without inflating millions of records with repeated metadata. --- ## 16. Required provenance The exact wire contract will be defined with the Enterprise source/result schemas, but the architecture requires enough information to reconstruct and audit the mapping. At minimum, the retained model must be capable of recording: ```text run CTE mode run CTE epoch definition per source: source identity native time-domain kind timestamp format/encoding where relevant unit where relevant timezone/offset policy where relevant time scale where relevant anchor source and value mapping kind mapping parameters precision/loss policy normalizer/version identity per record/evidence where required: source record identity original/native timestamp resulting CTE or deterministic means to reproduce it ``` The exact wire representation must avoid unnecessary per-record duplication. --- ### 16.1 Evidence, declarations, and resolved conclusions Enterprise temporal processing separates three layers: ```text source temporal evidence operator/run temporal declarations resolved temporal conclusions ``` **Source temporal evidence** records what adapters and source metadata actually provide. **Temporal declarations** supply additional facts or relationships needed to interpret or anchor a source, such as a named timezone, epoch/unit, relative origin, or anchor correspondence. **Resolved temporal conclusions** are produced only by preflight and include effective interpretation, selected CTE mode, resolved anchor path, mapping parameters, exactness, assumptions, temporal-quality provenance, and comparability status. A manifest must not accept derived claims such as `comparable: true`, `synchronized: true`, or a user-authored resolved CTE offset as substitutes for preflight. Conflicting temporal evidence is not resolved by ordinary configuration precedence. Any future override mechanism must be explicit, auditable, and provenance-preserving. Until such a mechanism is deliberately defined and supported, contradictory evidence fails preflight. This separation also allows a source declaration to remain stable across runtime capability improvements. For example, a source may correctly declare GPS time today even if the installed runtime rejects the conversion; a future verified runtime may resolve the same truthful declaration without changing what the source claims to be. ## 17. User-facing timestamp classes This table is the conceptual basis for later user documentation and AI training material. | Source timestamp | Additional information | Anchor status | CTE eligibility | |---|---|---|---| | `2026-09-10T14:00:00Z` | Supported absolute time scale | Intrinsic | Eligible for absolute CTE | | `2026-09-10T16:00:00+02:00` | Supported absolute time scale | Intrinsic | Eligible for absolute CTE | | `2026-09-10 16:00:00` | `Europe/Stockholm`, unambiguous at that instant | Resolved intrinsic anchor | Eligible for absolute CTE | | `2026-09-10 16:00:00` | No timezone/offset | Not fully anchored | Not eligible for absolute CTE | | `8431229100 ns` | Acquisition start = known absolute instant | External absolute anchor | Eligible for absolute CTE | | `8431229100 ns` | Native 0 = run CTE 2.5 s | External relative anchor | Eligible for relative CTE | | `8431229100 ns` | No relationship to common run timeline | Unanchored | Not eligible for multi-source execution | | Numeric epoch value | Epoch and unit explicitly declared | Intrinsic after interpretation | Eligible if exactly representable | | Numeric epoch value | Unit guessed from magnitude | Invalid policy | Reject | | Device ticks | Exact supported tick conversion + anchor | Potentially anchored | Eligible only if exact mapping is supported | | Ambiguous DST local time | Zone known but occurrence not disambiguated | Ambiguous | Reject | | Unsupported GPS/TAI/leap-second case | No verified conversion | Unresolved | Reject | --- ## 18. Worked examples ### 18.1 One UTC source ```text 2026-09-10T14:00:00.123456789Z -> resolved absolute instant -> Unix/POSIX epoch nanoseconds -> absolute CTE -> engine ``` No timezone guessing occurs. ### 18.2 One local-time source Source record: ```text 2026-09-10 16:00:00.125 ``` Source metadata: ```text timezone = Europe/Stockholm ``` Pipeline: ```text local civil time + named zone -> timezone/DST resolution -> unique absolute instant -> absolute CTE ``` If the local time is ambiguous or nonexistent, preflight fails unless the source contract provides deterministic disambiguation. ### 18.3 One relative BLF source ```text 0ns 999927ns 2000093ns ``` No trustworthy absolute recording start is available. For a single-source run, the relationship can be declared explicitly as: ```text native 0ns = relative CTE 0 ``` The exact nanosecond values can then map directly to relative CTE. No absolute datetime is invented, and Workbench does not silently choose the source origin or zero point on the user's behalf. ### 18.4 UTC CSV plus relative BLF CSV: ```text 2026-09-10T14:00:05Z ``` BLF: ```text native = 5s anchor: native 0 = 2026-09-10T14:00:00Z ``` Both map to the same absolute CTE instant. The engine sees equal CTE timestamps and the configured equal-timestamp policy decides deterministic record order. ### 18.5 Two relative logs ```text Source A native 0 = run CTE 0 Source B native 0 = run CTE +2.5s ``` A record at B native `1.0s` maps to `CTE 3.5s`. The run is valid as a relative CTE run even though no wall-clock datetime is known. ### 18.6 Unanchored relative source Source A is absolute. Source B contains `8431229100ns since recording start`, but recording start is unknown. There is no deterministic mapping from Source B into Source A's CTE. Result: ```text preflight rejection engine never starts ``` ### 18.7 Drift-sensitive clocks Two sources have an anchor at recording start, but engineering metadata says one device clock runs at a measurably different rate. One anchor gives offset but not rate correction. Result in v1: ```text unsupported clock transformation preflight rejection ``` No silent 1:1 approximation is permitted. --- ## 19. Diagnostic principles Timestamp failures must explain the actual temporal problem rather than collapse into a generic `normalization failed` message. Candidate diagnostic categories include: ```text TIMEZONE_REQUIRED AMBIGUOUS_LOCAL_TIME NONEXISTENT_LOCAL_TIME AMBIGUOUS_TIMEZONE_ABBREVIATION TIMESTAMP_UNIT_REQUIRED TIMESTAMP_EPOCH_REQUIRED UNSUPPORTED_TIME_SCALE UNSUPPORTED_LEAP_SECOND RELATIVE_ANCHOR_REQUIRED INVALID_ABSOLUTE_TIMESTAMP CLOCK_MAPPING_UNRESOLVED CLOCK_RATE_CORRECTION_UNSUPPORTED CLOCK_DISCONTINUITY_UNSUPPORTED TIMESTAMP_PRECISION_LOSS NON_MONOTONIC_NORMALIZED_SOURCE CTE_EPOCH_MISMATCH ``` Exact public codes belong to the implementation contract and should be frozen only when that contract is implemented. --- ### 19.1 One diagnostic, two presentations Recognized temporal failures use one canonical structured diagnostic with complementary technical and human presentations. The canonical diagnostic should be capable of carrying: ```text stable machine code severity precise technical explanation structured technical context plain-language explanation corrective guidance where possible source/field/record references where applicable ``` Machine consumers react to stable codes and structured fields, never by parsing English text. Human-facing explanations should answer, when applicable: 1. What happened? 2. Why does it matter? 3. What information does Logline have or lack? 4. What can the user do to correct it? Plain-language presentation must remain technically truthful but must not require specialist timestamp terminology merely to understand the problem. Technical detail remains available for developers and support tooling. Known validation/preflight failures must not surface raw implementation exceptions as their primary user-facing message. Unexpected internal failures may retain technical exception detail in protected logs while presenting a useful outer diagnostic and a stable diagnostic/correlation identifier. ## 20. v1 supported temporal model The first Enterprise temporal model should intentionally remain narrow and deterministic. Supported design target: - exact CTE timestamps at nanosecond precision; - absolute CTE based on Unix/POSIX epoch; - relative CTE with explicit run-relative epoch; - explicit UTC/offset timestamps; - local civil timestamps when a deterministic supported timezone mapping is supplied; - explicitly declared numeric epoch units; - exact relative integer time units; - one anchor per 1:1 relative clock mapping; - mixed absolute + relative sources when every relative source has an absolute anchor; - multiple relative sources when all are anchored to one relative run CTE; - deterministic equal-timestamp ordering; - one independent normalized cursor per source; - source-native timestamp provenance; - report projection from CTE only when provenance permits it. --- ## 21. Explicitly deferred or unsupported in v1 The following must not be approximated silently: - automatic timezone guessing; - machine-local timezone fallback; - magnitude-based epoch-unit guessing; - ambiguous DST selection; - unsupported leap-second interpretation; - GPS/TAI/other time-scale conversion without explicit verified support; - clock drift compensation; - clock-rate correction; - multi-anchor regression/interpolation; - heuristic signal-correlation synchronization; - NTP/GPS correction inferred from unrelated metadata; - clock resets/wraps/discontinuities without explicit segmentation or mapping; - silent rounding into nanosecond CTE; - full materialized merge of huge sources merely to establish ordering. Capabilities may be added later, but each requires an explicit contract and verification. --- ## 22. Relationship to current Logline components ### 22.1 Engine The engine owns execution truth and consumes one ordered record stream. CTE tightens the semantic meaning of the engine timestamp: an engine timestamp is already a canonical execution coordinate. CTE does not require the engine to understand source normalization. ### 22.2 Import and source adapters Import/source layers preserve native timestamp evidence and expose the information needed for normalization. Format-specific code must not invent absolute time when the format does not establish it. ### 22.3 Enterprise worker/control plane Enterprise preflight is responsible for rejecting runs whose sources cannot be mapped safely into one CTE under the runtime's advertised capabilities. The Source Package Manifest references this temporal model rather than redefining timestamp semantics independently. The current Work Package freezes the resolved run timeline, deterministic source ordering, and named temporal bindings so workers execute preflight conclusions rather than reinterpreting manifest intent. ### 22.4 Synchronizer The synchronizer operates on already-normalized per-source CTE cursors. It is upstream of the engine. ### 22.5 Reporting Canonical execution results retain CTE. Report projection/enrichment may add absolute or native-source representations using retained normalization provenance. Such conversion is not engine execution semantics. ### 22.6 Workbench Workbench consumes the same shared temporal preflight and runtime binding model as headless execution; it does not implement an independent synchronization model. The current retained-source path provides: - source-local Raw inspection for each retained import; - one merged Execution Records stream for canonical execution; - shared `@logline/temporal` run-timeline preflight; - explicit synchronization of relative canonical source clocks through exact anchors rather than inferred offsets; - one resolved temporal binding environment reused by Execution Records and Run/Debug while each keeps an independent cursor; - canonical top-level timestamp normalization before Core composition; - structured temporal diagnostics with corrective guidance when a source set is unresolved or contradictory; - lifecycle invalidation of synchronization facts when the source instances that justified them are replaced or removed; - separate canonical execution identity and source-local provenance; - preservation of original source timestamps alongside exact CTE time. The Workbench synchronization editor owns canonical source-clock relationships only. Existing named non-canonical temporal references, named anchors, and quality evidence remain part of the temporal declaration/binding model and are preserved when canonical synchronization is edited. A dedicated general-purpose UI for authoring every possible named payload clock/reference is not implied by the current synchronization editor. --- ## 23. Relationship to the Logline language This document does **not** define the complete Logline language syntax or operator registry for time; those contracts belong to the language/compiler/engine design. CTE remains the execution-time foundation beneath those operators. At the original 10 September baseline, language-time operations were still described here as future/separate work. The current language/runtime now includes exact timestamp/duration operations plus explicit temporal conversion and named binding access, including `time.reference`, `time.anchor`, and `time.toCte`. That implementation does not weaken the normalization boundary: Enterprise/source normalization still places canonical record timestamps onto CTE before Engine execution. Language operators act on already-canonical timestamps or explicitly selected non-canonical values; they do not turn Engine into a source synchronizer. --- ## 24. Verification requirements Timestamp handling must be verified as a correctness feature, not only unit-tested as parsing code. Verification of this model includes, or where the capability remains unsupported must eventually include, at least: - exact nanosecond boundary tests; - negative/positive second normalization tests; - equivalent UTC and fixed-offset timestamp tests; - named-timezone tests; - daylight-saving ambiguous-time rejection tests; - daylight-saving nonexistent-time rejection tests; - numeric epoch unit tests; - no-unit rejection tests; - exact relative-anchor mapping tests; - mixed absolute/relative multi-source tests; - two-relative-source synchronization tests; - equal-CTE deterministic tie tests; - unanchored-source rejection tests; - clock-drift/rate-correction rejection tests; - clock reset/non-monotonic source rejection tests; - unsupported time-scale tests; - precision-loss rejection tests; - report projection/provenance tests; - large source-backed multi-cursor synchronization tests; - repeat-run determinism tests. Verification must prove that normalization produces the same CTE ordering independently of host machine timezone and locale. --- ## 25. Architectural invariants The following are the normative design rules. 1. **CTE is the engine's only time domain.** 2. **Every engine input record is normalized to CTE before execution.** 3. **Every source in one run maps to the same CTE epoch.** 4. **Absolute timestamps are resolved to unique supported absolute instants before CTE mapping.** 5. **Every source in a multi-source run is anchored.** 6. **Relative timestamps require an external/common-timeline relationship unless the run is a single-source relative CTE with an explicitly defined origin.** 7. **Native timestamp evidence is preserved separately from CTE whenever practical.** 8. **No timezone, unit, epoch, DST occurrence, or clock correction is guessed silently.** 9. **CTE arithmetic and ordering are exact; floating-point millisecond conversion is not canonical.** 10. **v1 clock mappings are 1:1 plus offset; drift/rate correction is unsupported unless explicitly added later.** 11. **Each normalized source cursor emits records in non-decreasing CTE order.** 12. **Multi-source synchronization occurs outside the engine.** 13. **Equal CTE timestamps use deterministic tie-breaking without changing their timestamps.** 14. **Execution results retain CTE as canonical time.** 15. **Report projection may convert CTE only where provenance makes that conversion deterministic.** 16. **A relative CTE must never be presented as an absolute datetime without an absolute anchor.** 17. **Unsupported temporal semantics fail preflight; they are never approximated inside the engine.** 18. **Language-level time syntax is a separate concern from source normalization and CTE.** 19. **Timestamp representation, native time-domain semantics, anchoring, and CTE mapping are modeled as separate concerns.** 20. **Run CTE mode is a preflight conclusion derived from the resolved temporal graph.** 21. **Relative CTE zero is explicit and stable; it is never inferred from source ordering or earliest data.** 22. **Redundant anchor paths and cycles are allowed when exactly consistent; contradictory paths fail preflight.** 23. **CTE exactness does not imply physical clock or synchronization accuracy.** 24. **Source evidence, operator declarations, and resolved temporal conclusions remain distinct.** 25. **Recognized temporal diagnostics provide both machine-precise structure and understandable human guidance from one canonical diagnostic.** --- ## 26. Implementation alignment record ### 26.1 Original baseline status When this design baseline was written on 10 September 2026, the document was a target architecture specification rather than a claim that the entire normalization pipeline was implemented. At that point, exact relative BLF nanosecond preservation and engine-facing exact seconds/nanoseconds conversion already demonstrated part of the intended direction, while the Enterprise source manifest, normalization contracts, synchronizer, capability reporting, and report provenance still required alignment. ### 26.2 Headless runtime alignment as of 24 September 2026 The headless runtime now implements the central CTE pipeline described by this document for the supported exact v1 model. Implemented and verified architecture includes: - `@logline/temporal` as the runtime-neutral owner of temporal declarations, validation, exact CTE mappings, canonical timestamp normalization, named temporal references, named anchors, runtime bindings, and named preflight-binding resolution; - one independently normalized source cursor per admitted source; - exact canonical top-level record timestamp normalization before Engine execution; - deterministic lazy multi-source composition outside the Engine; - one final canonical execution-stream index assigned after composition; - one canonical CTE stream supplied to Engine; - immutable Enterprise Work Packages that freeze the resolved run timeline, deterministic source ordering, and resolved named temporal binding set; - Engine temporal operators that consume the same immutable preflight-resolved binding environment used for source normalization; - trusted compiler-derived temporal-use analysis persisted separately from the client-published Program Bundle; - admission-time validation of compiler-static named temporal dependencies; - a real Enterprise multi-source temporal end-to-end execution proof. The Enterprise capability `execution.blf-multi-source-single-program` is therefore verified for the current supported path. This does not imply that every temporal form listed as a design target in this document is implemented. Unsupported interpretation/mapping semantics continue to fail deterministically rather than being approximated. ### 26.3 Canonical record time versus payload time The implementation makes the following boundary explicit: ```text canonical top-level record timestamp -> automatically interpreted/normalized by the source + temporal pipeline -> exact CTE timestamp -> canonical execution stream -> Engine payload/source field that happens to contain temporal data -> remains ordinary source data -> program explicitly selects an interpretation -> time.toCte(...) -> optional named reference or named anchor as required -> same preflight-resolved temporal binding environment ``` Automatic source synchronization applies only to the record's canonical top-level timestamp. Logline does not scan arbitrary payload fields and rewrite values that resemble timestamps. This rule is essential to deterministic semantics: source normalization prepares execution chronology, while language-level conversion expresses an explicit program decision about non-canonical temporal data. ### 26.4 Named non-canonical temporal references A source temporal declaration may now expose explicitly named source-local clocks in addition to the source's canonical record clock. Each named reference has its own: - source-local `id`; - temporal domain declaration; - optional anchors; - optional quality evidence. Named references are resolved independently from the canonical record clock. `time.reference(source = ..., id = ...)` addresses only an explicitly resolved named reference. Missing named references never fall back to the source's canonical mapping. Named anchor IDs are source-local runtime identities. A named anchor may be resolved on the canonical clock or on a named reference clock, but anchor identity must remain unambiguous within the source declaration. When a resolution path originates from a named reference, resolved temporal provenance records that reference identity rather than collapsing it into the canonical source clock. ### 26.5 Runtime language semantics over temporal bindings The implemented language/runtime semantics now include: - `time.reference(source = ..., id = ...)` -> a temporal-reference identity value; - `time.anchor(source = ..., id = ...)` -> the exact resolved CTE timestamp of that named anchor; - `time.toCte(value, as = ..., ...)` -> explicit conversion of a non-canonical value to CTE under the selected interpretation. `time.anchor(...)` does not return an opaque anchor handle. Its runtime value is a CTE timestamp; anchor identity remains available in expression provenance. For epoch-timestamp conversion, a supplied `temporalReference` must resolve to a binding whose temporal semantics are compatible with the selected interpretation. For example, an exact offset that belongs to a relative boot clock is not accepted merely because arithmetic could place a Unix/POSIX value somewhere on CTE. Semantic compatibility is checked explicitly. Displacement-style conversions require an explicit CTE anchor. Exact conversion remains mandatory; inexact nanosecond conversion is rejected. ### 26.6 Preflight binding resolution Canonical temporal preflight first selects and resolves the authoritative run timeline. Named binding resolution consumes that already-resolved timeline; it does not select a second CTE or create a competing synchronization model. The current exact binding resolver supports the implemented v1 cases needed by the verified execution path, including: - intrinsic Unix/POSIX clocks on an absolute CTE; - exact anchored linear clocks; - source-point anchors to already-resolved canonical clocks; - exact rational tick conversion only when integral nanoseconds result; - named anchor resolution on canonical or named clocks. It rejects unresolved, contradictory, semantically unsupported, or inexact relationships deterministically. No tolerance, averaging, inferred zero, or approximate fit is introduced by the named-binding layer. ### 26.7 Compiler discovery and Enterprise static preflight The compiler discovers use sites of `time.reference(...)` and `time.anchor(...)` across executable expressions, including collectors and structured segments. For each use site it records: - binding kind (`reference` or `anchor`); - source operand as static or runtime-dependent; - id operand as static or runtime-dependent; - source span when available. Literal strings and string constants are statically resolvable. Record-derived, binder-derived, and other computed identities remain runtime-dependent. This metadata is descriptive compiler analysis, not part of canonical `ProgramIR` execution semantics. Enterprise persists it as trusted server-owned `ProgramBundleAnalysis` tied to the exact immutable Program Bundle and program artifact identities/digests. At run admission: - when both `source` and `id` are compiler-static, the named binding is a link-time dependency and must be present in the resolved run binding set; - repeated identical missing static uses collapse into one admission diagnostic; - runtime control flow does not make a static lookup optional because the language currently has no optional/maybe-missing form of `time.reference` or `time.anchor`; - if either identity operand is runtime-dependent, admission does not guess and Engine lookup remains authoritative if that path executes. ### 26.8 Workbench implementation alignment as of 26 September 2026 The core Workbench multi-source temporal path is now aligned with the shared architecture. Multiple accepted imports are retained independently; Raw remains source-local; Execution Records, Run, Debug, replay, and report evidence use canonical merged-stream identity; exact CTE composition reuses Core; and unresolved relative clocks remain blocked until an explicit trusted synchronization relationship resolves them. Workbench temporal preflight now delegates run-timeline resolution to `@logline/temporal`, resolves named bindings against that same authoritative timeline, and passes the resulting immutable binding environment both to canonical timestamp normalization and to Engine runtime services. The Workbench does not independently infer temporal offsets. The user-facing synchronization flow supports exact canonical-clock anchoring for relative retained sources, including source-to-source and run-relative relationships. It preserves non-editor temporal facts, rejects disconnected/conflicting relationships, keeps viewer and Run cursors independent, and preserves original source-time provenance separately from CTE. Further temporal capabilities remain subject to the same explicit-support rule as headless execution. In particular, the synchronization editor is not a claim of support for heuristic correlation, drift fitting, clock-reset recovery, or every representable named payload clock. Those capabilities require their own verified contracts. --- ## 27. Summary The user-facing explanation can ultimately be reduced to one rule: > **Before Logline compares records, every source must be placed on the same trustworthy timeline.** The technical rule is: > **The engine executes only CTE.** Everything that makes source timestamps trustworthy and comparable—timezone interpretation, epoch/unit resolution, anchoring, relative-to-absolute mapping, synchronization, and future clock correction—belongs outside the engine. Everything that turns engine CTE back into useful human or source-oriented time belongs to report projection and provenance, not execution semantics. That separation keeps the engine deterministic while allowing Enterprise to support increasingly complex real-world logging environments without contaminating the engine with source-specific time logic. ## Reusable clock interpretation and alignment policy Source import establishes an unambiguous canonical top-level timestamp field or extraction rule, its units, clock domain, and the accepted record mapping. Clock interpretation within one source and alignment of independently recorded sources are distinct operations. A configuration must not treat a detected relative clock as evidence that clocks across files began together. For a single participating relative-clock source, Workbench shall offer **first accepted source timestamp at run-relative zero** as the default, explicitly labeled reference convention. It does not assert that the first record marks the physical beginning of the test or acquisition. Applying this convention produces an explicit resolved temporal declaration and must remain reproducible outside Workbench. If a program or source requires an external temporal relationship, the default cannot supersede that requirement. Participating absolute-clock sources with unambiguous absolute timestamp interpretation may be placed on CTE without manual anchoring. The ability to parse an absolute time does not prove the device clock was accurate; explicit, evidence-backed offset corrections may be supplied. Multiple relative sources, and mixtures of absolute and relative sources, require an established common reference: declared corresponding clock points, trustworthy acquisition metadata, known offsets, or an external absolute/run reference. Independent zero points shall not be presumed coincident. Matching similar-looking events is not sufficient evidence for automatic alignment. Source time values remain intact in provenance. Resolved CTE values are derived and separately represented. Reconfiguration recomputes the canonical merged chronology and invalidates dependent execution/debug state as needed. Only participating sources are required to pass temporal readiness for execution; excluded retained sources remain inspectable and configurable. User-facing explanations shall distinguish *recorded source time*, *source/reference correspondence*, and *resolved common timeline time*. An explanatory, non-editable timeline may display the configured source/target correspondence; it must not imply accuracy or synchronization evidence not established by the configuration. ### Explicit interpretation of numeric source timestamps The portable Log Processing Configuration may declare `timestampInterpretation` on a logical source slot when import evidence establishes a numeric timestamp representation but **does not establish its origin**. The declaration is distinct from minimum source `requirements.clock` constraints and from the slot's `timeRule` synchronization mapping: - `numeric-unix-epoch` declares that the source-native numeric coordinate uses the Unix/POSIX epoch, with a specified unit (`ns`, `us`, `ms`, or `s`). It does **not** prove that the device clock is accurate; a separate `absolute-offset` rule may express a validated correction. - `numeric-relative` declares source-native numeric time in the specified unit with no Unix/POSIX epoch meaning. Its synchronization rule must separately establish an allowed first-record convention or a trustworthy correspondence to a run or another source. Declaring multiple sources as relative does **not** establish their mutual alignment. During Workbench preparation the declared numeric clock is bound to the assigned retained source ID. The accepted record's *original* top-level timestamp is inspected as an exact integer; unsafe JavaScript numbers, fractions, time-of-day notation, contradictory verified absolute evidence, mixed representations, and unreadable timestamps fail closed. The configured unit (`ns`, `us`, `ms`, `s`) is scaled using integer arithmetic to CTE nanoseconds. Source-to-source anchors and first-record-zero evidence retain their native integer units until this same interpretation boundary converts them. Source provenance and imported timestamp objects are never rewritten. Temporal preflight resolves and validates the common timeline before the lazy merged reader normalizes each record; source identity replacement invalidates the interpretation alongside its synchronization facts. The optional interpretation is effective only for its bound source in the applied processing configuration. Workbench provides the **Numeric timestamp interpretation** control in **Log processing configuration**, where the user may declare a numeric-relative or numeric-Unix/POSIX origin and the exact unit (`ns`, `us`, `ms`, or `s`) for a bound retained source when the importer has not established the origin. Portable configuration JSON can carry the same declaration. The editor distinguishes an explicit user-provided interpretation from independently verified importer evidence; choosing an interpretation is not itself proof of clock accuracy or of a source-to-source correspondence. Changing the interpretation invalidates the existing time rule, and only validated Apply makes the updated declaration active. These declarations are portable processing instructions, **not automatically verified importer observations**. Before becoming executable, admission must confirm the selected native timestamp field can be decoded under the declared representation and unit, preserve the original source value, perform exact arithmetic, validate the associated temporal rule and evidence, and freeze the accepted mapping. Unsupported input must be rejected rather than silently coerced into a verified clock. Configuration parsing validates declaration shape and compatibility; it does not itself reclassify imported records or admit execution. Existing configurations without this optional declaration retain their current semantics. ### Automatic temporal preparation for one log A single participating source does not require an external reusable Log Processing Configuration when its trusted importer can establish an unambiguous canonical top-level timestamp interpretation and all program-required temporal information. The importer/admission boundary selects and validates the timestamp extraction and native domain; canonical temporal preflight continues to require a **resolved explicit mapping** before execution. Configuration omission is not permission for the temporal library or Engine to invent an origin. - **Absolute source:** use the supported absolute-to-CTE mapping when the clock representation, timezone/epoch and units are unambiguous. Clock accuracy is not inferred. - **Relative source:** resolve the first authoritatively accepted record timestamp and explicitly map that source-native value to run-relative CTE zero. The accepted-record reader supplies evidence, including for lazily read binary files; a bounded review sample must not stand in for that evidence. The convention does not assert physical acquisition start. - **Ambiguous source:** reject and request an explicit source hint or configuration, without silently selecting among timestamp candidates or fabricating missing references. Admission freezes the timestamp extraction, importer/decoder version, source identity, native origin evidence when applicable, and resolved mapping in the Work Package. Named temporal references required by `.lgl` still require their own binding validation. The worker reuses the frozen interpretation. For multiple participating sources, independent clocks still require a proved common timeline; one-source defaults do not generalize into automatic multi-source synchronization. # FILE: enterprise/SETUP_GUIDES.md # Logline Enterprise setup guides Logline Enterprise setup documentation is available at `https://prologline.com/enterprise/setup/`. The Microsoft Azure / Entra guide covers the required API identity and authorization setup, plus Console configuration for interactive users; that identity path has been validated end to end. AWS, Google Cloud, and self-hosted environments are marked not validated until a real deployment passes the corresponding Logline Enterprise verification. - Azure / Entra: https://prologline.com/enterprise/setup/azure/ - Amazon Web Services: https://prologline.com/enterprise/setup/aws/ - Google Cloud: https://prologline.com/enterprise/setup/gcp/ - Self-hosted / other: https://prologline.com/enterprise/setup/self-hosted/ # FILE: enterprise/ENTERPRISE_RUNTIME_AND_LICENSING.md # Logline Enterprise: Runtime and Licensing Concepts This is user-facing conceptual guidance for AI retrieval. It is not an executable deployment manifest, a cloud setup specification, an API contract, or a substitute for the environment-specific deployment guides. ## Separation of responsibilities The hosted Logline platform provides Workbench authoring, interactive exploration and documentation. Logline Enterprise runs automated evaluations in customer-controlled infrastructure and can operate without a customer-hosted Workbench. The Enterprise API/control plane performs authorized admission, licensing checks, scheduling, persistence, recovery and report delivery. Execution workers run compiler/Engine/import adapters for assigned evaluations. The Console is a browser client over the protected API, not a separate execution authority. The reusable language and Engine are independent of the commercial licensing subsystem. A Logline program describes expected log behavior; it never controls the equipment being observed. ## Operational objects - **Program Bundle:** An immutable, versioned set of one or more `.lgl` programs and trusted derived analysis for executable publication. - **Run Profile:** Reusable execution policy identifying one Program Bundle and optional delivery configuration, independently of a particular input package. - **Source Package Manifest:** The producer's declaration of completed inputs, companion artifacts and the Run Profile to evaluate. It is the completion/admission trigger, not an instruction to embed credentials in program source. - **Run / Work Package:** A validated, frozen execution request whose source, policy and temporal mapping can be reproduced or diagnosed. - **Result, Report and Evidence:** Authoritative retained outcomes and provenance. Optional downstream delivery does not rewrite an already committed execution outcome. Do not invent concrete JSON fields, cloud resource identifiers, Run Manifest examples, API payloads, secret values or support guarantees from these descriptions. Consult the current versioned product contracts and deployment guide for such details. ## Source processing and time A Run may reference multiple source logs and decoder/companion artifacts. Source-native clocks must be interpreted and mapped to the Canonical Timeline Epoch (CTE) before the Engine consumes a deterministic merged record stream. Exact alignment and source order are part of reproducibility. Matching-looking events are not sufficient evidence to fabricate a clock offset. A runtime cannot safely admit unresolved included sources merely because source records are present. ## Deployment and access boundaries Enterprise is designed with provider-neutral core behavior and environment-specific deployment adapters. Docker is a local reference/evaluation environment; Azure has a documented reference and bounded infrastructure/identity validation; AWS, GCP and other installations must not be claimed production validated without corresponding acceptance evidence. The documented supported control topology uses one active control plane/scheduler for a shared PostgreSQL deployment authority and independently scalable workers, not an implied active-active scheduler cluster. Customer identity, API authorization, infrastructure permissions and license entitlement are distinct checks. A valid license never authenticates a user or authorizes data access. ## Offline signed licensing A logical Enterprise deployment has one durable Deployment ID and shared PostgreSQL control state. Its initial full-feature trial lasts **90 days** and permits **up to 20 concurrent logical evaluations**. Queued work does not itself consume logical-evaluation capacity. Paid licenses are signed offline, bound to the Deployment ID, and uploaded by an authorized administrator. The runtime verifies entitlements locally using provisioned vendor public verification keys; it makes no mandatory vendor license-service call, and no private signing key is shipped to customers. An expired or invalid paid entitlement never automatically reinstates trial rights. Existing reports/evidence remain accessible subject to authorization, and already-running evaluations are intended to finish safely. Do not promise an unrestricted grace period or specific commercial terms solely from this knowledge summary; authoritative licensing decisions and contract terms are governed separately. A single deployment's multiple browsers and workers share a license; independent installations require their own deployment-bound license files. ## Capability status and reliable answers The Enterprise API, Console, licensing enforcement and deployment adapters are implemented in source, but implementation is **not** proof of fully accepted or generally released customer deployment bundles. Describe environment-specific validation as scoped, and refer users to the current Enterprise setup and release-status pages for actual supported availability. Do not promise AWS/GCP readiness, active-active scheduling, arbitrary unlimited concurrency, installation phone-home, or unsupported Run Manifest fields. Public guides: - Enterprise overview: https://prologline.com/enterprise - Release and capability status: https://prologline.com/releases - Setup guide selector: https://prologline.com/enterprise/setup/ - Azure setup: https://prologline.com/enterprise/setup/azure/ - Licensing model: https://prologline.com/enterprise/licensing # FILE: workbench/WORKBENCH_WORKFLOWS.md # Logline Workbench: Authoring, Evidence, and Contextual Assistance This document describes user-visible Workbench capabilities. It is knowledge for user guidance, not an assistant API schema or permission to mutate a program. ## Interactive workflow A user can create or open a plain-text `.lgl` program; work with the Text, Structure, and Visual representations; import one or more log sources; configure source interpretation and synchronization; include selected sources in execution; then run, debug, and inspect reports. The ordinary Run/Debug/Report workflow evaluates canonical Execution Records. An editor representation or AI explanation is not independent execution authority. Log sources are retained independently. Raw records are source-local. Execution Records are the validated, included, deterministic merged canonical stream and are the basis of ordinary execution. Log Processing Configuration must be applied before its draft changes affect the executable record stream. Included relative sources without a defensible exact temporal mapping cannot be executed; do not suggest automatic event-matching or invented offsets. ## Semantic selection and the Inspector Workbench selection is shared across authoring representations and Inspector context. The Text editor can resolve a cursor location within a validated source revision to a semantic scenario, segment, collector, or structured branch. Supported segment forms include transition, event, group, repeat, parallel, and crossroads, including nested constructs. The nearest supported semantic construct is selected; placing a cursor does not edit the source or recompile it. If the source changed after its validated outline, the old outline must not be treated as an authoritative selection for the new text. ## Contextual AI assistance The dedicated `/logline/ai` page is for platform-wide questions such as Logline concepts, Enterprise setup, integrations, and Run Manifest concepts. The embedded Workbench AI panel is for authoring and investigating the current program, selection, diagnostics and logs. These experiences maintain separate conversations; their live AI answers depend on the external AI service and should not be described as locally verified when that service is unavailable. The Workbench can prepare editable questions about a selected construct or selected diagnostic. Preparation is not automatic submission. The assistant must not infer selection from an unrelated cursor or stale validated source. It must not claim that a drafted question has been answered by the model. ## Compiler-authoritative authoring AI-proposed Logline code is untrusted until the current compiler verifies it. The Workbench can review a suggested complete program, display real diagnostics, and prepare an editable repair question based on the proposed source and compiler feedback. Creating a reviewed program requires explicit user approval and an eligible empty Workbench draft; it must not overwrite an existing program or apply an answer directly. The Workbench also supports explicit preview of a validated proposed program against the currently available canonical Execution Records using a separate Engine session. The current local preview guard is **10,000 records**; larger inputs are rejected for this preview rather than silently truncated. Previewing does not replace the active program, debugger, Run or authoritative report. Preview outcomes are evidence for review, not approval to mutate user source. Some structured edit proposals may be previewed and applied through bounded, validated Workbench operations. Do not imply that arbitrary multi-operation plans, arbitrary DSL rewrites, or any text supplied by a model can be applied without supported operation checks and user approval. ## Diagnostics, execution, and reports Compiler diagnostics address source validity. Execution failures or inconclusive results arise from evidence and candidate semantics even for valid source. The Inspector and Debugger reflect Workbench selection and engine-derived evidence. A user asking why a transition failed should be guided toward the selected condition, relevant record values, attempts, candidates, diagnostics, and report evidence, without inventing unobserved logs or claiming that a live AI reply was validated. ## Source authorities and verification boundary The Logline grammar/compiler/Engine, canonical record composition, and actual Workbench controls are authoritative for behavior. The source corpus's example programs and fixture expectations are narrower than a universal guarantee about all customer logs. The Workbench feature source and regression tests were reviewed at repository commit `e2d3b2f1`; live AI service integration and broader cross-environment acceptance remain separate checks. # FILE: metadata/CAPABILITY_AND_SOURCE_BOUNDARIES.md # Knowledge Source Boundaries and Evidence Hierarchy This pack describes the current Logline language and product concepts using reviewed repository source and maintained documentation. It must not be used to infer capabilities or security guarantees absent from the referenced implementation and accepted verification. ## Evidence priority 1. Current grammar, validation, compiler and Engine behavior determine accepted syntax and runtime semantics. 2. Exact, validated example programs and paired fixtures demonstrate their stated cases, not all possible inputs. 3. Workbench and Enterprise source together with tests establish the existence of implemented controls and contracts. 4. Product documentation explains intended user workflows and deployment requirements; requirements/design documents alone do not establish shipped behavior. 5. AI-generated prose, recommendations and example snippets are hypotheses until checked against current authoritative source and data. ## Distinguish these statuses - **Documented / designed:** requirement, architecture, or intended behavior; not proof of implementation. - **Implemented:** represented in current source; may still require environment-specific validation. - **Verified:** explicitly tested or accepted for a stated scope; never broaden the scope without evidence. - **Released / publicly available:** tied to actual publication or live service availability, not to a successful local build alone. For all operational questions, identify what information the user must supply (for example source clock meaning, authority, deployment environment and actual manifest contract) instead of fabricating missing values. Never assume a public AI service response has been verified simply because the Workbench can prepare a request. ## Privacy and security A `.lgl` file is declarative source, not a script for running system commands. Do not include credentials, customer logs, proprietary identifiers, individual usage information, signing keys, sensitive deployment configurations or authenticated customer API responses in public-facing examples. An assistant knowledge corpus and a customer Enterprise runtime are different trust domains. Public crawler access to this pack is not permission to collect customers' source or logs. ## Corpus identity Repository source reviewed: `e2d3b2f1`. The repository may evolve after this review; future updates should regenerate the pack and revalidate examples. The published mirror and aggregate text resources must be generated from the maintained `docs/ai-assistant/source-pack/` directory rather than edited separately.