本文へ移動
cccskills
無料GitHub で公開

redact-visualization-for-disclosure

Redact rendered visual artifacts — Mermaid diagrams, SVGs, and HTML dashboards — before public disclosure, using an ordered longest-first mapping table (specific label, then namespace label, then catch-all placeholder) that swaps sensitive identifiers for descriptive stand-ins while preserving structure, node ids, and teaching value. Covers whole-word identifier replacement, node-label-vs-node-id discrimination, re-rendering the derived image from the redacted source, and verifying the result through the redaction gate. Use when a diagram or dashboard built from internal findings must ship to a public mirror without leaking the names behind it.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md11.9 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Redact Visualization for Disclosure

A diagram leaks differently than prose: the sensitive names sit in node labels, tooltip text, and embedded <text> nodes, while the shape of the graph is exactly the generalizable insight worth publishing. This skill redacts the labels and keeps the structure — replacing each internal identifier with a descriptive stand-in through an ordered mapping table, re-rendering the image from the redacted source, and then asserting over both that no mapped identifier survives.

When to Use

  • Publishing an architecture/flow diagram (Mermaid .mmd, rendered .svg) built from internal findings
  • Shipping an HTML dashboard whose cells/tooltips name internal flags, functions, or endpoints
  • Promoting an investigation visualization into a public guide while keeping the named internals private
  • Re-deriving a public image after the private source diagram changed (redaction must re-run, not be hand-patched)

Inputs

  • Required: The source visual artifact (.mmd, .svg, .html) in the private repo
  • Required: A mapping table — sensitive identifier → descriptive stand-in. enforce-redaction-gate Step 1 covers how to derive the shapes it should cover
  • Optional: The render toolchain (e.g. a Mermaid CLI) to regenerate the image from the redacted source
  • Optional: A target path in the public mirror for the redacted output

Procedure

Step 1: Separate Structure from Labels

Decide, per artifact, what carries the leak and what carries the insight. In every diagram format the structure (which node connects to which) is the shareable pattern; the labels are the sensitive part.

FormatSensitive (redact)Structural (preserve)
Mermaidnode labels, edge labels, subgraph titlesnode ids, edge directions, layout
SVG<text>, <title>, id/data-* attrspath geometry, viewBox, styles
HTMLcell text, tooltips, captionstable shape, headings, layout

The rule that prevents the most damage: redact labels, preserve ids. A Mermaid A1[acme_widget_gate] becomes A1[widget-gate] — the id A1 is structural and carries nothing; the label is the leak.

Expected: A per-format list of which token positions get rewritten and which are left untouched.

On failure: If a node id itself encodes a sensitive name (rare), treat it as a label and remap it consistently across every edge that references it.

Step 2: Build the Ordered Mapping Table

Map each sensitive identifier to a descriptive stand-in. Order matters: longest/most-specific first, so a precise label wins before a namespace label before the catch-all. Otherwise a generic prefix rewrite eats the specific case.

# Ordered tiers. Within each dict, apply longest-key-first.
SPECIFIC = {                       # exact internal name -> descriptive stand-in
    "acme_widget_autoinstall_gate": "[autoinstall-gate]",
    "acme_relay_chain_v1":          "[relay-chain-gate]",
}
NAMESPACE = {                      # family prefix -> namespace label
    "acme_widget_": "[widget-namespace]",
}
FUNCTIONS = {                      # minified identifier (whole-word) -> role name
    r"\bQ3\(\)": "resolveProvider()",
    r"\bAb\b":   "flagResolver",
}
def redact(text):
    for src in sorted(SPECIFIC,  key=len, reverse=True): text = text.replace(src, SPECIFIC[src])
    for src in sorted(NAMESPACE, key=len, reverse=True): text = text.replace(src, NAMESPACE[src])
    for pat, repl in FUNCTIONS.items():                  text = re.sub(pat, repl, text)
    text = re.sub(r"acme_[A-Za-z0-9_]+", "[feature-flag]", text)   # catch-all, last
    text = re.sub(r"\b(\w+(?:\(\))?) \1\b", r"\1", text)           # collapse "name name" pairs
    return text

Two non-obvious rules baked in above: whole-word boundaries for minified identifiers (so Ab does not match inside Abstract), and a collapse pass that removes adjacent duplicate stand-ins left when an original label paired a name with its minified twin (scheduleWakeup Y8z → both map to scheduleWakeup → collapse to one).

Expected: Every sensitive identifier in the source maps to a descriptive stand-in; the catch-all only ever fires on tokens the specific/namespace tiers missed.

On failure: If the catch-all fires often, a real identifier family is unmapped — add a specific or namespace entry rather than relying on the generic placeholder, which erases teaching value.

Step 3: Apply to the Source, Write to the Public Path

Run the mapping over the source text and write the redacted artifact to the public-mirror path. Never edit the public copy by hand — it must be a pure function of the private source so re-runs are deterministic.

# Write Step 2's table to a mapping file — one `source<TAB>replacement` pair per line, or a
# JSON object. Order does not matter in the file: the tool sorts longest-source-first, so a
# namespace prefix can never eat a more specific name.
cat > /tmp/viz-map.tsv <<'MAP'
acme_widget_autoinstall_gate	[autoinstall-gate]
acme_widget_	[widget-namespace]
MAP

python3 tools/redact-artifact.py --type mermaid --mapping /tmp/viz-map.tsv \
  docs/flow.mmd -o publish/docs/flow.mmd

For SVG/HTML pass --type html: replacements still apply to the whole text, but the verification tier additionally parses the document and asserts that no source term survives in a text node or an attribute value, reporting the position and never the content. A position is a label such as text[N] or attr:<name>[N], where N is one ordinal counted across the whole document from 1: on <div data-id="acme&#95;secret">acme&#95;secret</div>, whose character reference hides the term from the whole-text check, it reports attr:data-id[1] and text[2].

Expected: Exit 0, and the redacted artifact has identical structure to the source with descriptive stand-ins in every label position. A non-zero exit means the tool refused to hand back output it could not verify — exit 1 for a surviving term, 2 for could-not-measure (an empty mapping, an unreadable input, or markup the structure tier could not examine in full, such as an unterminated quote or tag the parser dropped). Terms that may appear in an encoding your mapping does not spell — base64, a different case — go in --also-deny, which asserts without substituting.

On failure: If a diff shows a structural change (a dropped edge, a renamed id), the mapping over-matched — scope it to label positions and re-run.

Step 4: Re-render the Derived Image

If the artifact has a rendered form (an .svg/.png generated from the .mmd), regenerate it from the redacted source. A stale rendered image is the classic leak: the source got redacted, the image did not.

mmdc -i publish/docs/flow.mmd -o publish/docs/flow.svg

Expected: The rendered image is regenerated from the redacted source and shows only stand-in labels.

On failure: If the render tool is unavailable, do not ship the old image — remove it from the publish set until it can be regenerated, and note the gap.

Step 5: Verify Through the Redaction Gate

Step 3 already verified the redacted source: redact-artifact asserts its own output before returning it, so a clean exit there is the gate for the text artifact. What Step 3 cannot cover is the RENDERED image, which a different tool produced from the redacted source — re-assert over it, because a renderer can reintroduce a label from a cache or a theme file.

# --assert-only is load-bearing. Without it the mapping SUBSTITUTES first, so a label the
# renderer reintroduced is rewritten before the assertion looks and this check cannot fail for
# the one case it exists to catch (measured: rc=0, "0 survivor(s)", over an SVG containing the
# private label). With it, the mapping's keys become deny terms and nothing is rewritten.
python3 tools/redact-artifact.py --type html --assert-only --mapping /tmp/viz-map.tsv \
  publish/docs/flow.svg || {
  echo "rendered image still leaks; re-render from the redacted source"; exit 1; }

Expected: Exit 0 on the rendered image, the redacted source having already been asserted in Step 3. A non-zero exit is the check working, and the two codes mean different things: 1 means a term survived into the render. 2 is could-not-measure (the causes Step 3 lists) and must never be reported as a leak. The || branch above says "still leaks", so treat it as covering 1 only; on 2, fix the input and re-run.

On failure: A gate hit means the mapping table is incomplete — add the missing shape to the mapping (Step 2) and the deny-list, then re-run from Step 3. Do not hand-edit the public file to silence the gate.

Validation

  • The redacted artifact has byte-identical structure to the source (only labels changed)
  • Node ids/edges are preserved; only labels/text nodes are rewritten
  • The rendered image was regenerated from the redacted source, not carried over
  • The mapping is ordered longest-first; the catch-all only fires on genuinely unmapped tokens
  • redact-artifact exits 0 on the redacted source (Step 3) and on the rendered image (Step 5)
  • The public artifact is a pure function of the private source (re-running is deterministic)

Common Pitfalls

  • Stale rendered image. Redacting the .mmd but shipping the old .svg publishes everything you just removed. Always regenerate.
  • Hand-editing the public copy. Once the public file diverges from the source mapping, the next re-run either reverts your edit or, worse, re-introduces the leak. Fix the mapping, not the output.
  • Catch-all over-reliance. Replacing every internal name with [feature-flag] strips the teaching value that justified publishing the diagram. Map families to descriptive namespaces.
  • Unscoped substring rewrite. Regexing the whole SVG/HTML can rewrite an attribute or a path id that merely contains a matching substring. Parse and scope to text nodes.
  • Wrong mapping order. Applying the namespace tier before the specific tier erases the precise stand-in. Longest/most-specific first, always.
  • Redacting ids that other edges reference. If you must remap an id, remap it everywhere it is referenced, or the graph breaks.

Related Skills

  • enforce-redaction-gate — how to build a redaction boundary for artifacts you hold the deny-list for; defines the shape vocabulary the mapping table draws on. Note it teaches building one rather than shipping one: this repository ships the post-condition half (tools/redact-artifact.py), and #853 records why a public tree gate is not possible
  • redact-for-public-disclosure — the methodology umbrella that decides what is publishable before this skill decides how to scrub the diagram
  • redact-wire-capture — the sibling transform for network/MITM captures rather than rendered artifacts
  • generate-workflow-diagram — produces the kind of Mermaid diagram this skill redacts for publication
  • annotate-source-files — upstream annotation step whose output diagrams may carry internal identifiers into the visual

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Execute structural metamorphosis using strangler fig migration, chrysalis phases, and interface preservation. Covers transformation planning, parallel running, progressive cutover, rollback design, and post-metamorphosis stabilization for system architecture evolution. Use when assess-form has classified the system as READY for transformation, when migrating from monolith to microservices, when replacing a core subsystem while dependents continue operating, or when any architectural change must be gradual rather than big-bang.

日本語の概要は準備中です。原文の説明を表示しています。

pjt222/agent-almanac372026年10月12日 更新

adaptic

無料

Master skill composing the 5-step synoptic cycle for panoramic synthesis across multiple domains. Orchestrates meditate, expand-awareness, observe, awareness, integrate-gestalt, and express-insight into a coherent process that produces unified understanding rather than sequential compromise. Use when a problem genuinely spans 3+ domains and the interactions between domains matter more than depth in any one, when sequential analysis feels like compromise rather than integration, or before major architectural decisions affecting multiple stakeholders.

日本語の概要は準備中です。原文の説明を表示しています。

pjt222/agent-almanac372026年10月12日 更新

Scaffold a new puzzle type across all 10+ pipeline integration points in jigsawR. Creates the core puzzle module, wires it into the unified pipeline (generation, positioning, rendering, adjacency), adds ggpuzzle geom/stat layers, updates DESCRIPTION and config.yml, extends the Shiny app, and creates a comprehensive test suite. Use when adding a completely new puzzle type to the package or following the 10-point integration checklist to ensure nothing is missed end-to-end.

日本語の概要は準備中です。原文の説明を表示しています。

pjt222/agent-almanac372026年10月12日 更新

Add Rcpp or RcppArmadillo integration to an R package for high-performance C++ code. Covers setup, writing C++ functions, RcppExports generation, testing compiled code, and debugging. Use when an R function is too slow and profiling confirms a bottleneck, when you need to interface with existing C/C++ libraries, or when implementing algorithms (loops, recursion, linear algebra) that benefit from compiled code.

日本語の概要は準備中です。原文の説明を表示しています。

pjt222/agent-almanac372026年10月12日 更新

aikido

無料

Practice aikido as a defensive martial art emphasizing harmony, redirection, and controlled resolution. Covers centering and grounding, ukemi (safe falling and rolling), core techniques (irimi-nage, shiho-nage, kote-gaeshi, ikkyo), blending and tai sabaki (body movement), randori (multiple attacker practice), weapons awareness, and applying principles off the mat. Use when learning a defensive martial art that prioritizes de-escalation, developing the ability to redirect aggression without causing unnecessary harm, building safe falling skills, or cultivating calm centeredness under physical pressure.

日本語の概要は準備中です。原文の説明を表示しています。

pjt222/agent-almanac372026年10月12日 更新

Analyze an arbitrary codebase to identify functions, APIs, and data sources suitable for exposure as MCP tools, producing a tool specification document. Use when planning an MCP server for an existing project, auditing a codebase before wrapping it as an AI-accessible tool surface, comparing what a codebase can do versus what is already exposed via MCP, or generating a tool spec to hand off to scaffold-mcp-server.

日本語の概要は準備中です。原文の説明を表示しています。

pjt222/agent-almanac372026年10月12日 更新

pjt222 のスキルをすべて見る

このスキルの問題を報告する