# 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.<path>`, `signals.<path>`, and `record.<path>` for structured input/current-record access.

`record.index` is the canonical merged-stream index. `record.sourceLine` is source provenance when available.
