com um clique
markout
Markout serializer grounding (fixture). Use for Markout output questions.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Menu
Markout serializer grounding (fixture). Use for Markout output questions.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Baseado na classificação ocupacional SOC
| name | markout |
| description | Markout serializer grounding (fixture). Use for Markout output questions. |
GROUNDING-CANARY: CANARY-CLAUDE-SKILL
Source-generated serializer. Default output is Markdown. Package Markout (includes the
source generator; no extra package needed).
using Markout;
// 1. Annotate every model type. List<T> -> table, scalar -> field.
[MarkoutSerializable(TitleProperty = nameof(Title))] // TitleProperty -> the H1 heading
public class Report
{
public string Title { get; set; } = "";
public int Count { get; set; }
[MarkoutSection(Name = "Items")] // -> "## Items" heading
public List<Row>? Items { get; set; } // List<T> -> a table
}
[MarkoutSerializable]
public class Row { public string Name { get; set; } = ""; public string Value { get; set; } = ""; }
// 2. Register EVERY type on a partial context (the source generator fills it in).
[MarkoutContext(typeof(Report))]
[MarkoutContext(typeof(Row))]
public partial class ReportContext : MarkoutSerializerContext { }
// 3. Serialize THROUGH the context.
MarkoutSerializer.Serialize(report, Console.Out, ReportContext.Default);
Serialize(obj) overload. EVERY MarkoutSerializer.Serialize
overload takes a MarkoutSerializerContext (or MarkoutTypeInfo<T>). Skipping the context does
not compile. This is the #1 mistake.[MarkoutSerializable] +
[MarkoutContext(typeof(T))] will not serialize. The context class MUST be partial.[MarkoutSerializable] (not
[JsonSerializable]), [MarkoutContext], [MarkoutSection(Name=...)], TitleProperty,
[MarkoutPropertyName], [MarkoutIgnore]. Do not use Json* attributes.List<T> -> table; scalar (string/int/bool) ->
a Field | Value row; [MarkoutSection(Name="X")] -> a ## X heading above the property.[MarkoutIgnoreInTable] on non-tabular list properties (List<Metric>, List<Breakdown>,
List<TreeNode>, List<Description>, Callout) or they get mistreated as table columns.Metric (bar chart), Breakdown/Slice (stacked bar), Callout (alert), TreeNode
(hierarchy), Description (term + text), CodeSection (code block). e.g. new Metric("Build", 4.2).
Pass children as a list/array/collection expression, never as trailing arguments:
new TreeNode("root", [new TreeNode("leaf")]). Badge is an optional property:
new TreeNode("root") { Badge = "📁" }.
Composite cells are data-only scalar properties: FieldLayout.Table renders a dense Markdown
value, and TableFormatter (TSV/JSONL) decomposes each into typed columns from one declaration.
Change<V> — a before → after change (NOT Comparison, which collides with System.Comparison<T>).
[MarkoutDelta(Delta.Percent)] on a numeric Change<V> appends the signed change, e.g.
98555 → 61190 (−38%); Delta.Absolute appends the signed difference; Delta.Multiple appends a
multiplicative factor with a direction word, e.g. 15 → 5 (3× fewer) / 5 → 15 (3× more) (a zero
endpoint renders —). With a goal, an aligned Delta.Multiple word omits the redundant status word
(15 → 5 (3× fewer) under Goal.Lower); a conflicting one keeps it (5 → 15 (3× more, bad)).
[MarkoutDeltaNoun("solved")] renders a caller noun on the signed delta —
4/6 → 6/6 (+2 solved) (sibling of [MarkoutUnit]; composites use IDeltaCountable: Fraction→count,
Share→value; Markdown-only).
[MarkoutGoal(Goal.Higher)] / [MarkoutGoal(Goal.Lower)] on a numeric Change<V> makes Markout
derive two decomposed fields — a structural direction
(increased/decreased/introduced (0→N)/resolved (N→0)/unchanged) and a goal-applied polarity
status (good/bad/neutral) — instead of the caller hand-coding ceiling/floor/drift. Optional
noise, [MarkoutGoal(Goal.Higher, 0.001)], treats sub-threshold movement as unchanged. Goal.Context
(default) derives nothing. Composite Change<Share|Percent|Fraction> also derive direction/status
from a single comparable magnitude (Share → raw Value; Percent/Fraction → their ratio;
Segments → the sum of its parts' values, i.e. the breakdown total). In dense Markdown the polarity word
renders inline, merged with any delta suffix into one group: 0 → 7 (bad), 98555 → 61190 (−38%, good).Fraction(count, total) → 24/24; Share(value, whole) → 5056 (24%)
([MarkoutUnit("s")] → 103s (93%)); Percent(part, whole) → 93%;
Segments(new Segment(label, value), ...) → 21/171/236 (labels become column names).Change<V> nests over composites: Change<Fraction>, Change<Share>, Change<Segments>.
A zero denominator renders — rather than NaN/Inf. e.g.
[MarkoutPropertyName("Session IET"), MarkoutDelta(Delta.Percent)] public Change<long> SessionIet { get; init; }.JSONL decomposition is heterogeneous (each record holds only its own keys); TSV keeps a uniform
column union (absent cells blank). Set MarkoutWriterOptions.JsonTypedValues = true to emit numeric
columns as JSON numbers instead of strings.
When a composite cell (Change<V>, etc.) is a column of an element table (List<T> where T has a
composite property), structured formatters (TSV/JSONL) decompose it into typed {column}_{sub} columns
— score_before/score_after/score_delta_pct, bugs_direction/bugs_status, tasks_delta_count/
tasks_delta_noun — so the card is reconstructable from the data. Markdown keeps the dense cell
(100 → 50 (-50%)). Scalar columns and Markdown are unchanged. [MarkoutIgnoreColumnWhen] columns that
are hidden for the table are dropped from the decomposed output too.
Two list-shapes render as multi-format cards from a [MarkoutSerializable] model — Markdown table +
flat typed JSONL/TSV — with no imperative writer calls:
List<MetricChange<T>> — a gated scalar metric per row. MetricChange<T>(Name, Before, After, Target? = null, TargetLabel? = null, Status = GateStatus.Unknown, StatusLabel? = null) where
T : struct. Set { Goal = Goal.Higher|Lower } (init property; optionally Noise) to derive the
direction/status axes from Before → After; a caller-supplied Status overrides the derived
polarity. Dense Markdown (default): Metric | Change | Target with the status word inlined
(0 → 7 (bad) — caller StatusLabel wins over the slug) and a goal marker on the label
(Failures (-) / Fully raised (+)); the Status column is dropped. Set
MarkoutWriterOptions.InlineGoalStatus = false for the legacy Metric | Change | Target | Status.
JSONL/TSV are unaffected: flat before/after/optional target/target_label/direction/status.
T must be a numeric scalar (int/long/double/decimal/...); a composite T (e.g. Segments) is a
compile error (MARKOUT005).[MarkoutSection(Name = "...", IncludeSectionInStructuredRows = true)] on a List<MetricChange<T>>
or List<MultiSourceRow> section prepends a leading section column (the section name) to TSV/JSONL
rows — for multiplexing several sectioned card shapes into one structured stream. Markdown is unchanged.List<MultiSourceRow> — a role matrix: MultiSourceRow(label, params Source[]),
Source(role, IMarkoutCell? value, format = default). Roles pivot to columns in Markdown
(caller-supplied order; absent role → -); JSONL emits one flat record per row with
{role}_{side}_{field} keys. Values are any IMarkoutCell incl. nested Change<Share> etc.;
scalars work too — new Source("baseline", 2) (int/long/double/decimal) and Source.Text(role, s)
decompose to a single {role} field; new Source(role, null) is an absent cell. Set the label column
header with [MarkoutLabelHeader("Metric")] (defaults to Field).Verdict(GateStatus Status, string? Label = null) — a first-class verdict cell (typed polarity
GateStatus + optional caller label); use as a Source value for a verdict row (decomposes to {role}).Decomposition keys are snake_case_lower (a fused role like claude-opus-4.8 becomes
claude_opus_4_8_...). Put [MarkoutIgnoreInTable] on these lists only when nested inside a table.
Pass a formatter to change output: new MarkdownFormatter() (default), PlainTextFormatter,
UnicodeFormatter, TableFormatter (compact/TSV/JSONL via MarkoutWriterOptions.TableMode).
e.g. MarkoutSerializer.Serialize(report, Console.Out, new TableFormatter(), ReportContext.Default);