PROTEUS docs
v0.1.0 Jeremy Hall

Appendix

Every workload type, fault kind, guard policy, AWS limit, environment variable and CLI flag, in one place.

Reference tables that would clutter a chapter. Everything here was generated from the live registries or read from the code, not typed out by hand.

The workload and fault tables came from:

from proteus.web.catalog_view import build_catalog
catalog = build_catalog()
len(catalog["archetypes"]), len(catalog["profiles"]), len(catalog["faults"])
# (12, 56, 14)

That is the same call the GUI palette makes, so these tables and the palette cannot disagree.

Workload types#

68 in total, from two layers.

Archetypes — 12#

Hand-written, with bespoke internal behavior: a Kafka consumer's lag responds to its producer's rate, a noisy neighbor hurts its victim more than itself. The metrics count is measured, not declared — each generator is asked for representative ticks and the distinct metric names are counted. Same for signals: an archetype claims a signal only if its generator really yielded a record for it.

Archetypes publish into the custom namespace proteus/{model-name} and carry their AWS counterpart in attributes. The AWS namespaces column lists the namespaces their metrics are mapped onto, where a mapping is confirmed.

Kind Label AWS namespaces mapped Metrics Signals
alb ALB — (custom namespace only) 16 metrics, traces, logs
nginx-web Nginx Web — (custom namespace only) 7 metrics, traces, logs
app-service App Service — (custom namespace only) 19 metrics, traces, logs
lambda Lambda — (custom namespace only) 11 metrics, traces, logs
rds-postgres RDS Postgres — (custom namespace only) 15 metrics, traces, logs
elasticache Elasticache — (custom namespace only) 10 metrics, traces, logs
kafka Kafka — (custom namespace only) 11 metrics, traces, logs
opensearch Opensearch — (custom namespace only) 10 metrics, traces, logs
eks-workload EKS Workload ContainerInsights 28 metrics, traces, logs
ecs-workload ECS Workload AWS/ECS, ECS/ContainerInsights 29 metrics, traces, logs
bedrock-agent Bedrock Agent AWS/Bedrock, AWS/Bedrock/Guardrails 17 metrics, traces, logs
browser-rum Browser RUM — (custom namespace only) 7 metrics, rum

180 distinct metric names across the twelve, of which 45 carry a confirmed AWS counterpart through proteus.aws_metric and proteus.aws_namespace attributes.

browser-rum is the only archetype that emits RUM and the only one that does not emit traces. It is also the only one whose runtime is browser.

A thirteenth archetype, custom, exists in the schema but is not a workload — it is the delegation mechanism that renders whichever profile a service's kind names. It is deliberately absent from the palette, because probing it with no kind yields a tile with no metrics and no signals, which looks broken.

Profiles — 56#

Declarative. Each covers one distinct AWS namespace, and adding an AWS service is a data edit rather than new code. 393 metric specifications across the 56.

20 of the 393 specs name no AWS counterpart. That null is load-bearing, not an oversight: an invented AWS metric name reads as authoritative and sends an operator hunting an alarm that cannot exist. Null means "no confirmed counterpart", never "not looked up yet". Where a profile has unmapped specs, the count is noted below.

Kind Label AWS namespace Metrics
apigateway-api API Gateway REST API AWS/ApiGateway 7
apprunner-service App Runner service AWS/AppRunner 8
appsync-api AppSync GraphQL API AWS/AppSync 5
athena-workgroup Athena workgroup AWS/Athena 6
aurora-cluster Aurora Cluster AWS/RDS 10
autoscaling-group Auto Scaling group AWS/AutoScaling 6
backup-vault AWS Backup vault AWS/Backup 5
batch-queue AWS Batch job queue AWS/Batch 6 (6 unmapped)
beanstalk-environment Elastic Beanstalk environment AWS/ElasticBeanstalk 9
bedrock-model Bedrock model invocation AWS/Bedrock 8
clb Classic Load Balancer AWS/ELB 8
clientvpn-endpoint Client VPN endpoint AWS/ClientVPN 6
cloudfront-distribution CloudFront distribution AWS/CloudFront 9
cognito-userpool Cognito user pool AWS/Cognito 7
connect-instance Amazon Connect instance AWS/Connect 7
directconnect-connection Direct Connect connection AWS/DX 7
documentdb-cluster DocumentDB Cluster AWS/DocDB 9
dynamodb-table DynamoDB Table AWS/DynamoDB 11
ebs-volume-standalone EBS volume AWS/EBS 8
ec2-instance EC2 instance AWS/EC2 14
efs-filesystem EFS File System AWS/EFS 7
emr-cluster EMR cluster AWS/ElasticMapReduce 10
eventbridge-bus EventBridge bus AWS/Events 6
fargate-task Fargate task ECS/ContainerInsights 9
firehose-stream Firehose delivery stream AWS/Firehose 5
fsx-filesystem FSx File System AWS/FSx 6
globalaccelerator Global Accelerator AWS/GlobalAccelerator 5
glue-job Glue job Glue 7
keyspaces-table Keyspaces Table AWS/Cassandra 6
kinesis-stream Kinesis data stream AWS/Kinesis 6
kms-key KMS key AWS/KMS 3 (2 unmapped)
lambda-provisioned Lambda provisioned concurrency AWS/Lambda 5
lightsail-instance Lightsail instance AWS/Lightsail 6
mediaconvert-queue MediaConvert queue AWS/MediaConvert 5
memorydb-cluster MemoryDB Cluster AWS/MemoryDB 8 (1 unmapped)
mq-broker Amazon MQ broker AWS/AmazonMQ 8
mwaa-environment MWAA environment AWS/MWAA 8 (2 unmapped)
nat-gateway NAT gateway AWS/NATGateway 8
neptune-cluster Neptune Cluster AWS/Neptune 7 (1 unmapped)
nlb Network Load Balancer AWS/NetworkELB 9 (1 unmapped)
redshift-cluster Redshift Cluster AWS/Redshift 10
route53-healthcheck Route 53 health check AWS/Route53 6
s3-bucket S3 Bucket AWS/S3 11
sagemaker-endpoint SageMaker endpoint AWS/SageMaker 12
secretsmanager Secrets Manager AWS/SecretsManager 3 (2 unmapped)
shield-protection Shield Advanced protection AWS/DDoSProtection 4
sns-topic SNS topic AWS/SNS 5 (1 unmapped)
sqs-queue SQS queue AWS/SQS 8 (1 unmapped)
ssm-managed-instance SSM managed instance AWS/SSM-RunCommand 3
stepfunctions-statemachine Step Functions state machine AWS/States 7
synthetics-canary CloudWatch Synthetics canary CloudWatchSynthetics 7
timestream-database Timestream Database AWS/Timestream 6 (1 unmapped)
transit-gateway Transit Gateway AWS/TransitGateway 7
vpc-endpoint VPC endpoint (PrivateLink) AWS/PrivateLinkEndpoints 5
vpn-connection Site-to-Site VPN connection AWS/VPN 3
waf-webacl WAF web ACL AWS/WAFV2 6 (2 unmapped)

Note The namespace column is what the metric stands in for, carried as an attribute. Proteus never publishes into any of these — a namespace beginning AWS/ is reserved and every request to it is rejected. See the reserved-prefix rule.

Runtimes and infra kinds#

Six runtimes: eks, ecs, ec2, lambda, managed, browser.

Eight infra kinds — the shared resources faults can contend over:

Kind Capacity keys in the default estate
load-balancer lcu
rds-instance iops, max_connections, mem_gib, storage_gib, vcpu
cache-cluster mem_gib, nodes, vcpu
kafka-cluster mem_gib, nodes, partitions, vcpu
opensearch-domain mem_gib, nodes, shards, storage_gib, vcpu
eks-nodegroup mem_gib, nodes, vcpu
ecs-cluster mem_gib, vcpu
ebs-volume iops, storage_gib

Fault kinds#

14, each with a severity in 0..1 and a time window. All compose through a single FaultEffect seam, so a fault does not need to know which archetype it lands on. Faults ramp rather than step, and reach other services by contention through shared infrastructure - not along depends_on. See the deep dive on faults.

Targets is the drop-target class the GUI palette enforces.

Kind What it does Targets Tunable params
cpu-saturation CPU pinned near 100%: latency degrades superlinearly, with throttling in the logs. service cpu_add, latency_mult, error_rate_add
oom-kill Memory exceeds the limit, pods are OOM-killed and restart; traffic dips in bursts. service mem_add, restarts_per_min, rps_mult, pulse_period_s
disk-full The volume fills and writes fail with ENOSPC. service disk_used_add, error_rate_add
slow-query A query plan regresses: latency only, with flat CPU and flat errors. service latency_mult, statement
connection-pool-exhaustion All pool connections are checked out: callers queue, then time out waiting. service pool_size, latency_mult, error_rate_add
thread-pool-rejection The work queue is full: errors dominate while latency barely moves. service error_rate_add, latency_mult
queue-depth Consumers fall behind: lag and queue depth climb, latency rises moderately, errors flat. service lag_msgs, depth_msgs, latency_mult
cache-stampede Cache hit ratio collapses and the miss storm multiplies downstream load. service cache_hit_mult, downstream_rps_mult, latency_mult
shard-hotspot Load skews onto one shard: it runs hot and rejects work from a full queue. service latency_mult, cpu_add, error_rate_add, shard
dependency-timeout A downstream call hangs to its timeout ceiling, then errors. service timeout_ms, error_rate_add, max_latency_mult, target_dependency
network-packet-loss Packets drop; retries stretch latency and leak a moderate error rate. service packet_loss_add, latency_mult, error_rate_add
noisy-neighbor A co-tenant saturates shared infrastructure; victims slow with no local cause. infra aggressor_tenant, cpu_add, latency_mult, error_rate_add, aggressor_cpu_add, aggressor_latency_mult
page-load-latency Front-end page loads slow sharply with a flat error rate. service latency_mult, rps_mult
agent-quality-regression Agent answer quality drops while latency, errors, CPU and tokens stay healthy. service eval_score_mult

noisy-neighbor is the only infra-targeted kind. Aimed at a service it has no aggressor and is deliberately inert, so the palette will not offer it as a service drop target. Its two aggressor_* parameters are what make it asymmetric — the aggressor's CPU climbs while the victim's latency doubles — because a symmetric version is not findable, and finding it is the exercise.

Two pairs are deliberately hard to tell apart without reading more than one signal: slow-query is latency with flat CPU and flat errors, while thread-pool-rejection is errors with barely-moved latency. agent-quality-regression is the hardest of all, because every conventional signal stays healthy.

Guard policies#

Five. Set with --guard; the default is estimate-confirm.

Policy Allowed Confirmation Sends Network Notes
estimate-confirm yes required yes yes The default. Shows the projection, requires an explicit yes.
budget-ceiling only under the cap required yes yes Refuses if the monthly ledger total plus this run exceeds --cap.
warn-only yes none yes yes Prints the projection and proceeds.
paranoid yes none no none Renders and costs everything, sends nothing, makes no network call at all.
unlimited yes none yes yes No spend check. Prints a banner saying so.

--cap defaults to $50 and applies to budget-ceiling only. --dry-run on seed, live or firehose forces paranoid.

paranoid also disables the live pricing lookup and falls back to the built-in rate table. That is not an oversight: the projection runs before the guard can refuse anything, so a cold or stale pricing cache under paranoid would make an outbound AWS call before anything had a chance to stop it. A slightly staler cost figure buys a promise that actually holds.

Two policies print a banner, because both are surprising in opposite directions:

PARANOID GUARD: telemetry will be rendered and costed but NOTHING will be sent to AWS.
UNLIMITED GUARD: every projected record will be sent to AWS with no spend check and
no confirmation. You are responsible for the bill.

AWS ingestion limits#

Endpoints are HTTP only, no gRPC. OTLP 1.x, binary or JSON, gzip or none.

Signal Endpoint SigV4 service Notes
metrics https://monitoring.{region}.amazonaws.com/v1/metrics monitoring —
logs https://logs.{region}.amazonaws.com/v1/logs logs Requires x-aws-log-group and x-aws-log-stream headers
traces https://xray.{region}.amazonaws.com/v1/traces xray Needs Transaction Search with destination CloudWatchLogs, or every request is rejected
RUM https://dataplane.rum.{region}.amazonaws.com/appmonitors/{id}/ rum Needs a real app monitor id, from the stack outputs

Per-request limits:

metrics logs traces RUM
Max records 1,000 datapoints 10,000 events 10,000 spans no published cap
Max uncompressed 5 MB 1 MB (20 MB in some regions) 5 MB no published cap
Max time gap per request — 24 h 24 h —
Earliest timestamp −14 d −14 d −14 d —
Latest timestamp +10 min +2 h +2 h —
TPS per account/region 500 5,000 — —

The 1,000-datapoint metrics cap is the tightest constraint in the system, and the +10-minute metrics future window is the tightest of the three. Proteus uses the tightest of each so one window is safe for every signal: −14 d to +10 min.

What Proteus actually batches at, deliberately under each ceiling:

metrics logs traces RUM
Records per request 1,000 10,000 10,000 200
Bytes per request 4,000,000 800,000 4,000,000 256,000
Hours per request — 23 23 —

Logs are capped at 1 MB in most regions and 20 MB in a handful — us-east-1, us-west-2, eu-west-1 "and others". Because the full list is not documented, the conservative 1 MB is used everywhere; the record cap binds first anyway.

Other limits that shaped the code:

  • Metrics: 150 labels max per datapoint, 1,024 characters max per attribute value, 40 KB max metadata per series, 1M new series per 10-minute window.
  • Traces: 200 KB max single span, 16 KB max per unique resource+scope.
  • Logs: 1 MB max single event.
  • CloudFormation: 51,200 bytes inline template, 1,000,000 bytes via S3.

The reserved AWS/ prefix#

You cannot publish to a namespace beginning AWS/. It is reserved and the request is rejected. ContainerInsights and ECS/ContainerInsights are reserved too.

So synthetic metrics go to the custom namespace proteus/{model-name} and carry their AWS counterpart in two attributes:

Attribute Holds
proteus.aws_metric The metric an operator would normally alarm on
proteus.aws_namespace The namespace it would normally live in

That lets the GUI say "this stands for pod_cpu_utilization_over_pod_limit in ContainerInsights" without ever writing into a reserved namespace. The rule is enforced in code — a profile spec whose name begins AWS/ raises at render — and asserted by the test suite against rendered records.

Environment variables#

Three are read by the tool. All are resolved at call time, never captured into a module-level constant, so a test or a side-by-side estate can isolate itself.

Variable Read by Default Effect
PROTEUS_HOME world model store, pricing cache, spend ledger, hunt ledger, GUI layout ~/.proteus The state directory. Point it elsewhere to keep several estates side by side.
PROTEUS_REGION every command's --region default falls back to AWS_REGION, then us-west-2 The default region for both the boto3 session and the OTLP endpoints.
PROTEUS_MODEL chat and hunt a cross-region inference profile The Bedrock model id or inference profile to use.

AWS_REGION is consulted as a fallback for PROTEUS_REGION. Standard AWS credential variables and AWS_PROFILE work as usual, since credentials are resolved by boto3 — --profile is the explicit override.

Note PROTEUS_VERSION is not an environment variable, despite appearing in the code. It is a constant resolved from installed package metadata, surfaced as the stack's ProteusVersion output and as a resource tag. Setting it in your shell does nothing.

proteus about prints the resolved state directory and region, which is the fastest way to find out that PROTEUS_HOME is set somewhere you forgot about.

State directory#

Contents of $PROTEUS_HOME (default ~/.proteus):

Path Holds
world.json The current world model
world.<timestamp>.bak.json Automatic backups, written before any overwrite
layout.json Canvas node positions from the GUI
pricing-{region}.json Cached AWS Pricing API rate card, one per region, 24-hour freshness
spend.json The budget-ceiling monthly spend ledger, in estimated dollars
hunts/ Sealed hunt answers and guess history

Warning Nothing in this directory belongs in git. It holds your sealed hunt answers, so committing it gives away every exercise. teardown does not touch it — delete it yourself for a genuinely clean machine.

CLI surface#

18 top-level commands. Every flag below was read from --help on this build.

Command What it does Touches AWS
doctor Check prerequisites and whether an existing deployment is still live. read-only
plan Build a world model from a preset and write it to disk. no
bootstrap Deploy the CloudFormation stack the synthetic telemetry depends on. writes
teardown Delete the stack. Shows exactly what will go first. deletes
seed Backfill history so the console is populated before you present. sends telemetry
live Stream telemetry with current timestamps while you narrate. sends telemetry
firehose Push data as fast as the quotas allow, to watch it arrive live. sends telemetry
serve Start the web GUI: compose the estate, drag faults, watch the cost, inject. only when you press inject
about Show the banner, version and where state lives. no
show Print the current estate: services, dependencies, infra and active faults. no
faults List the fault kinds this build can inject. no
import-cfn Build a world model from your own CloudFormation template. no
import-live Clone a real AWS account into a world model: topology plus observed baselines. read-only, and bills for GetMetricData
rename Rename services or infra nodes by pattern, rewriting every reference. no
chat Edit the estate in plain language. The AI edits the model, never the data. Bedrock only
hunt Hunt the injected fault. Four subcommands. Bedrock only
docs Build and preview the documentation site. no
site Assemble the product website and documentation. no

docs and site build this documentation rather than any telemetry. They are listed because they appear in proteus --help, and a surface table that omits a command a reader can see is worse than no table.

Shared options#

--model <path> (world model path) appears on doctor, plan, import-cfn, import-live, bootstrap, teardown, seed, live, firehose, serve, show, chat and hunt start. It is absent from rename, which reads and writes the default model path only.

--profile <str> (AWS profile) appears on every command that needs credentials: doctor, bootstrap, teardown, seed, live, firehose, serve, chat, hunt start, hunt guess, import-live. It is absent from import-cfn, which is the flag-level consequence of that command making no AWS call at all.

--region <str> appears on the same set plus plan, import-cfn and import-live. Default is PROTEUS_REGION → AWS_REGION → us-west-2.

--stack <str> (stack name override) appears on doctor, bootstrap, teardown, seed, live and firehose. Without it, the name is proteus-{model-name}.

Per-command options#

proteus doctor

Option Type Default Meaning
--days int 14 Backfill horizon the checks should assume.

proteus plan

Option Type Default Meaning
--preset str northwind-rx One of ai-chatbot, alb-fleet, minimal, ml-pipeline, northwind-rx, three-tier, web-server. Shapes and counts: The seven presets.
--seed int 1337 RNG seed; identical seeds give identical data.
--force / --no-force flag no-force Overwrite an existing world model.

proteus rename {selector} {pattern}

Offline. Both arguments are required. Renames services by default, infra nodes with --infra, and rewrites every reference to the old name as it goes.

Option Type Default Meaning
--infra flag off Rename infrastructure nodes instead of services.
--seed int the model's own seed Seed for # and {rand} placeholders.
--start int 1 First value for a counter placeholder.
--dry-run flag off Print the plan and change nothing.
--yes flag off Apply without confirming.

Name patterns#

The {pattern} argument. Two grammars, equivalent where they overlap — webserver00 is webserver{n:02}, and cache-## is cache-{rand:2}.

Form Example Result
zero run webserver00 webserver01, webserver02, …
zero run web-000 web-001, web-002, …
# run cache-## two random digits
{n} web-{n} web-1, web-2, …
{n:02} web-{n:02} web-01, web-02, …
{rand:2} cache-{rand:2} two random digits
{1..12} web-{1..12} web-1 … web-12, exactly 12 names
{01..12} web-{01..12} web-01 … web-12; a padded bound pads the output
{lit:00} web-{lit:00}-{n} web-00-1, web-00-2, …
escape web-\0\0 literal web-00

The counter rule, exactly: a maximal run of digits is a counter if and only if it consists entirely of zeros and is two or more characters long.

Read that as written rather than as a rule about what precedes the zeros, because the two readings differ in one case and agree everywhere a reader would think to check:

Pattern Digit run Result The lookbehind misreading gives
svc-100 100 literal svc-100 literal — agrees
port-8080 8080 literal port-8080 literal — agrees
web-0010 0010 literal web-0010 web-0110 — wrong

web-0010 is the only case that separates them: the rule looks at the whole run 0010, which is not entirely zeros, so nothing in it is a placeholder. A single 0 is likewise literal, so web0 and s3-bucket-0 keep their names. To put a counter after a digit, write it explicitly: svc-1{n:02} gives svc-101, svc-102, …

A pattern may hold one counter. web-00-shard-00 is refused, in either spelling, because two counters could reasonably move together, nest, or count independently. Ranges are exempt — they carry their own values, so web-{1..3}b{1..3} yields web-1b1, web-2b2, web-3b3.

Random placeholders seed from the model's own seed unless --seed overrides it, so a rename is reproducible from the world model alone.

Selectors#

The {selector} argument, matched against existing names.

Form Example Matches
glob web* web, webs, web-tier, webserver01
glob ? exactly one character
regex /^api-\d+$/ api-1, api-42; not api-x or xapi-1

Globs are full matches, so web* does not match myweb-tier — use *web*. Every other character is literal: web.server matches only web.server, and [abc] is three literal characters rather than a character class. Regexes are wrapped in slashes and matched with re.fullmatch, which makes ^ and $ redundant but harmless. ** is an alias for * and nothing more — service names are flat, with no separator to cross, so web**.server and web*.server select the same names. Zero matches is an empty result rather than an error.

proteus import-cfn <template>

Makes no AWS call. The template argument is required and is never modified.

Option Type Default Meaning
--name str the template's file name Estate name.
--seed int 1337 RNG seed; identical seeds give identical data.
--include str — Expand a nested stack: LogicalId=path/to/child.yaml. Repeatable. LogicalId/ChildId for a grandchild.
--force / --no-force flag no-force Overwrite an existing world model.
--strict flag off Exit non-zero if any resource type could not be mapped. For CI.
--dry-run flag off Print the report and write nothing.

proteus import-live

Reads a real account. Read-only — only Describe, List and Get, enforced by a client wrapper that raises before boto3 sees the call. GetMetricData is the only billed call. See the walkthrough for the limitation that is not visible in its output.

Option Type Default Meaning
--days float 14.0 How far back to read CloudWatch for the baselines.
--services str all Comma-separated subset to probe. Anything not probed is absent from the replica and reported as such.
--name str live-<account>-<region> Estate name.
--seed int 1337 RNG seed; identical seeds give identical data.
--force / --no-force flag no-force Overwrite an existing world model.
--discover-only flag off Stop after discovery. Requests no metric data, so it costs nothing and every baseline is an archetype default.
--no-census flag off Skip the tagging-API census and probe every selected service regardless. Slower, and the only way to reach a resource the tagging API does not return.
--strict flag off Exit non-zero if anything could not be mapped or replicated. For CI.
--dry-run flag off Print the report and write no world model.
--yes flag off Answer both cost disclosures. Read them first.

proteus bootstrap

Option Type Default Meaning
--log-retention-days int 14 Must be at least the backfill horizon or backdated logs are dropped.
--seed-days float 14.0 Backfill horizon you intend to seed. Synthesis refuses if retention is shorter.
--print flag off Print the template, deploy nothing.

proteus teardown

Option Type Default Meaning
--yes flag off Skip the confirmation prompt.

proteus seed

Option Type Default Meaning
--days float 14.0 How far back to backfill (max 14).
--interval float 60.0 Sampling interval in seconds.
--guard policy estimate-confirm Cost guard policy.
--cap float 50.0 Monthly cap in USD for budget-ceiling.
--dry-run flag off Render and size, send nothing. Forces paranoid.
--yes flag off Skip the confirmation prompt.

proteus live

Option Type Default Meaning
--minutes float 30.0 How long to stream before stopping.
--interval float 60.0 Sampling interval in seconds.
--tick float 30.0 Seconds between send cycles.
--guard policy estimate-confirm Cost guard policy.
--cap float 50.0 Monthly cap in USD for budget-ceiling.
--dry-run flag off Render and size, send nothing.
--yes flag off Skip the confirmation prompt.

proteus firehose — the same options as live with denser defaults: --minutes 10.0, --interval 10.0, --tick 10.0.

proteus serve

Option Type Default Meaning
--port int 8787 Port to listen on, bound to 127.0.0.1 only.
--open-browser / --no-open-browser flag open-browser Open the default browser on start.

proteus chat takes an optional positional message. Omit it for a REPL; a blank line exits.

proteus hunt has four subcommands:

Subcommand Arguments Options
start — --difficulty (easy/medium/hard, default medium), --region, --profile, --model
guess <hunt-id> <answer...> (both required) --region, --profile
reveal <hunt-id> (required) — (offline)
list — — (offline)

proteus show, proteus faults and proteus about take no options beyond --model on show.

Glossary#

Estate. The modeled distributed system as a whole: its services, their dependencies, the infrastructure they share, and the tenants that share it. What proteus show prints.

World model. The estate as data — a single JSON document at $PROTEUS_HOME/world.json, defined by proteus/model/schema.py. It is the only thing chat and hunt ever edit. Everything downstream is derived from it plus a seed, which is what makes runs reproducible. Carries a revision and a fingerprint, and the deployed stack records the fingerprint it was built from.

Archetype. One of the 12 hand-written workload types, with bespoke internal logic. A Kafka consumer's lag responds to its producer's rate because the archetype knows about both.

Profile. One of the 56 declarative workload types, each covering one AWS namespace. A profile declares its metrics rather than computing them, so adding an AWS service is a data edit. Reached through the custom archetype.

Tenant. A logical customer sharing infrastructure with other tenants. What makes noisy-neighbor possible: one tenant's aggression is another's unexplained latency. Rendered as node color on the GUI canvas.

Fault. An injected failure: one of the 14 kinds, aimed at a service or an infra node, with a severity in 0..1 and a start and end time. Ramps rather than steps. Reaches other services through shared infrastructure, not along depends_on.

Effect. The FaultEffect seam through which a fault reaches a workload. A fault composes effects — a latency multiplier, a CPU addend, an error-rate addend — so it does not need to know which archetype it lands on. Frozen contract; see Faults.

Tick. One instant of rendering for one service: a timestamp, an interval, the service, the model, the composed fault effect, and a seeded RNG. Generators receive ticks and yield records.

Window. A start, an end, and a sampling interval. Every render takes one. Clamped to the ingestible range, −14 d to +10 min.

Signal. One of the four telemetry types: metrics, logs, traces, rum. Each has its own endpoint, its own per-request caps, and its own emitter.

Record. A signal-neutral intermediate — MetricPoint, LogRecord, SpanRecord, RumEvent. The renderer produces records; emitters translate records into wire calls. This split is what makes faults testable without reading a console.

Seed. The RNG seed on the world model, default 1337. Same model plus same seed plus same window gives byte-identical telemetry.

seed (the command). Backfill: telemetry with backdated timestamps, up to 14 days, so the console is populated before you present. Not to be confused with the RNG seed above.

live. Stream telemetry with current timestamps, in cycles, while you narrate.

firehose. live with a much denser interval, to watch data arrive. Self-throttles below the account TPS ceilings so the run slows rather than collecting HTTP 429s.

Hunt. A fault-finding exercise. hunt start injects a hidden fault and seals the answer; you find it in CloudWatch Omni; hunt guess grades you on root cause, affected service and time window. The answer is withheld from show, from chat, from hunt list, and from the grader's own hint until you score 70 overall.

Guard. The cost policy that gates every injection. Five policies; all injecting commands go through one code path, so no mode can skip it.

Projection. The pre-flight estimate: record counts per signal, uncompressed wire bytes, request count, new metric series, and a dollar figure at list price. Deliberately pessimistic.

Proteus is MIT-licensed. Built by Jeremy Hall.

Synthetic telemetry for CloudWatch Omni. Everything it emits is fabricated; nothing in it describes a real system.