feat(layer-101): Content Verification System#26
Draft
slavazeph-coder wants to merge 8 commits into
Draft
Conversation
…, humanity score Implements ECDSA P-256 in-browser signing with a hash-linked chain of edit steps (lite C2PA), plus a heuristic humanity score so creators can tell whether a draft reads polished or unmistakably human. Inspired by the IG post on cryptographic provenance for content in the AI era. - contentProvenance.js: ensureIdentity / signContent / appendEdit / verifyManifest / humanityScore. SubtleCrypto-backed, FNV fallback for display-only environments. Manifest schema brainsnn-prov/1. - ContentProvenancePanel.jsx: Sign / Verify / Humanity / Log tabs. Identity card with handle + fingerprint. Manifest copy-to-clipboard. Smoke-tested: legitimate verify passes, tampered payload caught, 2-step chain verifies end-to-end, prevHash tamper caught.
…re modes
Cannibalized the loop pattern from context-labs/halo (not its Python code):
the harness watches itself via OpenTelemetry-shaped spans, clusters them
into named failure modes, and emits a structured fix-report a coding
agent can act on.
- telemetry.js: unified span buffer (cap 500). OTel schema with
trace_id/span_id/parent_span_id/name/kind/status/attributes/events.
Ring buffer + debounced localStorage mirror + pub/sub subscribers
+ withSpan() helper.
- harnessLift.js: generalizes Layer 27's n-gram lift miner into a
pure mineLift({ records, features, isPositive }) primitive +
mineSpansByOutcome() OTel-aware wrapper.
- harnessFailureModes.js: codifies The Brain's HALO-equivalent
failure-mode taxonomy — error-burst, slow-scan, hung-mcp,
dead-patterns, fp-heavy, refusal-loop. runDiagnostic() emits a
harness-report-v1 envelope; renderReportText() flattens for
paste-into-coding-agent.
- cognitiveFirewall.scoreContent() instrumented: emits a
firewall.scan span on every call (lang, ruleset, pressure,
evidence count, template count, text length). First instrumented
call site; the rest of the harness wires up incrementally.
- HarnessDiagnosticPanel: live-reads spans via subscribe(), shows
the report tier, per-finding hints, top operations p50, lift
candidates. Copy-as-text and copy-as-JSON for handoff.
Smoke-tested: 16-span fixture surfaces error-burst + slow-scan +
dead-patterns at CRITICAL tier; 5-span healthy fixture shows 0
findings. Build succeeds; +13 kB to main chunk.
… tools
Closes the HALO-style autonomous loop: agents can now pull the harness
report and a candidate rule diff over the existing Layer 19 bridge.
- mcpBridge.handleToolCall(): every tool dispatch emits an mcp.tool
span (ok/error) with tool name + arg keys.
- brainSteward.runTick(): each tick is now a steward.tick span with
per-phase events (anomaly, narration) and propagates error status.
- harnessProposer.js: pure function turning a harness-report-v1 into
rule-diff-v1 — additions[] derived from error-correlated lift
candidates classified by manipulation vocabulary (urgency / outrage
/ fear / certainty), followUps[] mapping findings to next-layer
actions (L31 evolve, L61 diagnostic, L66 coverage, L19 inspect,
L21 pause).
- Two new MCP tools: get_harness_report({ format }) and
propose_rule_diff({ topK }). Claude Code / Codex can now run the
loop autonomously over the existing JSON-RPC bridge.
Smoke-tested: lift miner correctly identifies error-correlated phrases,
proposer emits a `\\bact\\s+now\\s+urgent\\b` urgency rule, followUps
include L21 pause-steward on error-burst.
…e + Replay
Four-layer stretch on top of the Layer 102 telemetry foundation,
closing the HALO loop end-to-end with operator feedback + before/after
measurement + scrubbable replay.
- Layer 103 — Auto-Apply Rule Steward
autoSteward.js: poll runDiagnostic + proposeRuleDiff, filter to
low-risk additions (lift / length / quota gates), apply via
Layer 55 addCustomRule. Default dryRun + paused. Each cycle emits
an auto-steward.cycle span. Reversible from the applied log.
- Layer 104 — Harness Comparator
harnessComparator.js: compareReports → harness-diff-v1 envelope
with findings split into added/removed/shifted, aggregates ranked
by errorRate delta, tier shift labelled improved/regressed/unchanged.
Snapshot store cap 20 in localStorage.
- Layer 105 — Span Annotation
spanAnnotation.js: annotate({ spanId, label, note }) with five
standard labels (false-positive / false-negative / real-bug /
benign / investigate). decorateSpansWithAnnotations folds labels
into attributes._annotation so the lift miner picks them up. New
detector detectAnnotatedFalsePositives surfaces operator-flagged
FPs as a first-class finding.
- Layer 106 — Trace Replay
traceReplay.js: buildFrames buckets the buffer chronologically,
rollForward computes cumulative per-name totals up to a cursor.
Panel: scrubber, play/pause/step/reset, current-frame inspector,
cumulative ladder.
Smoke-tested: 12-span healthy baseline → 2 false-positive annotations
→ re-diagnosis goes warn with new annotated-fp finding → comparator
labels REGRESSED with findings.added containing annotated-fp →
replay builds 12 frames across 56s window. Build clean, +27 kB to
main chunk. All four panels registered in App.jsx + layerCatalog.
Four more on top of Layer 102. Closes the HALO observability stack: spans now have a path to a real collector, PII gets redacted on the way out, the operator gets toasted when the tier shifts, and the tour mirrors actual usage instead of static role steps. - Layer 107 — OTLP HTTP Exporter otlpExporter.js maps the internal span schema → OTel ResourceSpans (hex-padded ids, ms→ns, typeAttrValue, kind enum, status code). Optional auth header, configurable service.name, dry-run for local inspection. Always pipes through Layer 108 sanitizer before egress. - Layer 108 — Telemetry Sanitizer telemetrySanitizer.js: 6 standard PII patterns (email / phone / IPv4 / SSN-like / credit-card / bearer-token) + custom regex with compile validation. sanitizeSpan walks attributes, event attrs, status.message. piiAuditSummary nudges users when the buffer contains PII. - Layer 109 — Harness Alerts harnessAlerts.js: subscribes to telemetry, debounces 4s, runs the diagnostic, toasts new findings (severity-tinted) and tier shifts (red on regression / info on recovery). Off by default. - Layer 110 — Trace-Driven Tour traceDrivenTour.js: deriveTour reads aggregate-by-name buckets, walks a 7-step recipe library whose `when` predicates check the usage context, emits a tour-v1 envelope. Replaces Layer 94's static role tour with one derived from what you actually do. Smoke: PII audit catches email + 2× phone + IPv4 in seeded spans. OTLP payload assembles 9 spans with correct OTel envelope. Tour produces 3 steps reflecting "scan-heavy + steward usage". Build clean, +21 kB to main chunk.
… MCP Usage Round 3 on top of Layer 102. Power-user observability + a fix for a small telemetry bug found while smoke-testing. - Layer 111 — Span Distribution spanDistribution.js: log-scale 9-bucket duration histogram + p50/p90/p95/p99 per span name. Catches the slow tail outliers that aggregate p50/p95 alone hide. - Layer 112 — Trace Search traceSearch.js: parseQuery tokenizes a mini DSL — `name=foo status=error duration>200`. Operators =/!=/>/</>=/<=, bare words become free-text matches over name + JSON-stringified attrs. - Layer 113 — Diagnostic Snapshots diagnosticSnapshots.js: subscribes to telemetry, debounces, calls Layer 104 saveSnapshot whenever the harness tier changes. Keeps a longitudinal timeline so "when did we go critical?" has a real answer. Auto-snaps tagged for clean prune. - Layer 114 — MCP Tool Usage mcpToolUsage.js: cross-references BRAIN_TOOLS against mcp.tool spans. Hot (top by count) / Slow (top by p95) / Flaky (top by errorRate) / Dead (registered, never called). MCP-side cousin of Layer 102's dead-pattern detector. Bug fix: telemetry.recordSpan was only computing duration_ms when end_time was auto-filled, leaving callers who set end_time explicitly with null durations. Distribution + search rely on it. Smoke: 20-span fixture with 4 slow scans → distribution histogram [15 ≤10ms, 5 ≤500ms, p95=350ms]. Search query `name=firewall.scan duration>100` returns exactly the 5 slow ones. MCP usage groups scan_content×4 / get_brain_state×4 with correct error count + p95.
The IG post argues simple beats overwhelming. App.jsx was rendering 167
panels in one scroll column. Now there's a two-tab top bar:
- Home : just the 3D brain + scenario metrics + a single quick-action
card pointing at the firewall and the Layer Explorer.
- All : current behavior, every panel.
Power-user navigation already exists (⌘K command palette · Layer
Explorer · Role Tour · Trace-Driven Tour). Home mode persists in
localStorage so the first-paint stays clean across reloads.
Surgical change: just the conditional `{viewMode === 'all' && (<>…</>)}`
wrap around the existing panel column, plus two tiny inline components
(ViewModeTabs, HomeQuickActions) and ~50 lines of CSS. No panels moved,
no panels deleted.
…scan
The Home view was a static "go to All" card. Now it does the most
common thing in-place: paste text, click Quick scan, see pressure
tier + templates. No navigation needed.
Adds two focused workflows to the existing Home / All split:
- Scan : CognitiveFirewall + Coverage + Tone Shifter + Context
Memory + Scan Archive + Content Provenance — paste,
score, see which pattern fired, archive, sign.
- Diagnose : Layer 102–114 stack — diagnostic, alerts, auto-steward,
comparator, snapshots, distribution, search, MCP usage,
annotation, replay, OTLP exporter, sanitizer.
Each focused deck renders existing panel components inline; only one
viewMode mounts at a time so there's no double-render. The All tab
stays the escape hatch for the 110+ panel surface.
HomeDeck additions: inline scan textarea + Quick scan button →
shows manipulation pressure tier (Calm / Tilted / High pressure)
with template chips and recommended action. Immunity score +
streak as a side card. Quick-jump buttons to focused workflows.
Bundle: CSS +0.3 kB, JS +3 kB. Build clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Layer 101 implements the chain-of-custody / humanity-signaling idea from the referenced Instagram post — flawless AI imagery is cheap, so the durable competitive edge is verifiable provenance + visible humanity.
Two pieces, both fully in-browser:
contentProvenance.js— ECDSA P-256 keypair via Web Crypto, persisted locally.signContent()issues abrainsnn-prov/1manifest carrying the pub key + handle + an ordered chain of signed steps.appendEdit()chains a new edit step whoseprevHashreferences the previous step's hash (lite-C2PA).verifyManifest()walks every step, re-derives its hash, verifies the signature, checksprevHashlinkage, and confirms the latest payload hash matches. Plus ahumanityScore()heuristic across cadence variance / candid markers / contractions / irregularities / AI boilerplate.ContentProvenancePanel.jsx— Sign / Verify / Humanity / Log tabs. Identity card with handle + fingerprint, manifest copy-to-clipboard, recent-manifest log.Wired into
App.jsxand registered inlayerCatalog.js. Notes added toMEMORY.md.Test plan
npm run build— succeeds, no new warningspayload-tamperedprevHashtamper rejected withchain-brokenNotes
localStorage— exportable via Layer 57 (Data Portability) once the bundle export picks up the new keyssubtle-unavailableon non-HTTPS hosts so the Humanity tab still works in those environmentsGenerated by Claude Code