Back to index

Release Readiness

Table
Generates documents
Release Readiness

Seen as a design

Take it with you

Copy and paste, or save a file and hand it over. For a machine with no network, one “Everything” file is enough.

Everything

release-readiness-everything.md

Everything in this panel, including the contents behind each URL, in one Markdown file

Prompt

1.4 KB
Build an HTML document with "Release Readiness". This layout runs, so there is no composition to rebuild — what it needs is content.

## What this layout does
Release Readiness with explicit source values and reading conditions.

## What you have to supply
- Provide the source values, labels and decision conditions described by the schema.

## The shape of the input
- `title` — string — 結論を伝える見出し
- `subtitle` — string? — 出典・時点・母集団や仮定
- `release` — string — 対象リリース
- `checks` — array (label, status, required, evidence, owner) — 判定項目、結果、必須フラグ、証拠、責任者

schema.ts holds the machine-checkable validation. Ask rather than guess when an input is missing.

## When not to use it
- Do not compare values with incompatible units, populations, or assumptions.

## How to build it
Put the input in a JSON file and run:

```bash
node scripts/render.mjs release-readiness <input.json> --theme ink -o out.html
```

The output is one self-contained file and fetches nothing at render time.

## The source
- https://design-vault.pages.dev/designs/release-readiness/source/template.tsx
- https://design-vault.pages.dev/designs/release-readiness/source/schema.ts
- https://design-vault.pages.dev/designs/release-readiness/source/sample-data.json
- https://design-vault.pages.dev/designs/release-readiness/sample.html

Files

Template, input schema, sample data and metadata. This document was generated from those four. The generated document

template.tsx

7.0 KB

/designs/release-readiness/source/template.tsx

Show contents
import type { ReactNode } from "react";
import type { Props } from "./schema";
function Ledger({heads,rows,caption}:{heads:string[];rows:ReactNode[][];caption?:string}) { return <table className="ledger">{caption && <caption>{caption}</caption>}<thead><tr>{heads.map((h,i)=><th key={i} scope="col">{h}</th>)}</tr></thead><tbody>{rows.map((r,i)=><tr key={i}>{r.map((v,j)=><td key={j} data-label={heads[j]}>{v}</td>)}</tr>)}</tbody></table>; }
function Notes({children}:{children:ReactNode}) { return <details><summary>データ・判断条件を確認</summary>{children}</details>; }

const CSS = String.raw`
.asset{font-family:var(--font-sans);color:var(--color-primary);background:var(--color-surface);max-width:var(--container-slide);margin:auto;padding:3rem 2rem;line-height:1.6;font-size:var(--text-body-sm)}
.asset *{box-sizing:border-box}.asset header{margin-bottom:2rem}.asset .eyebrow{font-family:var(--font-mono);font-size:var(--text-label);letter-spacing:.08em;color:var(--color-secondary);margin-bottom:.75rem}.asset h1{font-size:var(--text-h1);font-weight:700;line-height:1.35;letter-spacing:-.025em;max-width:32em}.asset h2{font-size:var(--text-h3);font-weight:600;margin-bottom:.75rem}.asset h3{font-size:var(--text-body-md);font-weight:600}.asset .subtitle,.asset .muted{color:var(--color-secondary)}.asset .subtitle{margin-top:.75rem}.asset .number{font-variant-numeric:tabular-nums;font-family:var(--font-mono)}.asset .hero-number{font-size:var(--text-display);line-height:1.2;font-weight:700;letter-spacing:-.04em}.asset .callout{border-left:.25rem solid var(--color-tertiary);padding:1rem 1.5rem;background:var(--color-surface-subtle);margin-bottom:1.5rem}.asset .grid2{display:grid;grid-template-columns:1fr 1fr;gap:1.5rem}.asset .grid3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1.5rem}.asset .panel{padding:1.5rem;background:var(--color-surface-subtle);border-radius:var(--radius-md);min-width:0}.asset .rule{border-top:1px solid var(--color-outline);padding-top:1rem;margin-top:1rem}.asset .pill{display:inline-block;padding:.25rem .75rem;border:1px solid var(--color-outline);border-radius:var(--radius-full);font-size:var(--text-label)}.asset .focus{background:var(--color-tertiary-container);color:var(--color-on-tertiary-container)}.asset .dark{background:var(--color-primary);color:var(--color-on-primary)}.asset .dark .muted{color:var(--color-on-primary-container)}.asset .row{display:grid;grid-template-columns:12rem minmax(0,1fr) 6rem;gap:1rem;align-items:center;padding:.75rem 0;border-bottom:1px solid var(--color-outline)}.asset .row>*{min-width:0}.asset .track{height:1rem;position:relative;background:var(--color-neutral);border-radius:var(--radius-sm)}.asset .bar{height:100%;background:var(--color-tertiary);border-radius:var(--radius-sm)}.asset .track.tall{height:2rem}.asset .flex{display:flex;gap:1rem;align-items:center;justify-content:space-between;flex-wrap:wrap}.asset .stack>*+*{margin-top:1rem}.asset ul{list-style:disc;padding-left:1.25rem}.asset li+li{margin-top:.5rem}.asset .plot{display:block;width:100%;height:auto;overflow:visible}.asset .plot text{font-family:var(--font-sans);font-size:14px;fill:var(--color-secondary)}.asset .plot .ink{fill:var(--color-primary)}.asset .plot .axis{stroke:var(--color-outline);stroke-width:1}.asset .plot .accent{stroke:var(--color-tertiary);fill:none;stroke-width:3}.asset .legend{display:flex;gap:1.5rem;flex-wrap:wrap;font-size:var(--text-label);margin-bottom:1rem}.asset .legend b{display:inline-block;width:.75rem;height:.75rem;margin-right:.5rem}.asset .ledger{border-collapse:collapse;width:100%;font-variant-numeric:tabular-nums}.asset .ledger caption{text-align:left;font-weight:600;margin:1rem 0}.asset .ledger th{font-weight:600;color:var(--color-secondary);text-align:left}.asset .ledger th,.asset .ledger td{padding:.75rem 1rem;border-bottom:1px solid var(--color-outline);vertical-align:top;overflow-wrap:anywhere}.asset .ledger th:first-child,.asset .ledger td:first-child{padding-left:0}.asset .ledger th:last-child,.asset .ledger td:last-child{padding-right:0}.asset .ledger tbody tr:hover{background:var(--color-surface-subtle)}.asset details{border-top:1px solid var(--color-outline);margin-top:1.5rem;padding-top:1rem}.asset summary{cursor:pointer;color:var(--color-secondary);padding:.5rem 0;min-height:2.75rem}.asset summary:focus-visible{outline:2px solid var(--color-tertiary);outline-offset:.25rem}.asset .small{font-size:var(--text-label)}.asset .mobile-only{display:none}.asset .horizontal-list{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1rem}.asset .board-column{border-top:.25rem solid var(--color-primary);padding-top:1rem;min-width:0}.asset .board-item{padding:1rem 0;border-bottom:1px solid var(--color-outline)}.asset .board-item p{margin-top:.5rem}.asset .statement{font-size:var(--text-h2);line-height:1.5;font-weight:600}.asset .meta-line{margin-top:.75rem;font-size:var(--text-label);color:var(--color-secondary)}.asset pre{white-space:pre-wrap;overflow-wrap:anywhere}.asset footer{margin-top:2rem;font-size:var(--text-label);color:var(--color-secondary)}
@media(max-width:640px){.asset{padding:1.5rem 1rem}.asset h1{font-size:var(--text-h2)}.asset header{margin-bottom:1.5rem}.asset .grid2,.asset .grid3,.asset .horizontal-list{grid-template-columns:1fr}.asset .row{grid-template-columns:minmax(0,1fr) 5rem;gap:.5rem}.asset .row>:first-child{grid-column:1/-1}.asset .desktop-only{display:none!important}.asset .mobile-only{display:block}.asset .panel{padding:1rem}.asset .ledger,.asset .ledger tbody,.asset .ledger tr,.asset .ledger td{display:block}.asset .ledger thead{display:none}.asset .ledger tr{padding:.75rem 0;border-bottom:1px solid var(--color-outline)}.asset .ledger td{display:grid;grid-template-columns:7rem minmax(0,1fr);gap:.75rem;border:0;padding:.25rem 0!important}.asset .ledger td:before{content:attr(data-label);color:var(--color-secondary);font-size:var(--text-label)}.asset .hero-number{font-size:var(--text-h1)}}
@media print{.asset{max-width:none;padding:1rem}.asset details>*{display:block}.asset summary{display:none}}
`;

export default function Template(d: Props) {
const blocked=d.checks.filter(c=>c.required&&c.status!=="pass");const names={pass:"確認済み",fail:"不合格",pending:"未確認"};
return <section className="asset asset-release-readiness"><style>{CSS}</style><header><p className="eyebrow">RELEASE READINESS</p><h1>{d.title}</h1>{d.subtitle && <p className="subtitle">{d.subtitle}</p>}</header>
<div className="callout"><span>{d.release}</span><p className="statement">{blocked.length?"判断保留 · 必須条件 "+blocked.length+"件が未充足":"必須条件は充足 · 責任者による最終判断へ"}</p></div><Ledger heads={["項目","必須","結果","証拠","責任者"]} rows={d.checks.map(c=>[c.label,c.required?"必須":"任意",names[c.status],c.evidence,c.owner])}/><Notes><p>この表は承認を代行しません。未確認と不合格を分け、証拠を確認して責任者が判断します。</p></Notes>
<footer>必須の未確認・不合格を満たされた条件として扱わない。</footer></section>;
}

schema.ts

691 B

/designs/release-readiness/source/schema.ts

Show contents
import { z } from "zod";
const text = z.string().trim().min(1).max(160);
const short = z.string().trim().min(1).max(48);
const value = z.number().finite();
const positive = value.positive();

export const schema = z.object({
  title: text.describe("結論を伝える見出し"),
  subtitle: text.optional().describe("出典・時点・母集団や仮定"),
  release:short.describe("対象リリース"),
  checks:z.array(z.object({label:short,status:z.enum(["pass","fail","pending"]),required:z.boolean(),evidence:text,owner:short}).strict()).min(3).max(10).describe("判定項目、結果、必須フラグ、証拠、責任者"),
}).strict();
export type Props = z.infer<typeof schema>;

meta.yaml

1.3 KB

/designs/release-readiness/source/meta.yaml

Show contents
id: release-readiness
name:
  ja: リリース判定チェック
  en: Release Readiness
purpose:
  ja: 判定項目の必須条件と証拠を揃え、出荷判断の未解決点を読む。
  en: Release Readiness with explicit source values and reading conditions.
status: published
still: ./still.png
category: operations
catalogOrder: 550
jobs:
  - assign-governance
useCases:
  - process
layoutKinds:
  - table
tags:
  - release-readiness
  - operations
  - offline
  - responsive
whenToUse:
  - ja: 判定項目の必須条件と証拠を揃え、出荷判断の未解決点を読む。
    en: Use to communicate release readiness.
avoidWhen:
  - ja: 同じ条件・単位で比較できないデータには使わない
    en: Do not compare values with incompatible units, populations, or assumptions.
requiredInputs:
  - ja: 必須の未確認・不合格を満たされた条件として扱わない。
    en: Provide the source values, labels and decision conditions described by the schema.
relatedLayouts:
  - fit-gap-assessment
  - action-register
dataSchema:
  title: string — 結論を伝える見出し
  subtitle: string? — 出典・時点・母集団や仮定
  release: string — 対象リリース
  checks: array (label, status, required, evidence, owner) — 判定項目、結果、必須フラグ、証拠、責任者
sources: []

sample-data.json

881 B

/designs/release-readiness/source/sample-data.json

Show contents
{
  "title": "必須条件が1件未確認、出荷判断を保留する",
  "subtitle": "架空サンプル|レイアウトの使用例",
  "release": "受付機能 v1.4",
  "checks": [
    {
      "label": "受入試験",
      "status": "pass",
      "required": true,
      "evidence": "主要30ケースを完了",
      "owner": "業務担当"
    },
    {
      "label": "移行手順",
      "status": "pending",
      "required": true,
      "evidence": "最終リハーサル待ち",
      "owner": "移行担当"
    },
    {
      "label": "監視設定",
      "status": "pass",
      "required": true,
      "evidence": "通知受信を確認",
      "owner": "運用担当"
    },
    {
      "label": "ヘルプ記事",
      "status": "pass",
      "required": false,
      "evidence": "文面レビュー済み",
      "owner": "サポート担当"
    }
  ]
}