@litfamily/litopencode 1.0.31 → 1.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/README-Ko-KR.md +6 -6
- package/README.md +6 -6
- package/TRADEMARK.md +12 -0
- package/dist/activation-primary-prompts.js +5 -1
- package/dist/activation-probe.js +1 -0
- package/dist/activation-prompt-utils.d.ts +1 -1
- package/dist/activation-reentry.d.ts +20 -0
- package/dist/activation-reentry.js +110 -1
- package/dist/activation-routing.d.ts +2 -1
- package/dist/activation-routing.js +100 -11
- package/dist/activation-workflow-prompts.d.ts +4 -0
- package/dist/activation-workflow-prompts.js +30 -0
- package/dist/activation.d.ts +1 -1
- package/dist/activation.js +44 -5
- package/dist/adhd-next.d.ts +51 -0
- package/dist/adhd-next.js +150 -0
- package/dist/agents/defaults.js +1 -1
- package/dist/cli/managed-skill-assets.d.ts +1 -1
- package/dist/cli/managed-skill-assets.js +7 -1
- package/dist/cli/native-skill-integrity.js +1 -1
- package/dist/cli.js +7 -1
- package/dist/commands.d.ts +28 -1
- package/dist/commands.js +58 -5
- package/dist/durable-plan.d.ts +5 -1
- package/dist/durable-plan.js +14 -2
- package/dist/features.d.ts +80 -1
- package/dist/features.js +105 -1
- package/dist/hooks.js +3 -0
- package/dist/ledger.js +12 -1
- package/dist/plan-scope-roots.d.ts +23 -0
- package/dist/plan-scope-roots.js +116 -0
- package/dist/restart-notice.d.ts +7 -0
- package/dist/restart-notice.js +40 -0
- package/dist/secret-shapes.js +5 -5
- package/dist/server.js +4 -0
- package/dist/session-liveness.d.ts +20 -0
- package/dist/session-liveness.js +99 -0
- package/dist/skills.d.ts +22 -1
- package/dist/skills.js +36 -0
- package/dist/start-work-typed.d.ts +34 -0
- package/dist/start-work-typed.js +167 -0
- package/dist/state.d.ts +3 -0
- package/dist/state.js +3 -0
- package/dist/tools.js +22 -2
- package/dist/tui/mission-band.d.ts +22 -1
- package/dist/tui/mission-band.js +75 -16
- package/dist/tui/mission-looks.d.ts +38 -0
- package/dist/tui/mission-looks.js +73 -0
- package/dist/tui/mission-model.d.ts +2 -0
- package/dist/tui/mission-model.js +3 -1
- package/dist/tui/mission-rainbow.d.ts +33 -0
- package/dist/tui/mission-rainbow.js +90 -0
- package/dist/tui/mission-source.d.ts +49 -0
- package/dist/tui/mission-source.js +217 -2
- package/dist/tui/mission-text.d.ts +2 -0
- package/dist/tui/mission-text.js +9 -1
- package/dist/tui/mission-threads.d.ts +58 -0
- package/dist/tui/mission-threads.js +128 -0
- package/dist/tui.js +112 -7
- package/dist/uiux-visual-catalog.js +8 -1
- package/dist/v2/events.js +3 -0
- package/dist/v2/session-hooks.js +38 -5
- package/dist/workflow-stack.d.ts +53 -0
- package/dist/workflow-stack.js +196 -0
- package/docs/assets/readme/badge-version.svg +1 -1
- package/docs/assets/skills/lit-schematic.webp +0 -0
- package/docs/reference-Ko-KR.md +48 -3
- package/docs/reference.md +54 -3
- package/package.json +1 -1
- package/skills/frontend-ui-ux/SKILL.md +3 -2
- package/skills/frontend-ui-ux/kit/components.css +414 -0
- package/skills/frontend-ui-ux/kit/fonts.json +22 -0
- package/skills/frontend-ui-ux/kit/layouts/landing.html +164 -0
- package/skills/frontend-ui-ux/kit/layouts/settings.html +114 -0
- package/skills/frontend-ui-ux/kit/layouts/workspace.html +115 -0
- package/skills/frontend-ui-ux/kit/styles/computational-brutalism.json +227 -0
- package/skills/frontend-ui-ux/kit/styles/field-notes.json +205 -0
- package/skills/frontend-ui-ux/kit/styles/graphite.json +200 -0
- package/skills/frontend-ui-ux/kit/styles/meadow.json +199 -0
- package/skills/frontend-ui-ux/kit/styles/neo-brutalism.json +222 -0
- package/skills/frontend-ui-ux/kit/ui.js +226 -0
- package/skills/frontend-ui-ux/references/brand-and-imagery.md +2 -2
- package/skills/frontend-ui-ux/references/complete-contract.md +2 -1
- package/skills/frontend-ui-ux/references/craft-floor.md +6 -2
- package/skills/frontend-ui-ux/references/default-editorial-pixel.json +3 -0
- package/skills/frontend-ui-ux/references/house-styles.md +236 -0
- package/skills/frontend-ui-ux/references/motion-guide.md +2 -2
- package/skills/frontend-ui-ux/references/production.md +3 -1
- package/skills/frontend-ui-ux/references/slop-register.md +4 -4
- package/skills/frontend-ui-ux/scripts/design-lock.mjs +400 -0
- package/skills/frontend-ui-ux/scripts/pixel-art.mjs +60 -0
- package/skills/frontend-ui-ux/scripts/probe-lock.mjs +235 -0
- package/skills/frontend-ui-ux/scripts/probe-page.mjs +34 -12
- package/skills/frontend-ui-ux/scripts/probe-static.mjs +16 -3
- package/skills/frontend-ui-ux/scripts/probe-thresholds.json +8 -2
- package/skills/frontend-ui-ux/scripts/probe.mjs +35 -7
- package/skills/lit-adhd/SKILL.md +209 -0
- package/skills/lit-adhd/references/brief-format.md +46 -0
- package/skills/lit-adhd/references/card-examples.md +103 -0
- package/skills/lit-adhd/references/status-taxonomy.md +34 -0
- package/skills/lit-adhd/scripts/rewind.mjs +933 -0
- package/skills/lit-diagram-drawer/SKILL.md +4 -3
- package/skills/lit-diagram-drawer/references/style-guide.md +20 -11
- package/skills/lit-diagram-drawer/references/type-architecture.md +3 -3
- package/skills/lit-diagram-drawer/references/type-dependency.md +1 -1
- package/skills/lit-diagram-drawer/references/type-tree.md +3 -3
- package/skills/lit-diagram-drawer/references/type-wardley.md +1 -1
- package/skills/lit-diagram-drawer/references/verifier-guide.md +1 -0
- package/skills/lit-diagram-drawer/scripts/craft-thresholds.json +1 -2
- package/skills/lit-diagram-drawer/scripts/visual-quality.mjs +1 -2
- package/skills/lit-docx/SKILL.md +2 -1
- package/skills/lit-handoff/SKILL.md +2 -0
- package/skills/lit-hijack/SKILL.md +422 -0
- package/skills/lit-hijack/references/capture-and-provenance.md +87 -0
- package/skills/lit-hijack/references/clean-room-build.md +111 -0
- package/skills/lit-hijack/references/distil-and-licence.md +100 -0
- package/skills/lit-hijack/references/gap-and-port-design.md +126 -0
- package/skills/lit-hijack/references/parity-and-report.md +110 -0
- package/skills/lit-hijack/scripts/hijack.mjs +993 -0
- package/skills/lit-plan/SKILL.md +8 -0
- package/skills/lit-pptx/SKILL.md +27 -11
- package/skills/lit-pptx/fonts/jetbrains-mono/JetBrainsMono-Bold.ttf +0 -0
- package/skills/lit-pptx/fonts/jetbrains-mono/JetBrainsMono-Regular.ttf +0 -0
- package/skills/lit-pptx/fonts/jetbrains-mono/OFL.txt +93 -0
- package/skills/lit-pptx/fonts/jetbrains-mono/SOURCE.md +17 -0
- package/skills/lit-pptx/references/density-and-fill.md +9 -3
- package/skills/lit-pptx/references/direction-step.md +21 -6
- package/skills/lit-pptx/references/examples/04-lecture-chalk-ko.md +3 -6
- package/skills/lit-pptx/references/examples/05-research-talk-paper-en.md +1 -5
- package/skills/lit-pptx/references/examples/08-reliability-keynote-night-en.md +0 -4
- package/skills/lit-pptx/references/examples/09-status-update-ledger-en.md +2 -2
- package/skills/lit-pptx/references/examples/11-forecast-review-night-ko.md +4 -7
- package/skills/lit-pptx/references/examples/13-engineering-review-computational-brutalism-ko.md +173 -0
- package/skills/lit-pptx/references/examples/14-launch-pitch-neo-brutalism-ko.md +154 -0
- package/skills/lit-pptx/references/examples/15-design-lecture-bauhaus-ko.md +139 -0
- package/skills/lit-pptx/references/examples/16-community-programme-riso-ko.md +158 -0
- package/skills/lit-pptx/references/examples/17-public-data-briefing-newsroom-ko.md +179 -0
- package/skills/lit-pptx/references/layout-families.md +65 -47
- package/skills/lit-pptx/references/title-treatments.md +83 -134
- package/skills/lit-pptx/references/tonalities/atlas.md +3 -3
- package/skills/lit-pptx/references/tonalities/bauhaus.md +140 -0
- package/skills/lit-pptx/references/tonalities/chalk.md +7 -6
- package/skills/lit-pptx/references/tonalities/computational-brutalism.md +150 -0
- package/skills/lit-pptx/references/tonalities/gazette.md +1 -1
- package/skills/lit-pptx/references/tonalities/ledger.md +1 -1
- package/skills/lit-pptx/references/tonalities/neo-brutalism.md +161 -0
- package/skills/lit-pptx/references/tonalities/newsroom.md +144 -0
- package/skills/lit-pptx/references/tonalities/night.md +1 -1
- package/skills/lit-pptx/references/tonalities/paper.md +2 -2
- package/skills/lit-pptx/references/tonalities/riso.md +137 -0
- package/skills/lit-pptx/references/tonalities/signal.md +3 -3
- package/skills/lit-pptx/references/tonalities/studio.md +7 -6
- package/skills/lit-pptx/run.mjs +2 -1
- package/skills/lit-pptx/scripts/compile-deck.js +1 -1
- package/skills/lit-pptx/scripts/craft-thresholds.json +4 -8
- package/skills/lit-pptx/scripts/craft_extras.py +56 -3
- package/skills/lit-pptx/scripts/deck_output.py +75 -90
- package/skills/lit-pptx/scripts/embed_fonts.py +13 -1
- package/skills/lit-pptx/scripts/layout_inventory.py +12 -5
- package/skills/lit-pptx/scripts/lib/grid-resolver.js +101 -110
- package/skills/lit-pptx/scripts/lib/layout-resolver.js +9 -15
- package/skills/lit-pptx/scripts/lib/render-pack.js +373 -566
- package/skills/lit-pptx/scripts/lib/slide-grid.js +104 -0
- package/skills/lit-pptx/scripts/lib/template-registry.js +57 -6
- package/skills/lit-pptx/scripts/qa_deck.py +10 -11
- package/skills/lit-pptx/scripts/render_pages.py +118 -0
- package/skills/lit-pptx/templates/tonalities/atlas/pack.yaml +1 -1
- package/skills/lit-pptx/templates/tonalities/bauhaus/pack.yaml +98 -0
- package/skills/lit-pptx/templates/tonalities/chalk/pack.yaml +1 -1
- package/skills/lit-pptx/templates/tonalities/computational-brutalism/pack.yaml +99 -0
- package/skills/lit-pptx/templates/tonalities/gazette/pack.yaml +1 -1
- package/skills/lit-pptx/templates/tonalities/ledger/pack.yaml +1 -1
- package/skills/lit-pptx/templates/tonalities/neo-brutalism/pack.yaml +107 -0
- package/skills/lit-pptx/templates/tonalities/newsroom/pack.yaml +99 -0
- package/skills/lit-pptx/templates/tonalities/night/pack.yaml +1 -1
- package/skills/lit-pptx/templates/tonalities/paper/pack.yaml +1 -1
- package/skills/lit-pptx/templates/tonalities/riso/pack.yaml +99 -0
- package/skills/lit-pptx/templates/tonalities/signal/pack.yaml +2 -2
- package/skills/lit-pptx/templates/tonalities/studio/pack.yaml +1 -1
- package/skills/lit-recap/SKILL.md +4 -0
- package/skills/lit-schematic/SKILL.md +118 -0
- package/skills/lit-schematic/examples/iso-heat-exchanger/build.mjs +38 -0
- package/skills/lit-schematic/examples/iso-heat-exchanger/scene.mjs +133 -0
- package/skills/lit-schematic/examples/journal-adsorption-rig/build.mjs +87 -0
- package/skills/lit-schematic/examples/pid-dosing-skid/build.mjs +85 -0
- package/skills/lit-schematic/references/cutaway-outputs.md +70 -0
- package/skills/lit-schematic/references/isometric-craft.md +101 -0
- package/skills/lit-schematic/references/journal-figures.md +72 -0
- package/skills/lit-schematic/references/kit-api.md +134 -0
- package/skills/lit-schematic/references/pfd-and-layout.md +53 -0
- package/skills/lit-schematic/references/pid-drafting.md +103 -0
- package/skills/lit-schematic/references/pid-symbols.md +163 -0
- package/skills/lit-schematic/references/verification.md +100 -0
- package/skills/lit-schematic/scripts/doctor.mjs +57 -0
- package/skills/lit-schematic/scripts/lib/figure.mjs +81 -0
- package/skills/lit-schematic/scripts/lib/fonts.mjs +25 -0
- package/skills/lit-schematic/scripts/lib/geom.mjs +113 -0
- package/skills/lit-schematic/scripts/lib/interactive.mjs +292 -0
- package/skills/lit-schematic/scripts/lib/isa.mjs +115 -0
- package/skills/lit-schematic/scripts/lib/iso.mjs +719 -0
- package/skills/lit-schematic/scripts/lib/legend-sheet.mjs +162 -0
- package/skills/lit-schematic/scripts/lib/pid.mjs +937 -0
- package/skills/lit-schematic/scripts/lib/png.mjs +132 -0
- package/skills/lit-schematic/scripts/lib/qa-core.mjs +658 -0
- package/skills/lit-schematic/scripts/lib/route.mjs +218 -0
- package/skills/lit-schematic/scripts/lib/sheet.mjs +890 -0
- package/skills/lit-schematic/scripts/lib/svg.mjs +82 -0
- package/skills/lit-schematic/scripts/lib/theme.mjs +115 -0
- package/skills/lit-schematic/scripts/motion.mjs +129 -0
- package/skills/lit-schematic/scripts/qa.mjs +92 -0
- package/skills/lit-schematic/scripts/render.mjs +233 -0
- package/skills/lit-schematic/scripts/scaffold.mjs +60 -0
- package/skills/lit-scientific-visualization/SKILL.md +27 -4
- package/skills/lit-typographic-motion/SKILL.md +19 -17
- package/skills/lit-typographic-motion/THIRD_PARTY_NOTICES +9 -0
- package/skills/lit-typographic-motion/engine/accents.mjs +6 -0
- package/skills/lit-typographic-motion/engine/assets.mjs +282 -0
- package/skills/lit-typographic-motion/engine/blender/runner.py +228 -0
- package/skills/lit-typographic-motion/engine/blender.mjs +126 -0
- package/skills/lit-typographic-motion/engine/board.mjs +138 -0
- package/skills/lit-typographic-motion/engine/cover/assets.mjs +11 -8
- package/skills/lit-typographic-motion/engine/cover/capture.mjs +6 -6
- package/skills/lit-typographic-motion/engine/cover/render.mjs +20 -7
- package/skills/lit-typographic-motion/engine/cover/treatment.mjs +30 -3
- package/skills/lit-typographic-motion/engine/fill.mjs +54 -0
- package/skills/lit-typographic-motion/engine/gallery.mjs +118 -0
- package/skills/lit-typographic-motion/engine/house.mjs +42 -0
- package/skills/lit-typographic-motion/engine/look.mjs +65 -8
- package/skills/lit-typographic-motion/engine/loudness.mjs +101 -0
- package/skills/lit-typographic-motion/engine/scaffold.mjs +219 -0
- package/skills/lit-typographic-motion/engine/score.mjs +594 -0
- package/skills/lit-typographic-motion/engine/sound.mjs +9 -57
- package/skills/lit-typographic-motion/engine/stage/capture.mjs +23 -9
- package/skills/lit-typographic-motion/engine/stage/clock.js +8 -2
- package/skills/lit-typographic-motion/engine/stage/cover-init.js +12 -1
- package/skills/lit-typographic-motion/engine/stage/frame-worker.mjs +15 -7
- package/skills/lit-typographic-motion/engine/stage/gate.mjs +48 -4
- package/skills/lit-typographic-motion/engine/stage/qa-page.js +16 -5
- package/skills/lit-typographic-motion/engine/stage/qa.mjs +148 -7
- package/skills/lit-typographic-motion/engine/stage/render.mjs +69 -7
- package/skills/lit-typographic-motion/engine/stage/scan.mjs +20 -1
- package/skills/lit-typographic-motion/engine/stage/stage-kit.js +85 -4
- package/skills/lit-typographic-motion/engine/stills.mjs +1 -1
- package/skills/lit-typographic-motion/engine/styles.mjs +221 -0
- package/skills/lit-typographic-motion/engine/text.mjs +1 -1
- package/skills/lit-typographic-motion/engine/treatment.mjs +190 -6
- package/skills/lit-typographic-motion/engine/vendor/three/LICENSE +21 -0
- package/skills/lit-typographic-motion/engine/vendor/three/addons/environments/RoomEnvironment.js +144 -0
- package/skills/lit-typographic-motion/engine/vendor/three/addons/geometries/RoundedBoxGeometry.js +155 -0
- package/skills/lit-typographic-motion/engine/vendor/three/three.module.js +54571 -0
- package/skills/lit-typographic-motion/gate.mjs +18 -2
- package/skills/lit-typographic-motion/probe.mjs +13 -1
- package/skills/lit-typographic-motion/recipes/hero-3d/expected.json +64 -0
- package/skills/lit-typographic-motion/recipes/hero-3d/index.html +132 -0
- package/skills/lit-typographic-motion/recipes/orbit-loop/expected.json +2 -0
- package/skills/lit-typographic-motion/recipes/painted-light/expected.json +2 -0
- package/skills/lit-typographic-motion/recipes/weight-tide/expected.json +2 -0
- package/skills/lit-typographic-motion/references/cover.md +56 -13
- package/skills/lit-typographic-motion/references/craft-loop.md +20 -7
- package/skills/lit-typographic-motion/references/depth.md +112 -0
- package/skills/lit-typographic-motion/references/runtime.md +21 -6
- package/skills/lit-typographic-motion/references/sound.md +76 -0
- package/skills/lit-typographic-motion/references/stage.md +50 -7
- package/skills/lit-typographic-motion/references/studio.md +162 -0
- package/skills/lit-typographic-motion/references/style-bibles.md +18 -0
- package/skills/lit-typographic-motion/references/treatment.md +108 -9
- package/skills/lit-typographic-motion/render.mjs +60 -3
- package/skills/lit-typographic-motion/styles/paper.json +185 -0
- package/skills/lit-typographic-motion/styles/swiss-signal.json +188 -0
- package/skills/lit-typographic-motion/styles/terminalcore.json +182 -0
- package/skills/lit-typographic-motion/styles/tidal.json +187 -0
- package/skills/litresearch/SKILL.md +2 -0
- package/skills/managed-skill-manifest.json +517 -88
- package/skills/readme-studio/SKILL.md +1 -1
- package/skills/review-work/SKILL.md +2 -0
- package/skills/start-work/SKILL.md +8 -0
- package/skills/workflow-loop/SKILL.md +4 -0
- package/tools/check-pack-payload.mjs +5 -2
- package/tools/payload-substance-parity.json +4 -3
- package/tools/qa-cover-recipes.mjs +4 -3
- package/tools/version-manifests.json +2 -2
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Kit API
|
|
2
|
+
|
|
3
|
+
Every kit drawing is authored in **millimetres at final print size**: the SVG root carries `width="…mm"`, `height="…mm"` and a viewBox in the same numbers, so a stroke of `0.35` is 0.35 mm on paper and a font size of `2.47` is 7 pt. Import modules from `$SKILL_ROOT/scripts/lib/` (the scaffold writes absolute `file://` imports for you).
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
1. Sheets and canvases (`sheet.mjs`)
|
|
7
|
+
2. Symbols (`pid.mjs`)
|
|
8
|
+
3. Routing (`route.mjs`)
|
|
9
|
+
4. Journal figures (`figure.mjs`)
|
|
10
|
+
5. Isometric views (`iso.mjs`)
|
|
11
|
+
6. Tags (`isa.mjs`), theme (`theme.mjs`), helpers
|
|
12
|
+
7. QA and render from code
|
|
13
|
+
8. Legend sheet (`legend-sheet.mjs`)
|
|
14
|
+
9. Interactive page (`interactive.mjs`) and motion loop (`scripts/motion.mjs`)
|
|
15
|
+
|
|
16
|
+
## 1. Sheets and canvases (`sheet.mjs`)
|
|
17
|
+
|
|
18
|
+
### `createSheet(options)` → sheet
|
|
19
|
+
An ISO sheet with a zone frame, an equipment header band, a legend column, a notes block and a title block. Options: `mode` (`"pid"` | `"pfd"`), `size` (`"A4"`, `"A3"` default, `"A2"`, `"A1"`, or `[w, h]` mm), `title` (required), `subtitle`, `number`, `rev`, `date`, `scale` (`"NTS"` default), `sheet` (`"1 OF 1"`), `project`, `owner`, `drawn`, `checked`, `approved`, `notes` (array of strings, numbered), `lang`, `legendTitle`, `legendColumn` (default `true`), `headerBand` (default `true`). When the legend column would overflow, the instrument identification letters move to the right half of the notes block; if it still overflows, `sheet.warnings` says so.
|
|
20
|
+
|
|
21
|
+
The drawing area on A3 is about `[24, 39, 342, 246]`; read `sheet.drawing` for the exact box. Place every symbol inside it. A sheet has every canvas method below plus:
|
|
22
|
+
|
|
23
|
+
| Method | Does |
|
|
24
|
+
| --- | --- |
|
|
25
|
+
| `sheet.equipmentInfo(sym, lines)` | Adds the symbol's tag, name and spec lines to the header band above it (columns de-overlap themselves). |
|
|
26
|
+
| `sheet.render({ desc })` | The finished SVG string (`data-schematic-mode` is the sheet's mode). |
|
|
27
|
+
| `sheet.warnings` | Placement problems the build could not solve (a label with no clear place, a symbol outside the canvas, a legend that overflows). Print them; QA will fail on the same defects. |
|
|
28
|
+
|
|
29
|
+
### `createCanvas({ box, style, grid, clearance, stub, labelSize })` → canvas
|
|
30
|
+
A routed drawing area in a sheet or a journal panel. `style` is `"pid"` (black ink, ISA line weights) or `"journal"` (stream colours, names instead of tags, 7 pt labels, a 1 mm routing grid).
|
|
31
|
+
|
|
32
|
+
| Method | Does |
|
|
33
|
+
| --- | --- |
|
|
34
|
+
| `add(sym)` | Places a symbol; warns when it overlaps another or leaves the canvas. Returns the symbol. |
|
|
35
|
+
| `pipe({ from, to, via, points, kind, number, arrows })` | A process line. `kind`: `process-major` (default, 0.7 mm), `process-minor` (0.5), `utility` (0.35); every class has its own weight. `from`/`to` are ports or taps. With no `points` it is routed; `via` adds waypoints; `points` gives every corner yourself (checked orthogonal, first and last legs on the port normals). `number` places the line number on the longest clear straight. `arrows`: `"auto"`, `false`, or fractions `[0.3, 0.8]`. |
|
|
36
|
+
| `signal({ from, to, type })` | An instrument signal (ISA-5.1 Table 5.3.2): `type` `electric` (dashed, default), `pneumatic` (double slashes), `hydraulic` (L marks), `capillary` (crosses), `guided` (sine wave), `unguided` (broken sine wave), `data` (open circles; `software` is the same), `mechanical` (filled dots). Run a controller output to `valve.port("actuator")`. |
|
|
37
|
+
| `connect({ from, to })` | Instrument supply or process connection (0.18 mm thin solid impulse line). |
|
|
38
|
+
| `stream({ from, to, role, via })` | Journal stream line in the colour of `role` (`gas`, `liquid`, `coolant`, `heating`, `vent`, `signal`, `sample`, `vacuum`). |
|
|
39
|
+
| `inline(line, factory, options)` | Puts a valve, element or filter on the line at `options.at` (fraction, or a point near the line) and gaps the line under it. It snaps to the nearest straight run long enough; it throws when none is. Returns the symbol. |
|
|
40
|
+
| `line.tap(at)` | A branch point on a line (fraction, arc length, or a point within 1 mm of the line, and at least 3 mm from a bend). The port normal points to the line's left; `.flip()` gives the other side. A junction dot is drawn. |
|
|
41
|
+
| `line.at(fraction)` | `{ point, direction }` along the routed line. |
|
|
42
|
+
| `zone(box, name)` | A dashed enclosure (oven, cold box, skid boundary) with its name inside the top-left corner; lines may cross it, labels avoid it. |
|
|
43
|
+
| `streamNumber(line, n, { at })` | PFD stream number diamond on a straight run. |
|
|
44
|
+
| `streamTable({ box: [x0, y0, x1], streams, rows: [{ label, values }] })` | A stream table; returns its bottom y. |
|
|
45
|
+
| `text(x, y, text, { size, anchor, bold, color, kind })` | A fixed label that routes and later labels avoid. |
|
|
46
|
+
| `render()` | The canvas group. |
|
|
47
|
+
|
|
48
|
+
## 2. Symbols (`pid.mjs`)
|
|
49
|
+
|
|
50
|
+
Every factory takes `x, y` (the centre unless noted) in sheet mm and returns a symbol with `kind`, `tag`, `box`, `boxes`, `port(name[, t])`. Equipment tags must parse as `R-101`, `P-101A`, `TK-101`, …; instrument tags as ISA-5.1 (`PIC-101`). A bad tag throws.
|
|
51
|
+
|
|
52
|
+
| Factory | Kind(s) | Ports |
|
|
53
|
+
| --- | --- | --- |
|
|
54
|
+
| `vessel({ w, h, top, bottom, jacket, agitator, coil, packing, trays, demister, supports, liquid, tag, name })` | `vessel.vertical`, `.reactor`, `.jacketed`, `.column` | `top`, `bottom`, `top-left`, `top-right`, `bottom-left`, `bottom-right`, `jacket-in`, `jacket-out`, and `port("left" \| "right", t)` along the straight shell (t 0 top tangent → 1 bottom tangent), `port("top" \| "bottom", t)` across a head |
|
|
55
|
+
| `reactor(o)`, `column(o)`, `tank(o)` | jacketed stirred reactor; column with trays; cone-roof tank | as `vessel` |
|
|
56
|
+
| `drum({ w, h, saddles })` | `vessel.horizontal` | `left`, `right`, `port("top" \| "bottom", t)` |
|
|
57
|
+
| `gasCylinder({ w, h })` | `gas.cylinder` | `outlet` (up) |
|
|
58
|
+
| `pump({ r, type, facing })` | `pump.centrifugal`, `.positive`, `.metering` | `suction`, `discharge`, `signal` (stroke or speed input, bottom) |
|
|
59
|
+
| `compressor({ r, type, facing })` | `compressor.centrifugal`, `.reciprocating` (also a gas booster) | `inlet`, `outlet`, `drive` |
|
|
60
|
+
| `motor({ r })` | `drive.motor` | `shaft`, `left`, `right`, `bottom` |
|
|
61
|
+
| `exchanger({ r })` | `exchanger.general` | `tube-in`, `tube-out`, `shell-in`, `shell-out` |
|
|
62
|
+
| `shellTube({ w, h, type })` | `exchanger.shelltube` (`type: "fixed"`, default), `exchanger.floating`, `exchanger.utube` | `tube-in`, `tube-out`, `shell-in`, `shell-out` |
|
|
63
|
+
| `plateExchanger({ w, h })` | `exchanger.plate` (ISO 10628-2 item 3.6) | `hot-in`, `hot-out`, `cold-in`, `cold-out` |
|
|
64
|
+
| `airCooler({ w, h })` | `exchanger.aircooler` | `in`, `out` |
|
|
65
|
+
| `unit({ w, h, caption, glyph, ports })` | `package.unit` (chiller, circulator, analyser, DAQ, booster skid) | as declared: `ports: { supply: ["right", 0.3] }`; also `port(side, t)` |
|
|
66
|
+
| `valve({ type, orient, actuator, fail, tag })` | `valve.gate`, `.globe`, `.ball`, `.butterfly`, `.check`, `.needle`, `.plug`, `.diaphragm`, `.threeway`; with `actuator` (`diaphragm`, `piston`, `motor`, `solenoid`, `hand`) the kind is `valve.<type>.<actuator>`; `fail` is `FO`, `FC`, `FL` or `FI` | `a`, `b` (and `c` on a three-way), `actuator` when actuated |
|
|
67
|
+
| `angleValve({ inlet, outlet, actuator, fail, tag })` | `valve.angle`, `valve.angle.<actuator>` | `inlet`, `outlet` on two perpendicular sides, `actuator` |
|
|
68
|
+
| `regulator({ backPressure })` | `valve.regulator`, `valve.backpressure` | `a`, `b` |
|
|
69
|
+
| `safetyValve({ outlet, setPressure, tag })` | `valve.safety` | `inlet` (from below), `outlet` (side) |
|
|
70
|
+
| `ruptureDisk`, `orifice`, `rotameter`, `mfc`, `filter`, `reducer({ eccentric, flat })`, `flange`, `sightGlass`, `blind({ state })` | `relief.rupture`, `flow.orifice`, `flow.rotameter`, `flow.mfc` (+ `signal`), `line.filter`, `line.reducer`, `line.reducer-eccentric`, `line.flange`, `line.sightglass`, `line.blind`, `line.blind-open` | `a`, `b` |
|
|
71
|
+
| `flowElement({ type })` | `flow.orifice`, `flow.venturi`, `flow.magnetic`, `.coriolis`, `.vortex`, `.turbine`, `.ultrasonic`, `.thermal` | `a`, `b` |
|
|
72
|
+
| `instrument({ tag, fn, location, r })` | `instrument.<fn>-<location>`: `fn` `discrete` (default), `shared`, `computer`, `plc`; `location` `field` (default), `main`, `main-rear`, `aux`, `aux-rear` (round-1 names `dcs`, `plc`, `panel`, `panel-rear`, `local-panel` still work) | `top`, `bottom`, `left`, `right` |
|
|
73
|
+
| `interlock({ text })` | `logic.interlock` | `top`, `bottom`, `left`, `right` |
|
|
74
|
+
| `vent({ text })`, `drain({ text })`, `samplePoint({ text, facing })` | `terminal.vent`, `terminal.drain`, `terminal.sample` | `in` |
|
|
75
|
+
| `offPage({ text, pointing })`, `utility({ text, pointing })` | `terminal.offpage`, `terminal.utility` | `in`, `out` |
|
|
76
|
+
|
|
77
|
+
Inline factories take `orient` (`right`, `left`, `up`, `down`); `sheet.inline` sets it from the line. A symbol on a line running left is mirrored, not turned over, so an actuator still stands above the line; letters on an inline symbol (fail positions) always read upright, and on a vertical line they sit beside the body opposite the actuator. A later process line that crosses an earlier one hops it; the gate accepts the hop. `describeKind(kind, { short })` gives the legend text for every kind, including composed ones; `KIND_DESCRIPTIONS`, `ACTUATORS`, `FUNCTIONS`, `LOCATIONS` and `FAIL_POSITIONS` hold the parts.
|
|
78
|
+
|
|
79
|
+
## 3. Routing (`route.mjs`)
|
|
80
|
+
|
|
81
|
+
`routeOrthogonal({ from, to, obstacles, lines, bounds, grid, clearance, stub, bendCost, crossCost, nearCost, exempt })` returns corner points. It leaves each port along its normal far enough to clear every symbol's clearance zone, never enters an inflated symbol box, never runs along or turns on an existing line, crosses existing lines only at right angles (with a cost), and minimises length plus bends. Two ports that face each other on one axis join straight. It throws when no route exists. `orthogonal(points, { from, to })` validates a hand-given polyline.
|
|
82
|
+
|
|
83
|
+
## 4. Journal figures (`figure.mjs`)
|
|
84
|
+
|
|
85
|
+
`createFigure({ width, height, title, desc, lang, mode, labelStyle, textPt })`: `width` is `"single"` (85 mm), `"onehalf"` (120), `"double"` (178) or a number; `height` ≤ 230 mm; `labelStyle` `"paren"` → (a), `"bold"` → a, `"upper"` → A.
|
|
86
|
+
|
|
87
|
+
| Method | Does |
|
|
88
|
+
| --- | --- |
|
|
89
|
+
| `fig.panel(label, [x, y, w, h])` | A panel with its label at the top left (`label` `null` for a single-panel figure without a label). |
|
|
90
|
+
| `panel.canvas({ box })` | A journal-style canvas inside the panel (default box: below the label). |
|
|
91
|
+
| `panel.iso(view, { box, labelColumn, calloutSize })` | Fits an isometric view and its callouts into the panel. |
|
|
92
|
+
| `panel.text(x, y, text, options)`, `panel.raw(svg)` | Extra content. |
|
|
93
|
+
| `fig.key(roles, [x, y], { columns, colWidth })` | Stream-colour key; QA requires every role drawn to be in it. |
|
|
94
|
+
| `fig.render()` | The SVG (`data-min-text-pt="6"`). |
|
|
95
|
+
|
|
96
|
+
## 5. Isometric views (`iso.mjs`)
|
|
97
|
+
|
|
98
|
+
`createIsoView({ azimuth = 45, elevation = 30, light })`. World units are the object's own millimetres, x and y on the floor, z up. Nothing is projected until `fit`.
|
|
99
|
+
|
|
100
|
+
| Function | Does |
|
|
101
|
+
| --- | --- |
|
|
102
|
+
| `lathe({ name, origin, axis, profile, tone, steps, seams, cut, wall, layer, bias, into })` | A turned part: `profile` is `[[s, r], …]` along `axis` (`"x"`, `"y"`, `"z"`, `"-z"` or a vector) from `origin`; add a third element `1` to mark a smooth knot (no crease ring). One lathe is one convex body: build steps, flanges and nozzles as separate lathes. `seams: [s…]` draws weld rings. `cut: { from, to, span, turn }` opens a window from `s = from` to `to`, `span` degrees wide, centred on the side facing the viewer (`turn` rotates it); `wall` is the cut wall thickness. Returns a handle with `point(s, r, angle)`, `surface(s, sideDeg)`, `anchor(f, sideDeg)`, `facingAngle`, `frame`. |
|
|
103
|
+
| `box({ name, plan: { x, y, w, d, r }, z, h, tone, layer })`, `prism({ ring, z, h, … })` | Flat parts: pads, skids, saddles, brackets, plates. `anchor()` is the top centre. |
|
|
104
|
+
| `pipe({ name, points, r, tone, bend, caps, flow })` | A filleted route drawn as depth-sorted chunks with shine and shade bands; `anchor(f)` a point along it. `flow: { color, dash: [on, off], offset, width }` adds a dashed stripe whose dashes march with `offset` (screen mm), continuous across chunks. |
|
|
105
|
+
| `sphere({ name, center, r })`, `dots({ points, r, color })`, `polyline({ points, color, width, dash, flow })`, `boltCircle({ frame, s, radius, count })` | Balls, textures, hairlines, bolt heads. `polyline` `flow: { dash, offset, start }` in world mm marches dashes along collinear pieces of one run. |
|
|
106
|
+
| `extent(points)` | World points the fit keeps in frame although nothing is drawn there: where exploded or moving parts go, so every frame and every page state shares one scale. |
|
|
107
|
+
| `halo({ plan, z })` | Soft ground shadow (layer −2). |
|
|
108
|
+
| `callout({ part, at, text, side, number })` | A label in a column beside the art with a leader to a dot on `part` (its `anchor()`, or `at`). Sides are chosen to leave the art largest; leaders are reordered so none cross. |
|
|
109
|
+
| `fit(box, { pad, labelColumn, size })`, `render()`, `renderCallouts({ box, size })` | Used by `panel.iso`. Callout leaders are ordered so none cross and none run within 1.4 mm of another; what cannot be cleared lands in `view.warnings` (and in `fig.warnings()`). |
|
|
110
|
+
| `screenVector([dx, dy, dz])` | The screen offset in mm of a world move at the fitted scale: the explode vector an interactive page needs. |
|
|
111
|
+
|
|
112
|
+
Every factory also takes `group`: the assembly the part belongs to (`"shell"`, `"internals"`, `"drive"`). It is written as `data-group` around the part; interactive pages toggle and explode by it.
|
|
113
|
+
|
|
114
|
+
`createIsoView({ azimuth, elevation, light, palette })`: `palette` is `"material"` (default, full colour) or `"grey"` (opt-in quiet look); any other name throws. Material tones: `steel`, `stainless`, `frame`, `copper`, `brass`, `cast`, `concrete`, `insulation`, `rubber`, `glass` (the same in both palettes). Role tones, painted by the palette: `lo`, `mid`, `hi`, `accent` (the one part to watch), `cavity`, `section`, `liquid`, `warm`, `cool`. Layers: `-2` halo, `-1` ground, `0` everything else; `into: handle` draws a part inside a cut lathe, between its inner wall and its outer shell. Helpers: `ellipsoidalHead(R)`, `vesselProfile(R, straight, { top, bottom })`, `frameAlong(origin, axis)`, `fillet(points, radius)`.
|
|
115
|
+
|
|
116
|
+
## 6. Tags, theme, helpers
|
|
117
|
+
|
|
118
|
+
- `parseInstrumentTag(tag)` → `{ ok, letters, loop, first, modifier, functions, meaning }` or `{ ok: false, error }`; `parseEquipmentTag(tag)`; `parseLineNumber(text)` → `{ ok, size, fluid, sequence, spec, insulation }`.
|
|
119
|
+
- `theme.mjs`: `PID` (weights and text sizes), `JOURNAL` (widths, 7 pt text, 6 pt floor, 0.75 pt lines), `OKABE_ITO`, `STREAM` roles, `ISO` tokens, `fontFor(text)` (Arial for Latin, Pretendard for Hangul).
|
|
120
|
+
- `svg.mjs`: `svgDocument`, `el`, `pathOf`, `textBox`, `ptToMm`, `mmToPt`.
|
|
121
|
+
|
|
122
|
+
## 7. QA and render from code
|
|
123
|
+
|
|
124
|
+
`check(svgText, { mode, minTextPt, minStrokeMm })` from `qa-core.mjs` returns `{ verdict, fails, warnings, findings, stats }`. `renderPng`, `renderPdf`, `renderSheet`, `findChrome` from `scripts/render.mjs`; `checkExports` from `scripts/qa.mjs`.
|
|
125
|
+
|
|
126
|
+
## 8. Legend sheet (`legend-sheet.mjs`)
|
|
127
|
+
|
|
128
|
+
`createLegendSheet({ size = "A2", title, number, rev, date, scale, project, owner, drawn, checked, approved, sheet })` returns the SVG of the "P&ID symbols and abbreviations" sheet: every line class, the equipment, valves, actuators, self-acting and relief devices, piping items, flow elements, connections, the ISA-5.1 shape-and-location matrix, the identification letters by position, fail positions, the line-number form and the equipment prefixes, laid out in columns that never split a short section, with the usual frame, notes and title block. It is built from the library, so it lists exactly what the kit draws.
|
|
129
|
+
|
|
130
|
+
## 9. Interactive page (`interactive.mjs`) and motion loop (`scripts/motion.mjs`)
|
|
131
|
+
|
|
132
|
+
`renderInteractive({ title, description, lang, views: [{ id, label, svg, explode }], layers: [{ group, label }], order, duration, stagger, hint, text })` returns one self-contained HTML page: a button per preset view, an exploded-view toggle, a checkbox per layer group, callout labels that are focusable buttons, a part outline lit on hover or focus, keys `E` and `1`…`n`, `Esc` to clear, reduced motion honoured, an `aria-live` line for state changes, and `#view=…&explode=1&hide=a,b&select=C3` to open in a given state. `explode` maps each group to its screen vector in that view (`view.screenVector(worldMove)`); `order` is the order groups leave in (they come back in reverse). Build each view from the same scene function with `reach: true` style extents so the exploded parts stay on the page.
|
|
133
|
+
|
|
134
|
+
`renderMotion({ frame, out, name, seconds, fps, width, small, formats })` (or `node scripts/motion.mjs scene.mjs --out <dir>`) draws `frame(t)` for t in [0, 1), rasterises each frame in headless Chrome and writes `name.mp4` (H.264, yuv420p, even size), `name.webp` and `name.gif` (`small` px wide). It needs ffmpeg (and img2webp for WebP) and stops with `ENCODER_REQUIRED` and the install line when one is missing; it never installs anything. `examples/iso-heat-exchanger/scene.mjs` shows the pattern: one `scene({ azimuth, elevation, explode, flow, callouts, reach })` for the figure, the page and the film.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# BFD, PFD and equipment layout
|
|
2
|
+
|
|
3
|
+
ISO 10628-1 names three process diagrams that refine each other: the **block flow diagram** (units as boxes and the main streams), the **process flow diagram** (equipment, main streams with numbers, operating conditions, a stream table, the control loops that define the process), and the **P&ID** (every line, valve, instrument and safety device). Pick the lightest one that answers the reader's question.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
1. Which diagram
|
|
7
|
+
2. Block flow diagram
|
|
8
|
+
3. Process flow diagram
|
|
9
|
+
4. Stream table
|
|
10
|
+
5. Equipment layout and plot plan
|
|
11
|
+
6. Faults
|
|
12
|
+
|
|
13
|
+
## 1. Which diagram
|
|
14
|
+
|
|
15
|
+
| Reader's question | Diagram | Mode |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| What are the units and how does material move between them? | BFD | `pfd` with `unit()` boxes |
|
|
18
|
+
| What equipment, at what conditions, with what mass balance? | PFD | `pfd` |
|
|
19
|
+
| How is it built, controlled, isolated and protected? | P&ID | `pid` |
|
|
20
|
+
| How is it arranged in space, and what does it look like? | Layout or isometric | `pfd` sheet in plan, or `iso` |
|
|
21
|
+
| What did the experiment use? (paper) | Apparatus figure | `journal` |
|
|
22
|
+
|
|
23
|
+
A BFD drawn with real equipment symbols, or a PFD drawn with every isolation valve, answers the wrong question and costs the reader time.
|
|
24
|
+
|
|
25
|
+
## 2. Block flow diagram
|
|
26
|
+
|
|
27
|
+
Units are labelled boxes (`unit({ caption: "Hydrate formation" })`) of one size per level of importance, arranged left to right in process order; streams are `pipe` lines with arrows and short names (`"Feed gas, 5 MPa"` as a line number); recycles return along the bottom lane; utilities stay off the diagram unless they are the point. Use `createSheet({ mode: "pfd" })` and `streamNumber(line, n)` when a mass balance accompanies it.
|
|
28
|
+
|
|
29
|
+
## 3. Process flow diagram
|
|
30
|
+
|
|
31
|
+
- **Equipment**: every major item with its tag and name in the header band, drawn with the same symbols as the P&ID; spares (`P-101B`) and minor items stay off.
|
|
32
|
+
- **Streams**: main process lines, heavy; each carries a **stream number** in a diamond (`sheet.streamNumber(line, 3)`), numbered in flow order. The stream number is the key into the stream table.
|
|
33
|
+
- **Conditions**: pressure and temperature flags at key points as short texts beside the line (`sheet.text(x, y, "5.0 MPa, 2 °C")`), or only in the table.
|
|
34
|
+
- **Control**: the loops that define the process (reactor pressure, jacket temperature, level), with their controllers and final elements; no isolation valves, drains or vents.
|
|
35
|
+
- **Utilities**: heating and cooling media as short utility lines into exchangers, labelled with the medium.
|
|
36
|
+
|
|
37
|
+
## 4. Stream table
|
|
38
|
+
|
|
39
|
+
`streamTable({ box: [x0, y0, x1], streams: [1, 2, 3], rows: [{ label: "Pressure (MPa)", values: [0.1, 5.0, 5.0] }, …] })` draws one column per stream and one row per property inside the box and returns its bottom. Usual rows: phase, temperature, pressure, total mass flow, molar flow, composition of the key components. Put it below the drawing or across the bottom of the sheet; values come from the user's balance or simulation (HYSYS, Aspen, a spreadsheet), never from estimation without saying so. Units go in the row label, never in the cells.
|
|
40
|
+
|
|
41
|
+
## 5. Equipment layout and plot plan
|
|
42
|
+
|
|
43
|
+
A plan view is a PFD-style canvas drawn to scale: `createSheet({ scale: "1:50" })` and coordinates in sheet millimetres = real millimetres ÷ 50. Equipment outlines are their real footprints (`unit` boxes for skids and packages, plain circles added with `canvas.raw()` for vessels seen from above), with aisles at least 1 m real, maintenance envelopes dashed (`zone`), and north arrow and grid lines when the site needs them. For a three-dimensional impression of the same arrangement use an isometric view (`references/isometric-craft.md`): boxes for skids, lathes for vessels, pipes along racks.
|
|
44
|
+
|
|
45
|
+
## 6. Faults
|
|
46
|
+
|
|
47
|
+
| You see | Fix |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
| A PFD full of block valves and drains | Remove them; they belong to the P&ID. |
|
|
50
|
+
| Stream numbers that skip or jump around | Number in flow order; recycles take the next free number. |
|
|
51
|
+
| A stream table without units | Units in the row labels. |
|
|
52
|
+
| Values that do not close the balance | Take them from the user's balance or say they are illustrative. |
|
|
53
|
+
| A BFD with equipment symbols | Use labelled boxes; the BFD is about units, not hardware. |
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Drafting a P&ID sheet
|
|
2
|
+
|
|
3
|
+
A P&ID is an operating document: an operator, a reviewer in a HAZOP and a commissioning engineer each read it for a different question, and each must find the answer without asking the author. Everything here serves that reading.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
1. Before drawing
|
|
7
|
+
2. The sheet
|
|
8
|
+
3. Placing equipment
|
|
9
|
+
4. Lines: routing, crossings, branches
|
|
10
|
+
5. Line numbers and flow arrows
|
|
11
|
+
6. Valves and isolation
|
|
12
|
+
7. Instruments and control loops
|
|
13
|
+
8. Relief and venting
|
|
14
|
+
9. Legend, header, notes and title block
|
|
15
|
+
10. Faults that reviewers catch
|
|
16
|
+
|
|
17
|
+
## 1. Before drawing
|
|
18
|
+
|
|
19
|
+
Write four lists in the build script before any coordinate:
|
|
20
|
+
|
|
21
|
+
- **Equipment**: tag, name, design pressure and temperature, size or duty. These go to the header band (`sheet.equipmentInfo(sym, ["10 MPa / -20…80 °C", "1.0 L, SS316"])`).
|
|
22
|
+
- **Lines**: from, to, nominal size, fluid code, sequence, piping class → the line number `1/4"-CH4-101-HP1`. State the format once in the notes.
|
|
23
|
+
- **Instruments**: tag, what it measures, where it reads (field, panel, DCS), what it acts on.
|
|
24
|
+
- **Safety devices**: each PSV and rupture disk, its set pressure, the equipment it protects, and where it discharges.
|
|
25
|
+
|
|
26
|
+
Invent nothing silently. When the brief gives no set point, choose a plausible one, keep it in the build as a named constant, and list it in the reply as an assumption.
|
|
27
|
+
|
|
28
|
+
## 2. The sheet
|
|
29
|
+
|
|
30
|
+
`createSheet({ size: "A3", … })` draws an ISO A3 landscape sheet (420 × 297 mm): a frame 20 mm from the left edge (binding) and 10 mm elsewhere, zone numbers along the top and bottom and zone letters along the sides so a reviewer can say "the PSV at C6", the equipment header band across the top, the legend column on the right, the notes block bottom left and the title block bottom right. A1 and A2 work the same way for dense units; A4 suits a small skid.
|
|
31
|
+
|
|
32
|
+
Text at 1:1 on A3: tags 2.5 mm, equipment tags 3.0 mm bold, line numbers and notes 2.2 mm, title 4 mm. Nothing under 2.0 mm, because sheets are photocopied and reduced; the QA floor for P&ID sheets is 5.6 pt.
|
|
33
|
+
|
|
34
|
+
Line weights carry the hierarchy on the ISO 128 series, and every pipe class has its own: main process 0.7 mm, minor process 0.5 mm, utility 0.35 mm, instrument supply or process connection 0.18 mm; equipment outlines 0.5 mm, symbols 0.35 mm, signals 0.25 mm with the mark of their medium, tangent lines and details 0.18 mm. Pick the class by what the line carries, not by how it looks: a 2-inch cooling-water header is a utility line however big it is.
|
|
35
|
+
|
|
36
|
+
## 3. Placing equipment
|
|
37
|
+
|
|
38
|
+
- **Flow runs left to right.** Feed and utilities enter on the left, products and vents leave on the right or top. The main process route reads as one horizontal story.
|
|
39
|
+
- **Gravity is real.** Pumps sit below and near their suction vessel; drains go down; vents and relief discharge go up. A tank's outlet nozzle is at its bottom.
|
|
40
|
+
- **Equal elevations for related items.** Put duty and standby pumps one above the other with the same spacing; line up instruments of one loop.
|
|
41
|
+
- **Room for lines.** Keep 15–25 mm between symbols that exchange several lines, and leave free horizontal lanes for headers and a lane below the equipment for signal runs to the DCS.
|
|
42
|
+
- **Instruments sit next to what they measure,** offset 10–15 mm from the line or nozzle, with a short connection. Controllers and DCS bubbles go between the measurement and the final element, toward the top or the bottom lane, so signal lines do not cross the process.
|
|
43
|
+
- **Symbols never overlap.** The canvas warns, and the router cannot pass between symbols closer than twice the clearance (2.2 mm each side on a sheet).
|
|
44
|
+
|
|
45
|
+
## 4. Lines: routing, crossings, branches
|
|
46
|
+
|
|
47
|
+
The router follows the drafting rules a checker applies to a hand-drawn sheet:
|
|
48
|
+
|
|
49
|
+
1. **Leave a port on its normal.** A line leaves a nozzle straight out (up from a top nozzle, sideways from a side nozzle) before it turns, so the reader sees where it starts.
|
|
50
|
+
2. **Never through a symbol.** A route enters a symbol only at its own port. When there is no way around, the build throws: move a symbol or give `via` waypoints. Never draw the line by hand through it; `LINE.THROUGH_SYMBOL` fails.
|
|
51
|
+
3. **Few bends.** Each bend costs as much as about 9 mm of straight line, so routes prefer one or two clean corners to a staircase.
|
|
52
|
+
4. **Cross at right angles, on straights.** A later process line hops over an earlier one (a small semicircle); signal lines cross process lines without a hop. A line never turns on top of another line (`LINE.BEND_ON_LINE`): a corner on another line reads as a junction.
|
|
53
|
+
5. **Never run along another line** (`LINE.OVERLAP`): two lines on one track cannot be told apart.
|
|
54
|
+
6. **Branches leave a straight run.** `line.tap()` refuses a point within 3 mm of a bend and draws a junction dot. A branch leaves perpendicular to the main line.
|
|
55
|
+
7. **Every line ends on something:** a port, another line (a junction), or a terminal (vent, drain, off-page, utility). `LINE.DANGLING` fails anything else.
|
|
56
|
+
|
|
57
|
+
Draw the main process lines first, then minor lines, then utilities, then instrument connections and signals last, so the thin lines route around the heavy ones (the same order an illustrator uses for ducts before cables).
|
|
58
|
+
|
|
59
|
+
## 5. Line numbers and flow arrows
|
|
60
|
+
|
|
61
|
+
A line number labels each line between two pieces of equipment, placed parallel to its longest clear straight, beside it, never on it. The format sits in the notes: size – fluid code – sequence – piping class (`2"-PG-101-A1A`). Fluid codes are short and listed in the legend notes when they are not obvious (`CH4`, `CO2`, `CWS`/`CWR`, `N2`, `IA`, `PW`).
|
|
62
|
+
|
|
63
|
+
Flow arrows: one on each line's longest clear straight by default, kept clear of junctions and symbols; add arrows (`arrows: [0.2, 0.8]`) where the direction is not obvious, such as at a recycle or after a three-way valve. Never arrow a signal line.
|
|
64
|
+
|
|
65
|
+
## 6. Valves and isolation
|
|
66
|
+
|
|
67
|
+
- **Every instrument, pump, control valve and relief device can be isolated.** Put a block valve on each side of a control valve, with a bypass globe or needle valve when the process must run while the control valve is out.
|
|
68
|
+
- **Check valves** sit on pump discharges and on any line that must never flow back (gas supply into a reactor).
|
|
69
|
+
- **Drains and vents** at low and high points of a liquid loop, each with a valve.
|
|
70
|
+
- **Double block and bleed** on high-pressure gas: two block valves with a bleed valve between, where the gas supply meets the reactor.
|
|
71
|
+
- **Valve on a straight run**: `inline` snaps a valve to the nearest straight run that can hold it, and throws when none can.
|
|
72
|
+
|
|
73
|
+
## 7. Instruments and control loops
|
|
74
|
+
|
|
75
|
+
A loop on the sheet: element or transmitter at the process (`PT-101` connected by a thin solid line to a nozzle or a tap), signal to the controller (`PIC-101` in the DCS, dashed for electric), signal to the final element (`PV-101` diaphragm valve, or a pump's `signal` port, or a chiller's setpoint input). Draw the whole loop on the sheet, or end it at an off-page connector naming the sheet that continues it.
|
|
76
|
+
|
|
77
|
+
Alarms and trips: put `PAH`, `PAHH`, `TAH` on the controller bubble's loop number; a trip (`PSHH-101` → interlock `I-1` → `XV-101` closes) is drawn as its own loop through an interlock diamond. Safety instrumented functions are labelled as such in the notes.
|
|
78
|
+
|
|
79
|
+
## 8. Relief and venting
|
|
80
|
+
|
|
81
|
+
Every vessel that can be over-pressured (by a gas supply, a booster, heat input, fire, or a blocked outlet) has a relief device set at or below its design pressure. Draw the PSV on the vessel or its inlet line with its set pressure beside it (`setPressure: "SET 12 MPa"`), and draw where it discharges: a vent header, a flare off-page connector or a safe vent with `ATM`. A rupture disk upstream of a PSV protects the valve from a corrosive or hydrate-forming gas; draw a pressure gauge between them to show the disk is intact. A relief path that ends in the air is the first defect a HAZOP finds.
|
|
82
|
+
|
|
83
|
+
## 9. Legend, header, notes and title block
|
|
84
|
+
|
|
85
|
+
- **Legend**: built from what the sheet draws: every line kind, every symbol kind (composed kinds such as a globe valve with a diaphragm actuator, or a DCS function in the control room, get their own row and sample), and the instrument identification letters used with their meaning. Its column is fixed; when it would overflow, the identification letters move into the right half of the notes block, and if it still overflows the sheet warns: move to a larger sheet.
|
|
86
|
+
- **Legend sheet**: a drawing set opens with a "P&ID symbols and abbreviations" sheet. `createLegendSheet({ number, rev, date })` builds it from the library (every symbol, line class, the ISA shape-and-location matrix, the letters, fail positions, the line-number form, the equipment prefixes); give it the set's first drawing number.
|
|
87
|
+
- **Equipment header**: tag, name and two or three spec lines above each major item.
|
|
88
|
+
- **Notes**: numbered; the line number format, the meaning of duty/standby, set-point references, hold points. Keep them to facts the drawing cannot show.
|
|
89
|
+
- **Title block** (ISO 7200 fields): title, drawing number, revision, sheet, project, owner, drawn/checked/approved, date, scale (`NTS` for P&IDs). `TITLEBLOCK.FIELDS` fails an empty title, number, revision, date or scale.
|
|
90
|
+
|
|
91
|
+
## 10. Faults that reviewers catch
|
|
92
|
+
|
|
93
|
+
| You see | Fix |
|
|
94
|
+
| --- | --- |
|
|
95
|
+
| A line passes behind a vessel or through a valve body | Re-route with `via`, or move the symbol; the router refuses the pass-through. |
|
|
96
|
+
| A branch leaves at a corner | Tap a straight run at least 3 mm from the bend. |
|
|
97
|
+
| A controller with no final element | Draw the output signal to the valve, pump or heater it moves, or remove the `C`. |
|
|
98
|
+
| An instrument floating next to a vessel | Connect it to a nozzle (`vessel.port("right", 0.4)`) or a tap. |
|
|
99
|
+
| PSV discharge stops in the air | Run it to a vent, header or off-page connector. |
|
|
100
|
+
| Two lines labelled with the same number | Number every line between two items once. |
|
|
101
|
+
| Tags like `TCI` or `PCIC` | Readout letters come before output letters, no repeats: `TIC`, `PIC`. |
|
|
102
|
+
| A dense corner where labels overlap | Spread the equipment; never shrink text under 2.0 mm. |
|
|
103
|
+
| The legend shows symbols not on the sheet | The kit builds the legend from the drawing; a hand-written legend drifts. |
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# P&ID symbols and identification
|
|
2
|
+
|
|
3
|
+
The kit draws a vocabulary close to ISO 10628-2 (graphical symbols for process diagrams) for equipment and fittings, and ANSI/ISA-5.1 for instruments, their identification letters and signal lines. Conventions vary between owners and countries, so **the legend on the sheet governs**: the sheet's legend is built from the symbols and line kinds actually drawn, and the QA gate fails a sheet whose legend misses one. When a project has its own symbol standard, follow it and keep the legend true.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
1. Identification letters (ISA-5.1)
|
|
7
|
+
2. Instrument bubbles: what the function is and where it lives
|
|
8
|
+
3. Pipe classes and signal lines
|
|
9
|
+
4. Equipment symbols and tags
|
|
10
|
+
5. Valves, actuators and fail positions
|
|
11
|
+
6. Piping items, flow elements and terminals
|
|
12
|
+
7. Common tags for a high-pressure gas-hydrate loop
|
|
13
|
+
8. Standards basis, symbol by symbol
|
|
14
|
+
|
|
15
|
+
## 1. Identification letters (ISA-5.1)
|
|
16
|
+
|
|
17
|
+
A tag is **letters + loop number**: `PIC-101` is loop 101, pressure (P), indicating (I), controller (C). The first letter is the measured or initiating variable; an optional modifier follows it; then the functions, readout or passive ones before output ones; `H`, `L`, `M` modify the alarm or switch letter before them.
|
|
18
|
+
|
|
19
|
+
| Letter | First (measured variable) | Modifier after the first letter | Succeeding: readout / passive | Succeeding: output | Function modifier |
|
|
20
|
+
| --- | --- | --- | --- | --- | --- |
|
|
21
|
+
| A | Analysis (composition, pH, O₂) | | Alarm | | |
|
|
22
|
+
| B | Burner, combustion | | User's choice | | |
|
|
23
|
+
| C | User's choice (often conductivity) | | | Control | |
|
|
24
|
+
| D | User's choice (often density) | Differential | | | |
|
|
25
|
+
| E | Voltage | | Primary element (sensor) | | |
|
|
26
|
+
| F | Flow | Ratio | | | |
|
|
27
|
+
| G | User's choice (gauging) | | Glass, gauge, viewing | | |
|
|
28
|
+
| H | Hand | | | | High |
|
|
29
|
+
| I | Current | | Indicate | | |
|
|
30
|
+
| J | Power | Scan | | | |
|
|
31
|
+
| K | Time, schedule | Time rate of change | | Control station | |
|
|
32
|
+
| L | Level | | Light | | Low |
|
|
33
|
+
| M | User's choice (moisture) | Momentary | | | Middle |
|
|
34
|
+
| O | User's choice | | Orifice, restriction | | |
|
|
35
|
+
| P | Pressure, vacuum | | Point (test connection) | | |
|
|
36
|
+
| Q | Quantity | Integrate, totalise | | | |
|
|
37
|
+
| R | Radiation | | Record | | |
|
|
38
|
+
| S | Speed, frequency | Safety | | Switch | |
|
|
39
|
+
| T | Temperature | | | Transmit | |
|
|
40
|
+
| U | Multivariable | | | Multifunction | |
|
|
41
|
+
| V | Vibration | | | Valve, damper | |
|
|
42
|
+
| W | Weight, force | | Well, probe | | |
|
|
43
|
+
| X | Unclassified | x-axis | Unclassified | | |
|
|
44
|
+
| Y | Event, state | y-axis | | Relay, compute, convert | |
|
|
45
|
+
| Z | Position, dimension | z-axis | | Driver, actuator | |
|
|
46
|
+
|
|
47
|
+
Readable examples: `PT` pressure transmitter · `PI` local pressure gauge reading · `PIC` pressure indicating controller · `PCV` self-actuated pressure regulator · `PV` pressure control valve (final element of a PIC loop) · `PSV` pressure safety valve · `PSE` rupture disk · `PAH`/`PAHH` high and high-high pressure alarm · `PSHH` high-high pressure switch (trip) · `PDT` differential pressure transmitter · `TE` temperature element (thermocouple, RTD) · `TW` thermowell · `TT`, `TIC`, `TV` · `FT`, `FE` (orifice), `FIC`, `FV`, `FQI` totaliser · `LT`, `LG` level gauge, `LIC`, `LSL` · `AT` analyser transmitter (GC, MS, O₂) · `SC` speed controller · `HS` hand switch · `XV` on-off valve · `ZSO`/`ZSC` position switch open/closed.
|
|
48
|
+
|
|
49
|
+
`parseInstrumentTag` enforces: the first letter exists; a variable modifier only directly after it; function letters from the table, readout `I`/`R` before outputs, no repeats; `H`/`L`/`M` only after `A`, `S` or another `H`/`L`/`M`. `TAG.GRAMMAR` fails a symbol tag that breaks these, `TAG.DUPLICATE` fails two items with one tag.
|
|
50
|
+
|
|
51
|
+
**Loop numbering.** One loop number per measured point and everything that acts on it: `PT-101 → PIC-101 → PV-101`, and its alarms `PAH-101`. Number loops by unit (100s for the reactor section, 200s for the chiller) so a reader finds them.
|
|
52
|
+
|
|
53
|
+
## 2. Instrument bubbles: what the function is and where it lives
|
|
54
|
+
|
|
55
|
+
ISA-5.1 Table 5.1.1 separates two things a bubble says. Its **shape** names the kind of device or function; the **lines across it** name where it lives.
|
|
56
|
+
|
|
57
|
+
| Shape | Function | Kit `fn` |
|
|
58
|
+
| --- | --- | --- |
|
|
59
|
+
| Circle | Discrete instrument: a transmitter, gauge, switch or single-loop controller | `"discrete"` (default) |
|
|
60
|
+
| Circle in a square | Shared display and control: a function of the DCS or operator screen | `"shared"` |
|
|
61
|
+
| Hexagon | Computer function: an optimiser, a calculation outside the DCS | `"computer"` |
|
|
62
|
+
| Diamond in a square | PLC logic, or a safety instrumented system function | `"plc"` |
|
|
63
|
+
|
|
64
|
+
| Lines across the shape | Location | Kit `location` |
|
|
65
|
+
| --- | --- | --- |
|
|
66
|
+
| none | In the field, at the equipment | `"field"` (default) |
|
|
67
|
+
| one solid | Main control room, operator accessible (on the console or panel front) | `"main"` |
|
|
68
|
+
| one dashed | Main control room, not normally accessible (behind the panel, in a cabinet) | `"main-rear"` |
|
|
69
|
+
| two solid | Auxiliary or local panel near the unit, operator accessible | `"aux"` |
|
|
70
|
+
| two dashed | Auxiliary or local panel, not normally accessible | `"aux-rear"` |
|
|
71
|
+
|
|
72
|
+
So a DCS controller on the operator console is `instrument({ tag: "PIC-101", fn: "shared", location: "main" })`: a circle in a square with one solid line. A local pressure gauge is a plain circle. The kind is `instrument.<fn>-<location>` and the legend names both halves. The round-1 names still work: `location: "dcs"` means shared/main, `"plc"` plc/main, `"panel"` discrete/main, `"panel-rear"` discrete/main-rear, `"local-panel"` discrete/aux.
|
|
73
|
+
|
|
74
|
+
The letters sit in the upper half and the loop number in the lower half, clear of the location lines. Keep bubbles 10 mm across on an A3 sheet (`r = 5`); a 4-letter tag drops to 2.1 mm text automatically. An interlock or logic block is a diamond with its number (`interlock()`).
|
|
75
|
+
|
|
76
|
+
## 3. Pipe classes and signal lines
|
|
77
|
+
|
|
78
|
+
Pipe classes differ by **weight**, on the ISO 128 series, so they never look alike on the sheet or in the legend: main process 0.7 mm, minor process 0.5 mm, utility 0.35 mm, instrument supply or process connection 0.18 mm. Instrument signals are 0.25 mm and carry the mark of ISA-5.1 Table 5.3.2 for their medium.
|
|
79
|
+
|
|
80
|
+
| Line | Drawing | Kit |
|
|
81
|
+
| --- | --- | --- |
|
|
82
|
+
| Main process line | heavy solid, 0.7 mm | `pipe({ kind: "process-major" })` |
|
|
83
|
+
| Minor process line, small bore | solid, 0.5 mm | `"process-minor"` |
|
|
84
|
+
| Utility (cooling water, nitrogen, instrument air, steam) | solid, 0.35 mm | `"utility"` |
|
|
85
|
+
| Instrument supply or process connection, impulse line (Table 5.3.1) | thin solid, 0.18 mm | `connect()` |
|
|
86
|
+
| Electric or electronic signal (4–20 mA, discrete) | dashed | `signal({ type: "electric" })` |
|
|
87
|
+
| Pneumatic signal | double slashes every 6 mm | `"pneumatic"` |
|
|
88
|
+
| Hydraulic signal | L marks | `"hydraulic"` |
|
|
89
|
+
| Filled-system capillary tube | crosses | `"capillary"` |
|
|
90
|
+
| Guided electromagnetic or sonic signal (fibre, guided wave) | sine wave | `"guided"` |
|
|
91
|
+
| Unguided electromagnetic signal (radio, wireless transmitter) | broken sine wave | `"unguided"` |
|
|
92
|
+
| Data link within a control system (DCS bus, fieldbus segment) | small open circles | `"data"` (`"software"` still works) |
|
|
93
|
+
| Mechanical link (a lever, a shaft between two functions) | small filled dots | `"mechanical"` |
|
|
94
|
+
|
|
95
|
+
A signal runs from the transmitter to the controller to the final element. Every loop on the sheet ends at something that acts (a control valve, a pump's speed or stroke input, a heater, a trip), or it is an indication-only loop and has no controller letter. An actuated valve has an `actuator` port at the top of its actuator: run the controller's signal to `valve.port("actuator")`, never to the valve body.
|
|
96
|
+
|
|
97
|
+
## 4. Equipment symbols and tags
|
|
98
|
+
|
|
99
|
+
Equipment tags are a class prefix and a number, with an optional train letter: `R-101` reactor, `V-101` vessel, `TK-101` tank, `D-101` drum, `C-101` column, `E-101` exchanger, `P-101A/B` duty and standby pumps, `K-101` compressor, `BR-101` gas booster, `CH-101` chiller, `F-101` filter, `GC-101` gas cylinder, `M-101` mixer or agitator. The kit draws:
|
|
100
|
+
|
|
101
|
+
- **Vessels** (`vessel`): shell with 2:1 ellipsoidal heads (or flat or conical), tangent lines, optional jacket (`jacket-in` at the bottom, `jacket-out` at the top, so coolant flows upward), agitator with motor (turbine, anchor or propeller), internal coil, packing (a box with its diagonals, ISO 10628-2 item 2.4), trays, demister, legs or skirt, liquid level mark. Trays run across the whole shell as on a tray column (item 2.2); `trayStyle: "staggered"` draws segmental baffles that stop short of the far wall (item 2.5).
|
|
102
|
+
- **Machines** (`pump`, `compressor`): a centrifugal pump is a circle with a tangential discharge on a base; a rotary positive-displacement pump shows two rotors; a metering pump adds the diagonal adjustment arrow. A centrifugal compressor is a circle with converging sides; a reciprocating compressor or gas booster is a circle with a cylinder and rod.
|
|
103
|
+
- **Heat transfer**: a general exchanger or condenser (circle crossed by a zigzag, item 3.1); shell-and-tube with fixed tube sheets (`shellTube()`, item 3.3: shell, a tube sheet at each end, straight tubes), floating head (`type: "floating"`, item 3.4) or U-tubes (`type: "utube"`, item 3.5); plate exchanger (`plateExchanger()`, item 3.6: the pack with both diagonals and a centre line); air-cooled exchanger (`airCooler()`: bundle with its tube run, fan and motor below).
|
|
104
|
+
- **Packaged units**: anything with its own skid (chiller, circulator, analyser, DAQ, booster package) is a box with its caption and declared ports (`unit({ glyph: "coil" | "wave" })`).
|
|
105
|
+
|
|
106
|
+
## 5. Valves, actuators and fail positions
|
|
107
|
+
|
|
108
|
+
Valves are inline symbols on a straight run; the line is gapped under them. Bodies (ISA-5.1 Table 5.4.1, ISO 10628-2 groups 21 and 22): gate (plain bowtie), globe (bowtie with a filled dot), ball (bowtie with an open circle), plug (bowtie with a small square), butterfly (two end bars, the disc on the diagonal, a hub dot), needle (bowtie with a solid point above, for fine metering), diaphragm (bowtie under a bonnet arc), check (bowtie with the solid half pointing along the allowed flow), three-way (a third body on the branch, port `c`). An angle valve (`angleValve({ inlet, outlet })`) sits where the line turns: one body toward each port.
|
|
109
|
+
|
|
110
|
+
Actuators (Table 5.4.2) stand perpendicular to the line and name themselves in the kind, `valve.<body>.<actuator>`: `diaphragm` (spring-opposed pneumatic, the usual control valve), `piston` (cylinder), `motor` (electric, `M`), `solenoid` (on-off, `S`), `hand` (handwheel; `manual` is the same). Fail positions (Table 5.4.4) go beside the actuator as letters: `FO` fail open, `FC` fail closed, `FL` fail locked in its last position, `FI` fail indeterminate; anything else throws. Self-acting devices (Table 5.4.3): a pressure-reducing regulator (`regulator`) senses downstream through its impulse line, a back-pressure regulator (`backPressure: true`) senses upstream; a pressure safety or relief valve (`safetyValve`) has its inlet from below, outlet to the side and spring on top; a rupture disk (`ruptureDisk`) is two bars with the domed disk between them.
|
|
111
|
+
|
|
112
|
+
## 6. Piping items, flow elements and terminals
|
|
113
|
+
|
|
114
|
+
Piping items: concentric reducer (`reducer`) or eccentric reducer (`reducer({ eccentric: true, flat: "bottom" | "top" })`, flat side down on pump suctions), flange pair (`flange`), spectacle blind (`blind`, figure-8: the half in the line is solid when the line is blinded, `state: "open"` turns it to a ring), inline filter or strainer (`filter`), sight glass. Flow elements (ISA-5.1 Table 5.2.3) through `flowElement({ type })`: `orifice` (plate between flanges), `venturi` (converging-diverging throat), and notation boxes for meters without a drawn form of their own, labelled with the Table 5.2.2 notation: `magnetic` MAG, `coriolis` COR, `vortex` VOR, `turbine` TUR, `ultrasonic` US, `thermal` TMF. A variable-area meter (`rotameter`) and a mass flow controller (`mfc`, with a `signal` port) complete the set.
|
|
115
|
+
|
|
116
|
+
Terminals end a line on purpose: vent to atmosphere (`vent`, labelled `ATM` or the vent header), drain, sample point, off-page connector with the destination and drawing number, utility connection (`N2`, `IA`, `CWS`, `CWR`). A line that ends anywhere else is dangling (`LINE.DANGLING`).
|
|
117
|
+
|
|
118
|
+
**Line numbers** read `size-fluid-sequence-class[-insulation]`: `2"-P-1001-A1A`, `1/4"-CH4-101-HP1`, `DN50-CW-205-B1-IH`. On a P&ID the QA gate fails a line number that breaks this form (`LINE.NUMBER`); `parseLineNumber` reads one apart.
|
|
119
|
+
|
|
120
|
+
## 7. Common tags for a high-pressure gas-hydrate loop
|
|
121
|
+
|
|
122
|
+
A hydrate formation rig is a compact high-pressure gas loop; its P&ID usually carries these items, which the kit covers as listed:
|
|
123
|
+
|
|
124
|
+
| Item | Tag | Kit |
|
|
125
|
+
| --- | --- | --- |
|
|
126
|
+
| Gas cylinders (CH₄, CO₂, mixtures) with cylinder regulator | `GC-101`, `PCV-101` | `gasCylinder`, `regulator` |
|
|
127
|
+
| Gas booster raising cylinder gas to test pressure | `BR-101` | `compressor({ type: "reciprocating" })` or `unit` |
|
|
128
|
+
| Buffer or supply vessel | `V-101` | `vessel` |
|
|
129
|
+
| Jacketed stirred high-pressure reactor (sapphire windows optional) | `R-101` | `reactor` |
|
|
130
|
+
| Chiller or circulator on the jacket | `CH-101` | `unit({ glyph: "coil" })` |
|
|
131
|
+
| Reactor pressure and temperature | `PT-101`, `PI-101`, `TE-101`/`TT-101`, `TW-101` | `instrument` |
|
|
132
|
+
| Pressure control (supply regulator or BPR on vent) | `PIC-101`, `PV-101` | `valve({ actuator: "diaphragm" })` |
|
|
133
|
+
| Temperature control on the chiller | `TIC-201` → chiller setpoint | `signal` to the chiller unit |
|
|
134
|
+
| Relief: PSV set below the reactor's design pressure, rupture disk in series or parallel | `PSV-101`, `PSE-101` | `safetyValve`, `ruptureDisk` |
|
|
135
|
+
| Gas flow into the reactor | `FT-101`, `FQI-101` (consumed gas) | `instrument`, `mfc` |
|
|
136
|
+
| Sampling to GC | `SP-101`, `AT-101` | `samplePoint`, `instrument` |
|
|
137
|
+
| Vent to a safe location | `ATM` or `TO VENT HEADER` | `vent`, `offPage` |
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
## 8. Standards basis, symbol by symbol
|
|
141
|
+
|
|
142
|
+
Where each drawn form comes from, so a reviewer can check it against the project's own licensed copies. ISO 10628-2:2012 numbers its symbols by subject group (Table 1) and item (Table 2: group.item with an ISO 14617 registration number); ANSI/ISA-5.1-2009 groups instrument symbols in tables 4.1 and 5.1.1 to 5.4.4. Where the kit follows common US practice (PIP PIC001) rather than a numbered entry, the row says so.
|
|
143
|
+
|
|
144
|
+
| Kit kind | Basis |
|
|
145
|
+
| --- | --- |
|
|
146
|
+
| `vessel.*`, `vessel.horizontal`, `vessel.tank`, `gas.cylinder` | ISO 10628-2 group 1 (vessels and tanks): items 1.5 dished ends, 1.3 cone roof tank, 1.13 drum, 1.14 gas cylinder, 1.27 jacketed vessel |
|
|
147
|
+
| `vessel.column` | ISO 10628-2 group 2: 2.2 tray column (full-width trays, default), 2.4 fixed bed (packing), 2.5 staggered baffles |
|
|
148
|
+
| `exchanger.general`, `.shelltube`, `.floating`, `.utube`, `.plate` | ISO 10628-2 group 3: 3.1, 3.3, 3.4, 3.5, 3.6 |
|
|
149
|
+
| `exchanger.aircooler` | ISO 10628-2 group 3 (air cooler); drawn as bundle, fan and motor after common practice |
|
|
150
|
+
| `pump.*` | ISO 10628-2 group 15 (liquid pumps); centrifugal form with tangential discharge after PIP practice |
|
|
151
|
+
| `compressor.*` | ISO 10628-2 group 16 (compressors) |
|
|
152
|
+
| `valve.<body>` | ISA-5.1 Table 5.4.1; ISO 10628-2 group 21 (valves), group 22 (check valves) |
|
|
153
|
+
| `valve.<body>.<actuator>`, fail letters | ISA-5.1 Table 5.4.2 (actuators), Table 5.4.4 (failure and de-energised positions) |
|
|
154
|
+
| `valve.regulator`, `.backpressure`, `.safety`, `relief.rupture` | ISA-5.1 Table 5.4.3 (self-actuated final control elements); ISO 10628-2 group 23 (safety function) |
|
|
155
|
+
| `line.reducer*`, `line.flange`, `line.blind*`, `line.filter`, `line.sightglass` | ISO 10628-2 groups 24 (fittings) and 25 (piping); spectacle blind form after PIP practice |
|
|
156
|
+
| `flow.orifice`, `flow.venturi`, `flow.<meter>` | ISA-5.1 Table 5.2.3 (primary elements) and Table 5.2.2 (measurement notations MAG, COR, VOR, TUR, US, TMF) |
|
|
157
|
+
| `instrument.<fn>-<location>` | ISA-5.1 Table 5.1.1 (device and function symbols by location) |
|
|
158
|
+
| `logic.interlock` | ISA-5.1 binary logic (Table 5.7) as a diamond with its number |
|
|
159
|
+
| Pipe classes and widths | ISO 128 line-width series; ISO 10628-1 (main lines heavier than others) |
|
|
160
|
+
| Signal lines | ISA-5.1 Table 5.3.1 (instrument to process) and Table 5.3.2 (instrument to instrument) |
|
|
161
|
+
| Identification letters, tags | ISA-5.1 Table 4.1 |
|
|
162
|
+
|
|
163
|
+
The standalone legend sheet (`createLegendSheet`, `scripts/lib/legend-sheet.mjs`) prints every row of this vocabulary from the library itself, so the sheet a drawing set opens with never drifts from what the kit draws.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Verification
|
|
2
|
+
|
|
3
|
+
Look at the drawing the way its harshest reader will, before anyone else does. Rendering is cheap; a reviewer finding a line through a vessel costs a revision.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
1. The loop
|
|
7
|
+
2. The QA gate: every code and its fix
|
|
8
|
+
3. Render and look
|
|
9
|
+
4. The close-up sweep
|
|
10
|
+
5. Review checklist
|
|
11
|
+
6. Exports
|
|
12
|
+
|
|
13
|
+
## 1. The loop
|
|
14
|
+
|
|
15
|
+
1. Build → `node "$SKILL_ROOT/scripts/qa.mjs" drawing.svg`.
|
|
16
|
+
2. Fix every FAIL **in the build script**, rebuild, re-run QA until `QA PASS`.
|
|
17
|
+
3. Render (`render.mjs --png --dpi 600`) and open the PNG. Read it in the order of section 3. QA reads the SVG, never the PNG, so the renderer checks the PNG itself: it compares the ink in 36 regions against a small reference render of the same page, and a region that holds ink there but came out blank means the browser stopped painting (it happens above roughly 60 to 80 million pixels, an A2 sheet at 600 dpi). The renderer then steps the dpi down until the page arrives whole and prints `reduced from 600`; if it cannot, it stops with `RENDER_INCOMPLETE`. A reduced dpi on a large sheet is fine for reading; the PDF stays vector, and `--crop` gives any region at full resolution.
|
|
18
|
+
4. For anything denser than a dozen symbols or parts, render the close-up sweep (`--sheet sweep.png --grid 3x2`, or `4x3` for an A1 sheet) and read every cell.
|
|
19
|
+
5. Fix what the eye found, rebuild, re-run QA, re-render. Stop when QA passes and the last render shows nothing to fix.
|
|
20
|
+
|
|
21
|
+
QA is necessary, never sufficient: it reads geometry and markers, not appearance. It cannot see a leader dot on a face hidden behind another part, a nozzle standing on a cut-away shell, a misleading symbol choice, or a crowded corner that is technically clear. The look is the gate that catches those.
|
|
22
|
+
|
|
23
|
+
## 2. The QA gate: every code and its fix
|
|
24
|
+
|
|
25
|
+
`qa.mjs` parses the SVG itself (no browser), applies every transform and reads the markers the kit writes (`data-sym`, `data-box`, `data-ports`, `data-line`, `data-part`, `data-hull`, `data-leader`, `data-panel`, `data-legend-item`, `data-within`). Unmarked geometry still counts for strokes and text, so a hand-edited SVG cannot slip past by dropping markers. `--json` gives the same result as JSON; `--codes` lists the codes.
|
|
26
|
+
|
|
27
|
+
| Code | Meaning | Fix in the build |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| `XML.WELLFORMED` | The SVG does not parse. | Rebuild; never hand-edit the output. |
|
|
30
|
+
| `XML.EXTERNAL` | It loads an outside file or URL. | Inline it or drop it. |
|
|
31
|
+
| `SVG.ACTIVE` | Script or event handlers. | Remove them; a schematic is static. |
|
|
32
|
+
| `SVG.SIZE` | No physical width/height or viewBox. | Use `createSheet` / `createFigure`, which write mm sizes. |
|
|
33
|
+
| `TEXT.MIN_SIZE` | Text under the floor at print size (5.6 pt on sheets, 6 pt on figures). | Spread the layout or shorten the text; never shrink it. |
|
|
34
|
+
| `TEXT.OVERLAP` | Two labels overlap. | Move a symbol; the placer then finds room. |
|
|
35
|
+
| `TEXT.ON_SYMBOL` | A label sits on a symbol it does not belong to. | Move the label's owner or the symbol. |
|
|
36
|
+
| `TEXT.ON_ART` | A label sits on the isometric art. | Use `callout`, which places labels beside the art. |
|
|
37
|
+
| `TEXT.ON_LINE` | A line runs through a label. | Re-route (`via`) or move the label's owner. |
|
|
38
|
+
| `TEXT.CLIPPED` | A label runs past the drawing edge. | Widen the panel or shorten the label. |
|
|
39
|
+
| `TEXT.OUT_OF_CELL` | Text overflows its title-block cell, legend or notes block. | Shorten it, or move to a larger sheet. |
|
|
40
|
+
| `LINE.THROUGH_SYMBOL` | A line passes through a symbol. | Let the router route it, add `via`, or move the symbol. |
|
|
41
|
+
| `LINE.DANGLING` | A line end touches no port, line or terminal. | End it on a port, a `tap`, or a vent/drain/off-page terminal. |
|
|
42
|
+
| `LINE.BEND_ON_LINE` | A line turns on another line. | Move the waypoint; corners on lines read as junctions. |
|
|
43
|
+
| `LINE.OVERLAP` | Two lines share a track. | Give one a different lane. |
|
|
44
|
+
| `LINE.CROSSING` (warn) | Process lines cross without a hop. | Hand-drawn lines: route through the canvas so later lines hop. |
|
|
45
|
+
| `LINE.ARROW_IN_SYMBOL` | A flow arrow is drawn inside a valve, instrument or other body, where it reads as part of the symbol. | Let the canvas place arrows, or give `arrows` fractions that fall on open pipe; the canvas already slides an asked-for arrow off a body and warns when it cannot. |
|
|
46
|
+
| `LEADER.LOOSE` | A leader does not run from its label to a dot on its named part. | Use `callout({ part })` and anchor on that part. |
|
|
47
|
+
| `LEADER.CROSSING` | Two leaders cross. | Reorder anchors or move one callout to the other side. |
|
|
48
|
+
| `LEADER.SPACING` | A leader runs within 1.2 mm (print size) of another leader or of another leader's dot, so two read as one. | Move one dot to a clearer spot on its part (another face, further along the body), or send that label to the other side. The placer already reorders labels and opens rows to separate them; what it cannot clear it lists in `fig.warnings()`. |
|
|
49
|
+
| `STROKE.MIN` | A stroke under 0.25 pt. | Thicken it; hairlines vanish in print. |
|
|
50
|
+
| `SYMBOL.NO_BOX` | A symbol group without its box. | Draw symbols with the kit factories. |
|
|
51
|
+
| `TAG.GRAMMAR` | A tag breaks ISA-5.1 or the equipment pattern. | See `pid-symbols.md` section 1. |
|
|
52
|
+
| `LINE.NUMBER` | A P&ID line number is not size-fluid-sequence-class[-insulation]. | Write it as `2"-P-1001-A1A`; see `pid-symbols.md` section 6. |
|
|
53
|
+
| `TAG.DUPLICATE` | Two items share a tag. | Number loops and trains uniquely. |
|
|
54
|
+
| `LEGEND.COVERAGE` | A sheet draws a kind the legend lacks; a figure draws a stream role its key lacks. | Let the sheet build its legend; add the role to `fig.key`. |
|
|
55
|
+
| `TITLEBLOCK.FIELDS` | Title, number, revision, date or scale empty. | Fill them in `createSheet`. |
|
|
56
|
+
| `PALETTE.CVD` | Two stream colours are too close for some reader. | Use the `STREAM` roles; never invent colours for categories. |
|
|
57
|
+
| `PANEL.LABELS` | Panel labels missing, out of order, unequal or misplaced. | Use `fig.panel("a", …)` in reading order. |
|
|
58
|
+
| `FONT.FAMILIES` (warn) | More than two families. | Arial for Latin, Pretendard for Hangul. |
|
|
59
|
+
|
|
60
|
+
## 3. Render and look
|
|
61
|
+
|
|
62
|
+
Open the PNG at a size where the whole drawing fits, then read it in this order:
|
|
63
|
+
|
|
64
|
+
1. **Lines.** Every line runs from a port to a port, a junction or a terminal; nothing passes through a body; crossings are hops at right angles on straights; no line hugs another.
|
|
65
|
+
2. **Labels.** Nothing on a line, a symbol or the art; every label next to its owner; tags readable.
|
|
66
|
+
3. **Topology.** Trace each stream from source to destination; trace each control loop from element to final element; trace each relief path to its discharge.
|
|
67
|
+
4. **Isometric order.** Nothing behind shows through anything in front; the ground is under everything; tubes, baffles and pipes interleave correctly.
|
|
68
|
+
5. **Cutaways.** Nozzles and brackets stand on closed shell; internals stay inside the wall; the cut faces read as wall thickness.
|
|
69
|
+
6. **Leaders.** Each dot is on the face of the part its label names and on a face the viewer can see.
|
|
70
|
+
7. **Detail.** At this size the drawing reads as one machine or one process; no region is bare where the real thing has parts.
|
|
71
|
+
|
|
72
|
+
## 4. The close-up sweep
|
|
73
|
+
|
|
74
|
+
`render.mjs drawing.svg --sheet sweep.png --grid 3x2` renders every region of the drawing enlarged in one image, each cell captioned with its viewBox box. Read every cell for: line ends a hair short of a port, hops that clip a junction, arrowheads on dots, text touching strokes, bolt circles that stop in mid-face, seams that miss the outline, tone steps on a curved body. To inspect one region at print resolution: `render.mjs drawing.svg --crop x,y,w,h --png close.png --dpi 1200`.
|
|
75
|
+
|
|
76
|
+
## 5. Review checklist
|
|
77
|
+
|
|
78
|
+
**Content**
|
|
79
|
+
- [ ] Every number on the drawing comes from the brief, or is listed in the reply as an assumption.
|
|
80
|
+
- [ ] Every vessel that can be over-pressured has a relief device with a discharge destination.
|
|
81
|
+
- [ ] Every controller has a measurement and a final element; every instrument has a process connection.
|
|
82
|
+
- [ ] Isolation valves on both sides of control valves and instruments where the process requires them.
|
|
83
|
+
|
|
84
|
+
**Drawing**
|
|
85
|
+
- [ ] `QA PASS` on the final SVG.
|
|
86
|
+
- [ ] Flow reads left to right; gravity is respected.
|
|
87
|
+
- [ ] The legend and title block are complete (sheets); the key covers every stream role (figures).
|
|
88
|
+
- [ ] Line weights follow the hierarchy; text sizes meet the floor at print size.
|
|
89
|
+
|
|
90
|
+
**Isometric**
|
|
91
|
+
- [ ] It reads as the real equipment; 40+ parts; each part in its real material colour (grey only on request), at most one accent; halo under the base.
|
|
92
|
+
- [ ] Painter's order correct everywhere; interleaving parts split.
|
|
93
|
+
- [ ] Leaders end on visible faces of their parts; none cross.
|
|
94
|
+
|
|
95
|
+
**Exports**
|
|
96
|
+
- [ ] PNG at 600 dpi or more, pHYs written; PDF page equals the drawing size; both opened.
|
|
97
|
+
|
|
98
|
+
## 6. Exports
|
|
99
|
+
|
|
100
|
+
`qa.mjs drawing.svg --png drawing.png --pdf drawing.pdf [--dpi 600]` adds `PNG.CLOSED` (truncated file or bad checksum), `PNG.DPI` (declared resolution under the requirement, or pixel width that does not match the drawing width at that resolution), `PDF.CLOSED` (no header or end marker) and `PDF.SIZE` (page size differs from the drawing by more than 1 mm). A sheet larger than about 16 000 px at the requested resolution is rendered at the highest resolution Chrome can capture and the render line says so; render crops for a larger print.
|