@things-factory/figure-service 10.1.208 โ 10.1.212
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/README.md +1 -1
- package/dist-server/service/figure/event-subscriber.js +2 -2
- package/dist-server/service/figure/event-subscriber.js.map +1 -1
- package/dist-server/service/figure/figure-context.d.ts +2 -1
- package/dist-server/service/figure/figure-context.js +2 -1
- package/dist-server/service/figure/figure-context.js.map +1 -1
- package/dist-server/service/figure/figure-format.js +1 -1
- package/dist-server/service/figure/figure-format.js.map +1 -1
- package/dist-server/service/figure/figure-mutation.d.ts +5 -5
- package/dist-server/service/figure/figure-mutation.js +6 -6
- package/dist-server/service/figure/figure-mutation.js.map +1 -1
- package/dist-server/service/figure/figure-query.d.ts +3 -3
- package/dist-server/service/figure/figure-query.js +4 -4
- package/dist-server/service/figure/figure-query.js.map +1 -1
- package/dist-server/service/figure/figure-rename.d.ts +4 -4
- package/dist-server/service/figure/figure-rename.js +2 -2
- package/dist-server/service/figure/figure-rename.js.map +1 -1
- package/dist-server/service/figure/figure-tools.js +9 -9
- package/dist-server/service/figure/figure-tools.js.map +1 -1
- package/dist-server/service/figure/figure-type.d.ts +2 -2
- package/dist-server/service/figure/figure-type.js +2 -2
- package/dist-server/service/figure/figure-type.js.map +1 -1
- package/dist-server/service/figure/figure.d.ts +2 -2
- package/dist-server/service/figure/figure.js +1 -1
- package/dist-server/service/figure/figure.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/recipes/_lib/model.mts +12 -8
- package/recipes/air-cylinder/models/default.json +1 -1
- package/recipes/air-cylinder/recipe.json +13 -10
- package/recipes/air-cylinder/spec.json +1 -1
- package/recipes/air-shower/models/default.json +1 -1
- package/recipes/air-shower/recipe.json +11 -8
- package/recipes/barrier-gate/models/default.json +1 -1
- package/recipes/barrier-gate/recipe.json +11 -7
- package/recipes/base-frame/models/default.json +1 -1
- package/recipes/base-frame/recipe.json +0 -4
- package/recipes/belt-surface/guide.ko.md +1 -1
- package/recipes/belt-surface/models/default.json +1 -1
- package/recipes/belt-surface/recipe.json +0 -1
- package/recipes/bin-row/models/default.json +1 -1
- package/recipes/bin-row/recipe.json +0 -1
- package/recipes/bollard-row/models/default.json +1 -1
- package/recipes/bollard-row/recipe.json +0 -1
- package/recipes/buzzer/models/default.json +1 -1
- package/recipes/buzzer/recipe.json +0 -1
- package/recipes/cabinet-doors/build.mts +1 -1
- package/recipes/cabinet-doors/models/default.json +1 -1
- package/recipes/cabinet-doors/models/doors=1.json +1 -1
- package/recipes/cabinet-doors/models/doors=2.json +1 -1
- package/recipes/cabinet-doors/recipe.json +21 -13
- package/recipes/cable-tray/models/default.json +1 -1
- package/recipes/cable-tray/recipe.json +0 -3
- package/recipes/camera-mount/models/default.json +1 -1
- package/recipes/camera-mount/recipe.json +11 -8
- package/recipes/canopy/models/default.json +1 -1
- package/recipes/canopy/recipe.json +0 -5
- package/recipes/cart/models/default.json +1 -1
- package/recipes/cart/recipe.json +0 -12
- package/recipes/cart-handle/models/default.json +1 -1
- package/recipes/cart-handle/recipe.json +0 -3
- package/recipes/casters-four/models/default.json +1 -1
- package/recipes/casters-four/recipe.json +0 -8
- package/recipes/ceiling-rail-carriage/build.mts +1 -1
- package/recipes/ceiling-rail-carriage/models/default.json +1 -1
- package/recipes/ceiling-rail-carriage/recipe.json +19 -16
- package/recipes/chain-rails/models/default.json +1 -1
- package/recipes/chain-rails/recipe.json +0 -2
- package/recipes/charging-station/models/default.json +1 -1
- package/recipes/charging-station/recipe.json +0 -2
- package/recipes/column-row/models/default.json +1 -1
- package/recipes/column-row/recipe.json +0 -1
- package/recipes/control-cabinet/models/default.json +1 -1
- package/recipes/control-cabinet/recipe.json +11 -8
- package/recipes/conveyor-skirts/models/default.json +1 -1
- package/recipes/conveyor-skirts/recipe.json +0 -2
- package/recipes/counter-display/models/default.json +1 -1
- package/recipes/counter-display/recipe.json +0 -2
- package/recipes/dock-bumpers/models/default.json +1 -1
- package/recipes/dock-bumpers/recipe.json +0 -2
- package/recipes/dock-leveler/models/default.json +1 -1
- package/recipes/dock-leveler/recipe.json +11 -7
- package/recipes/double-hinged-door/build.mts +1 -1
- package/recipes/double-hinged-door/models/default.json +1 -1
- package/recipes/double-hinged-door/recipe.json +21 -14
- package/recipes/drawer-stack/models/default.json +1 -1
- package/recipes/drawer-stack/models/drawers=2.json +1 -1
- package/recipes/drawer-stack/models/drawers=3.json +1 -1
- package/recipes/drawer-stack/models/drawers=4.json +1 -1
- package/recipes/drawer-stack/recipe.json +99 -63
- package/recipes/drip-tray/models/default.json +1 -1
- package/recipes/drip-tray/recipe.json +0 -1
- package/recipes/duct-fan/models/default.json +1 -1
- package/recipes/duct-fan/recipe.json +11 -8
- package/recipes/emergency-stop/models/default.json +1 -1
- package/recipes/emergency-stop/recipe.json +11 -8
- package/recipes/end-covers/models/default.json +1 -1
- package/recipes/end-covers/recipe.json +0 -2
- package/recipes/ffu-row/models/default.json +1 -1
- package/recipes/ffu-row/recipe.json +0 -1
- package/recipes/fire-extinguisher/models/default.json +1 -1
- package/recipes/fire-extinguisher/recipe.json +0 -2
- package/recipes/first-aid-box/models/default.json +1 -1
- package/recipes/first-aid-box/recipe.json +0 -2
- package/recipes/floor-zone/models/default.json +1 -1
- package/recipes/floor-zone/recipe.json +0 -4
- package/recipes/folding-door/build.mts +1 -1
- package/recipes/folding-door/models/default.json +1 -1
- package/recipes/folding-door/recipe.json +21 -14
- package/recipes/fork/build.mts +1 -1
- package/recipes/fork/models/default.json +1 -1
- package/recipes/fork/recipe.json +23 -15
- package/recipes/fork/spec.json +1 -1
- package/recipes/gantry-frame/models/default.json +1 -1
- package/recipes/gantry-frame/recipe.json +0 -3
- package/recipes/gripper-2f/build.mts +1 -1
- package/recipes/gripper-2f/models/default.json +1 -1
- package/recipes/gripper-2f/recipe.json +23 -16
- package/recipes/gripper-2f/spec.json +1 -1
- package/recipes/guard-cover/models/default.json +1 -1
- package/recipes/guard-cover/recipe.json +11 -7
- package/recipes/handrail/models/default.json +1 -1
- package/recipes/handrail/recipe.json +0 -2
- package/recipes/hatch/models/default.json +1 -1
- package/recipes/hatch/recipe.json +11 -8
- package/recipes/hinged-door/build.mts +2 -3
- package/recipes/hinged-door/models/default.json +1 -1
- package/recipes/hinged-door/models/hinge=left.json +1 -1
- package/recipes/hinged-door/models/hinge=right.json +1 -1
- package/recipes/hinged-door/recipe.json +22 -15
- package/recipes/hmi-monitor/models/default.json +1 -1
- package/recipes/hmi-monitor/recipe.json +11 -8
- package/recipes/hopper/models/default.json +1 -1
- package/recipes/hopper/recipe.json +0 -2
- package/recipes/interlock-switch/models/default.json +1 -1
- package/recipes/interlock-switch/recipe.json +0 -1
- package/recipes/junction-box/models/default.json +1 -1
- package/recipes/junction-box/recipe.json +0 -1
- package/recipes/ladder/models/default.json +1 -1
- package/recipes/ladder/recipe.json +0 -3
- package/recipes/legs-four/models/default.json +1 -1
- package/recipes/legs-four/recipe.json +0 -4
- package/recipes/leveling-feet/models/default.json +1 -1
- package/recipes/leveling-feet/recipe.json +0 -4
- package/recipes/lift-updown/models/default.json +1 -1
- package/recipes/lift-updown/recipe.json +13 -9
- package/recipes/lift-updown/spec.json +1 -1
- package/recipes/light-curtain/models/default.json +1 -1
- package/recipes/light-curtain/recipe.json +0 -2
- package/recipes/limit-switch/models/default.json +1 -1
- package/recipes/limit-switch/recipe.json +11 -8
- package/recipes/linear-guide/build.mts +1 -1
- package/recipes/linear-guide/models/default.json +1 -1
- package/recipes/linear-guide/recipe.json +19 -16
- package/recipes/locker-row/models/default.json +1 -1
- package/recipes/locker-row/recipe.json +0 -1
- package/recipes/motor-box/models/default.json +1 -1
- package/recipes/motor-box/recipe.json +0 -1
- package/recipes/observation-window/models/default.json +1 -1
- package/recipes/observation-window/recipe.json +0 -2
- package/recipes/operator-panel/models/buttons=2.json +1 -1
- package/recipes/operator-panel/models/buttons=3.json +1 -1
- package/recipes/operator-panel/models/buttons=4.json +1 -1
- package/recipes/operator-panel/models/buttons=5.json +1 -1
- package/recipes/operator-panel/models/default.json +1 -1
- package/recipes/operator-panel/recipe.json +0 -5
- package/recipes/pallet/models/default.json +1 -1
- package/recipes/pallet/recipe.json +0 -4
- package/recipes/partition-wall/models/default.json +1 -1
- package/recipes/partition-wall/recipe.json +0 -3
- package/recipes/pass-box/models/default.json +1 -1
- package/recipes/pass-box/recipe.json +11 -8
- package/recipes/peg-board/models/default.json +1 -1
- package/recipes/peg-board/recipe.json +0 -2
- package/recipes/photo-sensor-pair/models/default.json +1 -1
- package/recipes/photo-sensor-pair/recipe.json +0 -2
- package/recipes/pipe-run/models/default.json +1 -1
- package/recipes/pipe-run/recipe.json +0 -1
- package/recipes/platform/models/default.json +1 -1
- package/recipes/platform/recipe.json +0 -5
- package/recipes/power-box/models/default.json +1 -1
- package/recipes/power-box/recipe.json +0 -1
- package/recipes/pressure-gauge/models/default.json +1 -1
- package/recipes/pressure-gauge/recipe.json +0 -1
- package/recipes/pull-cord/models/default.json +1 -1
- package/recipes/pull-cord/recipe.json +0 -1
- package/recipes/pump/models/default.json +1 -1
- package/recipes/pump/recipe.json +0 -2
- package/recipes/pusher/build.mts +1 -1
- package/recipes/pusher/models/default.json +1 -1
- package/recipes/pusher/recipe.json +19 -15
- package/recipes/robot-plinth/models/default.json +1 -1
- package/recipes/robot-plinth/recipe.json +0 -2
- package/recipes/roll-up-shutter/build.mts +1 -1
- package/recipes/roll-up-shutter/models/default.json +1 -1
- package/recipes/roll-up-shutter/recipe.json +19 -16
- package/recipes/roller-row/facts.md +1 -1
- package/recipes/roller-row/guide.ko.md +1 -1
- package/recipes/roller-row/models/default.json +1 -1
- package/recipes/roller-row/recipe.json +11 -7
- package/recipes/room-shell/models/default.json +1 -1
- package/recipes/room-shell/recipe.json +0 -5
- package/recipes/rotating-beacon/models/default.json +1 -1
- package/recipes/rotating-beacon/recipe.json +11 -9
- package/recipes/safety-fence/models/default.json +1 -1
- package/recipes/safety-fence/recipe.json +0 -2
- package/recipes/safety-mat/models/default.json +1 -1
- package/recipes/safety-mat/recipe.json +0 -1
- package/recipes/safety-sign-stand/models/default.json +1 -1
- package/recipes/safety-sign-stand/recipe.json +0 -3
- package/recipes/scanner-mount/models/default.json +1 -1
- package/recipes/scanner-mount/recipe.json +0 -3
- package/recipes/selector-switch/models/default.json +1 -1
- package/recipes/selector-switch/recipe.json +11 -8
- package/recipes/shelf-tiers/models/default.json +1 -1
- package/recipes/shelf-tiers/models/tiers=2.json +1 -1
- package/recipes/shelf-tiers/models/tiers=3.json +1 -1
- package/recipes/shelf-tiers/models/tiers=4.json +1 -1
- package/recipes/shelf-tiers/models/tiers=5.json +1 -1
- package/recipes/shelf-tiers/recipe.json +0 -4
- package/recipes/side-guides/models/default.json +1 -1
- package/recipes/side-guides/recipe.json +0 -2
- package/recipes/sign-board/models/default.json +1 -1
- package/recipes/sign-board/recipe.json +0 -1
- package/recipes/signal-tower-3/build.mts +1 -1
- package/recipes/signal-tower-3/models/default.json +1 -1
- package/recipes/signal-tower-3/recipe.json +11 -10
- package/recipes/sliding-door/build.mts +4 -7
- package/recipes/sliding-door/facts.md +1 -1
- package/recipes/sliding-door/guide.ko.md +1 -1
- package/recipes/sliding-door/models/default.json +1 -1
- package/recipes/sliding-door/models/leaves=1,lamp=false.json +1 -1
- package/recipes/sliding-door/models/leaves=1,lamp=true.json +1 -1
- package/recipes/sliding-door/models/leaves=2,lamp=false.json +1 -1
- package/recipes/sliding-door/models/leaves=2,lamp=true.json +1 -1
- package/recipes/sliding-door/recipe.json +48 -38
- package/recipes/stairs/models/default.json +1 -1
- package/recipes/stairs/recipe.json +0 -1
- package/recipes/status-lamp/models/default.json +1 -1
- package/recipes/status-lamp/recipe.json +11 -9
- package/recipes/stopper/models/default.json +1 -1
- package/recipes/stopper/recipe.json +11 -7
- package/recipes/suction-pads/models/default.json +1 -1
- package/recipes/suction-pads/recipe.json +0 -1
- package/recipes/tank/models/default.json +1 -1
- package/recipes/tank/recipe.json +0 -1
- package/recipes/telescopic-arm/build.mts +1 -1
- package/recipes/telescopic-arm/models/default.json +1 -1
- package/recipes/telescopic-arm/recipe.json +21 -13
- package/recipes/toe-board/models/default.json +1 -1
- package/recipes/toe-board/recipe.json +0 -1
- package/recipes/tote/models/default.json +1 -1
- package/recipes/tote/recipe.json +0 -1
- package/recipes/traffic-cones/models/default.json +1 -1
- package/recipes/traffic-cones/recipe.json +0 -2
- package/recipes/transfer-belts/build.mts +1 -1
- package/recipes/transfer-belts/models/default.json +1 -1
- package/recipes/transfer-belts/recipe.json +23 -15
- package/recipes/transfer-belts/spec.json +1 -1
- package/recipes/tray-stack/models/default.json +1 -1
- package/recipes/tray-stack/models/trays=3.json +1 -1
- package/recipes/tray-stack/models/trays=4.json +1 -1
- package/recipes/tray-stack/models/trays=5.json +1 -1
- package/recipes/tray-stack/recipe.json +0 -5
- package/recipes/trough/models/default.json +1 -1
- package/recipes/trough/recipe.json +0 -1
- package/recipes/turntable/models/default.json +1 -1
- package/recipes/turntable/recipe.json +11 -8
- package/recipes/valve-handle/models/default.json +1 -1
- package/recipes/valve-handle/recipe.json +11 -9
- package/recipes/waste-bin/models/default.json +1 -1
- package/recipes/waste-bin/recipe.json +0 -1
- package/recipes/work-light/models/default.json +1 -1
- package/recipes/work-light/recipe.json +11 -9
- package/recipes/workbench-top/models/default.json +1 -1
- package/recipes/workbench-top/recipe.json +0 -1
- package/server/service/figure/catalog-db.test.ts +1 -1
- package/server/service/figure/event-subscriber.ts +2 -2
- package/server/service/figure/figure-blueprint-query.test.ts +3 -3
- package/server/service/figure/figure-context.test.ts +3 -3
- package/server/service/figure/figure-context.ts +4 -2
- package/server/service/figure/figure-format.test.ts +7 -7
- package/server/service/figure/figure-format.ts +1 -1
- package/server/service/figure/figure-llm-smoke.test.ts +1 -1
- package/server/service/figure/figure-mutation.ts +6 -6
- package/server/service/figure/figure-propose-clips.test.ts +1 -1
- package/server/service/figure/figure-propose-steps.test.ts +2 -2
- package/server/service/figure/figure-query.ts +4 -4
- package/server/service/figure/figure-release-record-db.test.ts +3 -3
- package/server/service/figure/figure-rename-db.test.ts +2 -2
- package/server/service/figure/figure-rename.test.ts +3 -3
- package/server/service/figure/figure-rename.ts +6 -6
- package/server/service/figure/figure-subject.test.ts +1 -1
- package/server/service/figure/figure-tools.test.ts +19 -19
- package/server/service/figure/figure-tools.ts +9 -9
- package/server/service/figure/figure-type.ts +2 -2
- package/server/service/figure/figure.ts +2 -2
- package/translations/ko.json +31 -31
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figure-query.js","sourceRoot":"","sources":["../../../server/service/figure/figure-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { In } from 'typeorm'\nimport { Args, Arg, Ctx, Directive, Int, Query, Resolver, UseMiddleware } from 'type-graphql'\nimport { GraphQLJSON } from 'graphql-scalars'\n\nimport {\n Domain,\n getQueryBuilderFromListParams,\n getRepository,\n ListParam,\n Refusal,\n SpeakRefusals,\n refusalKey\n} from '@things-factory/shell'\nimport { formatFigureRef, parseFigureName, type FigureName } from '@hatiolab/figure-model'\n\nimport { Figure } from './figure.js'\nimport { FigureHistory } from './figure-history.js'\nimport { consumablePayloadOf, inspectSource } from './figure-format.js'\nimport { FigureInspection, FigureList, FigureProposalOutcome } from './figure-type.js'\nimport { FigureReplacedDraft } from './figure-replaced-draft.js'\nimport { replacedDraftsOf } from './figure-revert.js'\nimport { proposalOutcomeOf } from './figure-proposal.js'\nimport { meshSummaryOf } from './figure-mesh-store.js'\nimport { readableFigure, publicFigureOfName } from './figure-public.js'\nimport { figureCategories } from './figure-categories.js'\n\n@Resolver(Figure)\n@UseMiddleware(SpeakRefusals)\nexport class FigureQuery {\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => Figure, { nullable: true, description: 'Finds a single figure by its ID.' })\n async figure(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Figure> {\n const { domain } = context.state\n\n // ๋ถ๋ชจ ๋๋ฉ์ธ์ Figure ๋ ๋ณด์ธ๋ค โ Board ์ ๊ฐ์ ๋ฒ์ ๊ท์น์ด๋ค.\n return await getRepository(Figure).findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id }\n })\n }\n\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => FigureList, { description: 'Lists figures. Sortable by score, triangles, name, updatedAt.' })\n async figures(@Args() params: ListParam, @Ctx() context: ResolverContext): Promise<FigureList> {\n const { domain } = context.state\n\n const queryBuilder = getQueryBuilderFromListParams({\n repository: getRepository(Figure),\n params,\n domain,\n alias: 'figure',\n /*\n `tags` ๋ ์ฐพ์ ์ ์์ด์ผ ํ๋ค โ ํ๊ทธ์ ๊ฐ์ ๋ถ์ด๋ ๋ฐ ์์ง ์๊ณ **์ฐพ๋ ๋ฐ** ์๋ค.\n\n `simple-json` ์ด๋ผ ์นธ์๋ `[\"๋ฐ์ถ\",\"์๋\"]` ์ด ํต์งธ๋ก ๋ค์ด ์๊ณ , LIKE ๋ ๊ทธ ๊ธ์๋ฅผ\n ๋ณธ๋ค. ใ๋ฐ์ถใ๋ก ์ฐพ์ผ๋ฉด ๊ฑธ๋ฆฐ๋ค. ์ ํํ ๊ทธ ํ๊ทธ๋ง ๊ฑธ๋ฆฌ๋ ๊ฒ์ ์๋์ง๋ง(์ด๋ฆ์ ใ๋ฐ์ถใ์ด\n ๋ ๋ํ๋ ๊ฑธ๋ฆฐ๋ค) ์ฐพ๊ธฐ๋ก๋ ๊ทธ๊ฒ์ด ์คํ๋ ค ๋ซ๋ค.\n */\n searchables: ['type', 'name', 'description', 'category', 'tags']\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n /**\n * Other domains' public figures (LV figure-server design G2): what this domain may read, package and draw besides its\n * own and its parent's. The rows carry their domain, so a screen says whose each is. Their drafts are not opened.\n */\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => FigureList, { description: \"Other domains' public figures. Read only: their releases, never their drafts.\" })\n async publicFigures(@Args() params: ListParam, @Ctx() context: ResolverContext): Promise<FigureList> {\n const { domain } = context.state\n const mine = [domain.id, domain.parentId].filter(Boolean)\n const queryBuilder = getQueryBuilderFromListParams({\n repository: getRepository(Figure),\n params,\n alias: 'figure',\n searchables: ['type', 'name', 'description', 'category', 'tags']\n })\n .leftJoinAndSelect('figure.domain', 'owner')\n .andWhere('figure.public = :public', { public: true })\n .andWhere('owner.id NOT IN (:...mine)', { mine })\n const [items, total] = await queryBuilder.getManyAndCount()\n return { items, total }\n }\n\n /**\n * ๋ฑ๋ก๋ ํ์
์ด๋ฆ ๋ชฉ๋ก.\n *\n * ์ ์ ํ๋ฉด์ด **์ ํ์
์ด๋ฆ์ด ์ด๋ฏธ ์ฐ์ด๋์ง** ๋ฌผ์ด๋ณด๋ ๋ฐ ์ด๋ค. `type` ์ ์ ์ฅ๋๋\n * ์๋ณ์๋ผ ๋ง๋ ๋ค์ ๊ณ ์น ์ ์์ผ๋ฏ๋ก, ๋ง๋ค๊ธฐ ์ ์ ์๋ ค ์ค์ผ ํ๋ค.\n *\n * `state` ๋ก ๊ฑธ๋ฌ์ง์ง ์๋๋ค โ `draft` ์ธ Figure ์ ์ด๋ฆ๋ ์ด๋ฏธ ์ ์ ๋ ๊ฒ์ด๋ค.\n */\n /**\n * ๋ฐํ๋ ํ๋ค โ ์ต๊ทผ ๊ฒ๋ถํฐ.\n *\n * ์ ์ ์ค ์ ์ฅ์ ์ฌ๊ธฐ ์๋ค. ํ๋ณธ์ ๋ฐํ์์๋ง ์๊ธฐ๋ฏ๋ก(`releaseFigure`), ์ด ๋ชฉ๋ก์ด ๊ณง\n * ใ์ด ๋ํ์ด ๋ช ๋ฒ ์ฝ์๋์๋ใ๋ค.\n */\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [FigureHistory], { description: 'Released versions of a figure, newest first.' })\n async figureVersions(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<FigureHistory[]> {\n const { domain } = context.state\n\n /* Its own, its parent's, or another domain's public figure (G2): releases are what a public figure shows. */\n if (!(await readableFigure(domain, id, { id: true, public: true, domain: { id: true } }))) return []\n return await getRepository(FigureHistory).find({\n where: { originalId: id },\n relations: ['updater'],\n order: { version: 'DESC' },\n take: 10\n })\n }\n\n /**\n * ์ง๊ธ ์๋น์ฒ๊ฐ ์ฐ๋ ํ.\n *\n * ๋ํ์ ํ์ฌ ์ ๋ณธ์ ์ ์ ์ค์ผ ์ ์๋ค(์ด์). ๋ฐฐ์น๋ ๊ฒ์ด ๋ณด๋ ๊ฒ์ **๋ง์ง๋ง์ผ๋ก ๋ฐํ๋ ํ**์ด๊ณ ,\n * ๊ทธ๊ฒ์ ์ด ์๋ฆฌ๊ฐ ๋ตํ๋ค.\n */\n /** What a kept GLB holds, read again from its bytes (ADR-0129): the modeller asks when it reopens a figure. */\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => GraphQLJSON, { nullable: true, description: 'What a kept GLB holds, by its hash: bounds in mm, triangles, primitives and nodes. None when this domain does not hold it.' })\n async figureMeshSummary(@Arg('hash') hash: string, @Ctx() context: ResolverContext): Promise<unknown> {\n const { domain, tx } = context.state\n return (await meshSummaryOf(getRepository(Figure, tx).manager, domain, hash)) ?? null\n }\n\n /** What became of an AI proposal: the figures a save put it into (ADR-0097 ยง5.6 item 5). */\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [FigureProposalOutcome], {\n description: 'The figures an AI proposal was saved into, oldest first. None: it was not saved, or not in this domain.'\n })\n async figureProposalOutcome(@Arg('proposalKey') proposalKey: string, @Ctx() context: ResolverContext): Promise<FigureProposalOutcome[]> {\n const { domain, tx } = context.state\n return await proposalOutcomeOf(getRepository(Figure, tx).manager, domain, proposalKey)\n }\n\n /** The drafts reverts kept for a figure, newest first -- apart from its released versions (ADR-0097 ยง5.6). */\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [FigureReplacedDraft], { description: 'Drafts kept when a revert wrote over them, newest first. Not released versions.' })\n async figureReplacedDrafts(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<FigureReplacedDraft[]> {\n const { domain, tx } = context.state\n return await replacedDraftsOf(getRepository(FigureReplacedDraft, tx).manager, domain, id)\n }\n\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => FigureHistory, { nullable: true, description: 'The most recently released version of a figure.' })\n async figureReleased(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<FigureHistory> {\n const { domain } = context.state\n\n if (!(await readableFigure(domain, id, { id: true, public: true, domain: { id: true } }))) return null\n return await getRepository(FigureHistory).findOne({\n where: { originalId: id },\n order: { version: 'DESC' }\n })\n }\n\n /**\n * ๋ฐํํด๋ ๋๋ โ **๋๋ฅด๊ธฐ ์ ์** ๋ฌป๋ ์๋ฆฌ.\n *\n * ํ์ ์ `figure-gate.ts` ๊ฐ ํ๊ณ ์ด ์๋ฆฌ๋ ์ ๋ณธ์ ๊บผ๋ด ๋๊ธด๋ค. ๊ฐ์ ํ์ ์ `releaseFigure` ๋\n * ๋ถ๋ฅธ๋ค โ ํ๋ฉด์ด ๋ฌผ์ด ๋ณด๊ณ ํต๊ณผํ๋๋ผ๋ ๊ทธ ์ฌ์ด์ ์ ๋ณธ์ด ๋ฐ๋์์ ์ ์์ผ๋ฏ๋ก, ๋ง๋ ๊ฒ์ ์ธ์ ๋\n * ๋ฎคํ
์ด์
์ด๋ค. ์ด ์ง์๋ **์ด์ ๋ฅผ ๋ฏธ๋ฆฌ ๋ณด์ฌ ์ฃผ๊ธฐ ์ํ ๊ฒ**์ด๊ณ ํ๊ฐ์ฆ์ด ์๋๋ค.\n */\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => FigureInspection, { description: 'Whether a figure may be released, with the reasons.' })\n async inspectFigure(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<FigureInspection> {\n const { domain } = context.state\n\n const figure = await getRepository(Figure).findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id },\n /*\n `type` is read too. A asset carries no type, so the temporary-type refusal reads the row's; with only\n id and source selected it saw `undefined`, the panel enabled ใ๋ฐํํ๊ธฐใ, and the release mutation โ which\n loads the whole row โ refused on the press (2026-09-24).\n */\n select: { id: true, source: true, type: true }\n })\n\n if (!figure) {\n throw new Error(`Figure ${id} ๋ฅผ ์ฐพ์ ์ ์๋ค`)\n }\n\n /*\n **ํ๋ฉด์ด ๋ฐํ ๋ฌธ๊ณผ ๊ฐ์ ๊ฒ์ ๋ณธ๋ค.** ์ง์ ๋ฐํํ์ ์ฌ๊ธฐ์๋ ํจ๊ป ๋๊ธฐ์ง ์์ผ๋ฉด, ์ ์ ํ๋ฉด์\n ์กฐ์ฉํ๋ฐ ๋ฐํ์ ๋๋ฅธ ์๊ฐ ๊ณ์ฝ ์๋ฐ์ผ๋ก ๋งํ๋ค โ ๊ทธ๋๋ ์ด๋ฏธ ์ด ๊ตฐ๋ฐ๋ฅผ ๊ณ ์น ๋ค๋ค.\n */\n const released = await getRepository(FigureHistory)\n .createQueryBuilder('history')\n .where('history.originalId = :id', { id })\n .orderBy('history.version', 'DESC')\n .limit(1)\n .getOne()\n\n return inspectSource(figure.source, released?.source, context.t, figure.type, figure.category)\n }\n\n /**\n * The same judgement for a source that has not been saved โ what the modeller shows **while** the author edits.\n *\n * Without it a author saw nothing until they saved and opened the release panel. The judgement runs here, not\n * in the browser, because the sentences are made from the request's language (`inspectAnySource` with `context.t`)\n * and a second copy on the screen would drift from the one the release refuses with. When `id` names a saved\n * figure, its row type and last release are read as `inspectFigure` does; a figure never saved has neither.\n */\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => FigureInspection, { description: 'Whether an unsaved figure source would be released, with the reasons.' })\n async inspectFigureDraft(\n @Arg('source') source: string,\n @Ctx() context: ResolverContext,\n @Arg('id', { nullable: true }) id?: string\n ): Promise<FigureInspection> {\n const { domain } = context.state\n if (!id) return inspectSource(source, null, context.t)\n\n const figure = await getRepository(Figure).findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id },\n select: { id: true, type: true }\n })\n if (!figure) throw new Error(`Figure ${id} ๋ฅผ ์ฐพ์ ์ ์๋ค`)\n\n const released = await getRepository(FigureHistory)\n .createQueryBuilder('history')\n .where('history.originalId = :id', { id })\n .orderBy('history.version', 'DESC')\n .limit(1)\n .getOne()\n\n return inspectSource(source, released?.source, context.t, figure.type, figure.category)\n }\n\n /** The categories this server allows (G5), or null when a category is free text: the modeller offers them to choose from. */\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [String], { nullable: true, description: 'The categories this server allows, or null when a category is free text.' })\n async figureCategories(): Promise<string[] | null> {\n const codes = figureCategories()\n return codes ? [...codes] : null\n }\n\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [String], { description: 'All figure type names in scope โ used to check name collisions before create.' })\n async figureTypeNames(@Ctx() context: ResolverContext): Promise<string[]> {\n const { domain } = context.state\n\n const rows = await getRepository(Figure).find({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) } },\n select: { type: true }\n })\n\n return rows.map(r => r.type).filter(Boolean)\n }\n\n /**\n * ์๋น์ฒ(operato-board, operato-twin, things-scene)๊ฐ ๋ฐํ๋ ๋ํ์ ๋ฐ์ ๊ฐ๋ ๋ฌธ.\n *\n * ์ด๋ฆ์ ๋ณด๋์์ ๊ณ์ฝ์ด๋ผ ๊ทธ๋๋ก ๋๋ค(๋ฐ๊พธ๋ ์ผ์ ๋ฐ๋ก ํ๋ค). ๋๋ ค์ฃผ๋ ๊ฒ์ ์์ฐ์ด๋ค โ\n * `{ type, asset }`. ๊ทธ๋ฆฌ๋ ์ชฝ(`registerFigure`)์ด ์ปค๋๋ก ์ปดํ์ผํ๋ค.\n *\n * ## ๊ท์น\n * 1. ์๋น์ฒ๋ ์ด์(draft)์ ๋ณผ ์ ์๋ค โ **๋ฐ๋์ ๋ฐํ๋(released) ํ๋ง ์ ๋ฌ**ํ๋ค.\n * 2. ํ์ฌ Figure๊ฐ released ์ํ์ด๋ฉด ํ์ฌ source๋ฅผ ๋๊ธด๋ค.\n * 3. ํ์ฌ Figure๊ฐ ์ ์ ์ค(draft)์ด๋๋ผ๋ ์ด์ ์ ๋ฐํ๋ ์ด๋ ฅ(FigureHistory)์ด ์์ผ๋ฉด\n * ๊ฐ์ฅ ์ต๊ทผ์ released ํ๋ณธ์ ๋๊ธด๋ค.\n * 4. ํ ๋ฒ๋ ๋ฐํ๋ ์ ์๋ ์ด์ ์์ฐ์ด๊ฑฐ๋ ์กด์ฌํ์ง ์๋ ํ์
์ธ ๊ฒฝ์ฐ null์ ๋ฐํํ์ฌ\n * ๋ฏธ์์ฑ ์์ฐ์ด ์ฌ ํ๋ฉด์ ์ ์ถ๋๋ ๊ฒ์ ์๊ฒฉํ ์ฐจ๋จํ๋ค.\n * 5. ๋๋ฉ์ธ ์์ ์ ์์ ๋๋ฉ์ธ์ ํ์
์ด ๋ถ๋ชจ ๋๋ฉ์ธ์ ๋์ผ ํ์
์ ํญ์ ์ค๋ฒ๋ผ์ด๋ํ๋ค.\n * 6. ๊ถํ์ ์ ์(`figure`)๊ณผ **๋ค๋ฅธ category** ์ธ `figure-published` ๋ค. ์๋น์ฒ ์ฌ์ฉ์์๊ฒ\n * ์ ์ ๊ถํ์ ์๊ตฌํ๋ฉด boardยทtwin ์ ํ๋ ํธ๊ฐ ์ ๋จ๊ณ , ๊ทธ๋ ๋ค๊ณ ์ ์ธ์ ๋น์ฐ๋ฉด ์ด ์ง์์๋\n * ๋ก๊ทธ์ธ์กฐ์ฐจ ์ ํ ์ฌ๋์๊ฒ ์ด๋ฆฐ๋ค(`auth-rebuild.md` ยง1). `<module>-published` ๋\n * ใ๊ทธ ๋ชจ๋์ด ๋ฐํํ ๊ฒ์ ๋จ์ด ์ฝ๋ ๋ฌธใ์ด๋ผ๋ ๊ท์ฝ์ด๋ค โ ์ํคํ
ํธ ํ์ (2026-09-15).\n *\n * ## ์ด๊ฑฐ๋ ๋งํ ์๋ค โ ์ง๊ธ์ ์ฐ์ฐ์ด๋ค\n *\n * ์ด ๋ฌธ์ ์ด์ ๋ `type` ํ๋๋ฟ์ด๋ผ ์ด๋ฆ์ ๋ชจ๋ฅด๋ฉด ๋ชป ๊บผ๋ธ๋ค. ๊ทธ๋ฐ๋ฐ ๊ทธ๊ฒ์ด **์ค๊ณ๊ฐ ์๋๋ค** โ\n * ๋ชฉ๋ก์ ๋ด๋ `figures`ยท`figureTypeNames` ๊ฐ `figure` category ๋ก ์ ๊ฒจ ์์ด์ ๊ฒฐ๊ณผ์ ์ผ๋ก\n * ๊ทธ๋ฐ ๊ฒ๋ฟ์ด๋ค. ๋์ค์ ๋๊ฐ ์๋น์ฒ์ฉ ๋ชฉ๋ก ๋ฌธ์ ํ๋ ๋ ์ด๊ณ `figure-published` ๋ฅผ ๋ถ์ด๋ฉด\n * ์ด๊ฑฐ๊ฐ ํจ๊ป ์ด๋ฆฌ๊ณ , ใ์ด๋ฆ์ ์์์ผ ํ๋คใ์ ๊ธฐ๋๊ณ ์๋ ๊ฐ์ ์ด ์กฐ์ฉํ ์ฌ๋ผ์ง๋ค.\n * ๊ทธ ๋ฌธ์ ๋ผ ์ฌ๋์ด ์ด ๋จ๋ฝ์ ์ฝ๊ณ ๊ทธ๋ ์ ํ๋ฉด ๋๋ค.\n */\n /*\n This directive is attached by schema assembly, so a test that calls the resolver method\n directly never exercises it. `figure-blueprint-query.test.ts` reads this source for the\n declaration instead โ see the test named for it there.\n */\n @Directive('@privilege(category: \"figure-published\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => GraphQLJSON, {\n nullable: true,\n description:\n 'A released figure for its consumers (board, twin, things-scene): { type, version, asset }. The latest release, or the one numbered `version` for a consumer that pins releases (ADR-0104). Only returns released figures.'\n })\n async figureBlueprint(\n @Arg('type') type: string,\n @Ctx() context: ResolverContext,\n @Arg('version', type => Int, { nullable: true, description: 'A release number. Absent: the latest release.' }) pinned?: number\n ): Promise<any> {\n const { domain } = context.state\n\n /*\n A child domain shadows the same type in its parent, which is how a tenant replaces the standard\n CONVEYOR with its own. Only a released version shadows. When the child has just a draft, the\n parent's release is used, so starting a draft never makes placed figures disappear (chief\n architect ruling, 2026-09-17). This used to skip the fallback as soon as a child row existed and\n return null.\n */\n const latest =\n (await releasedSourceOf(domain.id, type)) ?? (domain.parentId ? await releasedSourceOf(domain.parentId, type) : null)\n\n if (!latest) {\n return null\n }\n\n /*\n A pinned release is read from the same figure the latest comes from -- the shadowing rule decides whose\n releases these are, then the number picks one. Releases are never deleted, so a number once handed out is\n always there; a number that never was is refused by name rather than answered with another release.\n */\n const found = pinned === undefined || pinned === null || pinned === latest.version ? latest : await releaseNumbered(latest.figure, pinned)\n if (!found) {\n throw new Refusal(\n 'figure-release-not-found',\n { type, version: pinned, latest: latest.version },\n '{type} has no release {version}. its latest release is {latest}.'\n )\n }\n\n const { figure, source: sourceToCompile, version } = found\n\n try {\n const text = typeof sourceToCompile === 'string' ? sourceToCompile : JSON.stringify(sourceToCompile)\n return { type, version, asset: consumablePayloadOf(text).asset }\n } catch (err) {\n console.error(`[figureBlueprint] ํ์
'${type}' (figure id: ${figure.id}) ์์ฐ ์ปดํ์ผ ์คํจ:`, err)\n\n /*\n Null says one thing here: nobody published this type (ADR-0063 ๊ฒฐ์ 2 ๋ณดํฌ). A released figure\n whose stored source no longer compiles is a different fact, and answering null for it makes the\n board draw a stand-in with the reason nowhere on screen โ the author published, the catalogue\n says released, and the only trace is the line above. That is the silence ADR-0053 refuses.\n\n The board asks per type inside a Promise.all and collects a rejection into `failed`, so this\n refusal costs that one figure its drawing and the scene still opens.\n */\n throw new Refusal(\n 'figure-release-does-not-compile',\n { type, figureId: figure.id, version },\n 'the released source of {type} does not compile. open it in the modeller and release it again.'\n )\n }\n }\n\n /**\n * Released figures a board asks for together, by full name `{namespace}/{type}` (ADR-0114 ๊ฒฐ์ 14).\n *\n * One answer per name: an item, or a refusal that names why. A refusal never takes another item away -- the board\n * draws what it got and a stand-in with the reason for the rest. This server keeps its policy: the latest release,\n * shadowed by the child domain as `figureBlueprint` does. A type map is the board server's.\n */\n @Directive('@privilege(category: \"figure-published\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => GraphQLJSON, {\n description:\n 'Released figures asked together by full name {namespace}/{type}: { items: [{ type, ref, asset }], refused: [{ type, code, message }] }. The latest release of each; one refusal never removes another item.'\n })\n async figureBlueprints(\n @Arg('types', type => [String], { description: 'Full figure names {namespace}/{type}. At most 500.' }) types: string[],\n @Ctx() context: ResolverContext\n ): Promise<any> {\n const { domain } = context.state\n const names = [...new Set(types)]\n if (names.length > FIGURE_BLUEPRINTS_MAX) {\n throw new Refusal('figure-names-too-many', { count: names.length, max: FIGURE_BLUEPRINTS_MAX }, 'at most {max} figure names can be asked at once, not {count}.')\n }\n\n const items: { type: string; ref: string; asset: unknown }[] = []\n const refused: { type: string; code: string; message: string }[] = []\n /* Plain text: a board draws the reason on a canvas, so a name with `/` is not escaped. */\n const refuse = (type: string, refusal: Refusal) =>\n refused.push({\n type,\n code: refusal.code,\n message: context.t\n ? context.t(refusalKey(refusal.code), { ...refusal.params, defaultValue: refusal.message, interpolation: { escapeValue: false } })\n : refusal.message\n })\n\n for (const type of names) {\n const name = parseFigureName(type)\n if (!name) {\n refuse(type, new Refusal('figure-name-malformed', { type }, '{type} is not a full figure name of the form namespace/type.'))\n continue\n }\n const found =\n (await releasedSourceOfName(domain.id, name)) ??\n (domain.parentId ? await releasedSourceOfName(domain.parentId, name) : null) ??\n (await publicReleasedSourceOf(name))\n if (!found) {\n refuse(type, new Refusal('figure-not-released', { type }, 'no release is published here.'))\n continue\n }\n try {\n items.push({ type, ref: formatFigureRef({ ...name, version: found.version }), asset: consumablePayloadOf(found.source).asset })\n } catch {\n refuse(\n type,\n new Refusal(\n 'figure-release-does-not-compile',\n { type, figureId: found.figure.id, version: found.version },\n 'the released source of {type} does not compile. open it in the modeller and release it again.'\n )\n )\n }\n }\n\n return { items, refused }\n }\n}\n\nconst FIGURE_BLUEPRINTS_MAX = 500\n\n/** The released source of a full name in one domain: the type there, published under that namespace. */\nasync function releasedSourceOfName(domainId: string, name: FigureName) {\n const found = await releasedSourceOf(domainId, name.type)\n return found && found.figure.namespace === name.namespace ? found : null\n}\n\n/** The released source of another domain's public figure by full name (G2): looked at after the reader's own. */\nasync function publicReleasedSourceOf(name: FigureName) {\n const figure = await publicFigureOfName(name.namespace, name.type)\n return figure?.domain ? releasedSourceOfName(figure.domain.id, name) : null\n}\n\n/** One numbered release of a figure, or null when it has none by that number. */\nasync function releaseNumbered(figure: Figure, version: number): Promise<{ figure: Figure; source: string; version: number } | null> {\n const row = await getRepository(FigureHistory).findOne({\n where: { originalId: figure.id, state: 'released', version }\n })\n return row?.source ? { figure, source: row.source, version: row.version } : null\n}\n\n/**\n * Finds the released source of a type in one domain, or null.\n *\n * Always the latest release's own copy, from history: it carries the size range written down at release (ADR-0087\n * decision 6), and the figure's row -- released or a draft -- keeps only the ends its author narrowed. A figure that\n * was never released gives null, because drafts never reach consumers.\n */\nasync function releasedSourceOf(\n domainId: string,\n type: string\n): Promise<{ figure: Figure; source: string; version: number } | null> {\n const figure = await getRepository(Figure).findOne({ where: { domain: { id: domainId }, type } })\n if (!figure) return null\n\n const latestReleased = await getRepository(FigureHistory).findOne({\n where: { domain: { id: domainId }, originalId: figure.id, state: 'released' },\n order: { version: 'DESC' }\n })\n\n /* The version travels with the source: a refusal names the edition that does not compile, and the\n row's own version is the draft being edited, not the one the board was handed. */\n return latestReleased?.source\n ? { figure, source: latestReleased.source, version: latestReleased.version }\n : null\n}\n"]}
|
|
1
|
+
{"version":3,"file":"figure-query.js","sourceRoot":"","sources":["../../../server/service/figure/figure-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { In } from 'typeorm'\nimport { Args, Arg, Ctx, Directive, Int, Query, Resolver, UseMiddleware } from 'type-graphql'\nimport { GraphQLJSON } from 'graphql-scalars'\n\nimport {\n Domain,\n getQueryBuilderFromListParams,\n getRepository,\n ListParam,\n Refusal,\n SpeakRefusals,\n refusalKey\n} from '@things-factory/shell'\nimport { formatFigureRef, parseFigureName, type FigureName } from '@hatiolab/figure-model'\n\nimport { Figure } from './figure.js'\nimport { FigureHistory } from './figure-history.js'\nimport { consumablePayloadOf, inspectSource } from './figure-format.js'\nimport { FigureInspection, FigureList, FigureProposalOutcome } from './figure-type.js'\nimport { FigureReplacedDraft } from './figure-replaced-draft.js'\nimport { replacedDraftsOf } from './figure-revert.js'\nimport { proposalOutcomeOf } from './figure-proposal.js'\nimport { meshSummaryOf } from './figure-mesh-store.js'\nimport { readableFigure, publicFigureOfName } from './figure-public.js'\nimport { figureCategories } from './figure-categories.js'\n\n@Resolver(Figure)\n@UseMiddleware(SpeakRefusals)\nexport class FigureQuery {\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => Figure, { nullable: true, description: 'Finds a single figure by its ID.' })\n async figure(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Figure> {\n const { domain } = context.state\n\n // ๋ถ๋ชจ ๋๋ฉ์ธ์ Figure ๋ ๋ณด์ธ๋ค โ Board ์ ๊ฐ์ ๋ฒ์ ๊ท์น์ด๋ค.\n return await getRepository(Figure).findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id }\n })\n }\n\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => FigureList, { description: 'Lists figures. Sortable by score, triangles, name, updatedAt.' })\n async figures(@Args() params: ListParam, @Ctx() context: ResolverContext): Promise<FigureList> {\n const { domain } = context.state\n\n const queryBuilder = getQueryBuilderFromListParams({\n repository: getRepository(Figure),\n params,\n domain,\n alias: 'figure',\n /*\n `tags` ๋ ์ฐพ์ ์ ์์ด์ผ ํ๋ค โ ํ๊ทธ์ ๊ฐ์ ๋ถ์ด๋ ๋ฐ ์์ง ์๊ณ **์ฐพ๋ ๋ฐ** ์๋ค.\n\n `simple-json` ์ด๋ผ ์นธ์๋ `[\"๋ฐ์ถ\",\"์๋\"]` ์ด ํต์งธ๋ก ๋ค์ด ์๊ณ , LIKE ๋ ๊ทธ ๊ธ์๋ฅผ\n ๋ณธ๋ค. ใ๋ฐ์ถใ๋ก ์ฐพ์ผ๋ฉด ๊ฑธ๋ฆฐ๋ค. ์ ํํ ๊ทธ ํ๊ทธ๋ง ๊ฑธ๋ฆฌ๋ ๊ฒ์ ์๋์ง๋ง(์ด๋ฆ์ ใ๋ฐ์ถใ์ด\n ๋ ํผ๊ท์ด๋ ๊ฑธ๋ฆฐ๋ค) ์ฐพ๊ธฐ๋ก๋ ๊ทธ๊ฒ์ด ์คํ๋ ค ๋ซ๋ค.\n */\n searchables: ['type', 'name', 'description', 'category', 'tags']\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n /**\n * Other domains' public figures (LV figure-server design G2): what this domain may read, package and draw besides its\n * own and its parent's. The rows carry their domain, so a screen says whose each is. Their drafts are not opened.\n */\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => FigureList, { description: \"Other domains' public figures. Read only: their releases, never their drafts.\" })\n async publicFigures(@Args() params: ListParam, @Ctx() context: ResolverContext): Promise<FigureList> {\n const { domain } = context.state\n const mine = [domain.id, domain.parentId].filter(Boolean)\n const queryBuilder = getQueryBuilderFromListParams({\n repository: getRepository(Figure),\n params,\n alias: 'figure',\n searchables: ['type', 'name', 'description', 'category', 'tags']\n })\n .leftJoinAndSelect('figure.domain', 'owner')\n .andWhere('figure.public = :public', { public: true })\n .andWhere('owner.id NOT IN (:...mine)', { mine })\n const [items, total] = await queryBuilder.getManyAndCount()\n return { items, total }\n }\n\n /**\n * ๋ฑ๋ก๋ ํ์
์ด๋ฆ ๋ชฉ๋ก.\n *\n * ์ ์ ํ๋ฉด์ด **์ ํ์
์ด๋ฆ์ด ์ด๋ฏธ ์ฐ์ด๋์ง** ๋ฌผ์ด๋ณด๋ ๋ฐ ์ด๋ค. `type` ์ ์ ์ฅ๋๋\n * ์๋ณ์๋ผ ๋ง๋ ๋ค์ ๊ณ ์น ์ ์์ผ๋ฏ๋ก, ๋ง๋ค๊ธฐ ์ ์ ์๋ ค ์ค์ผ ํ๋ค.\n *\n * `state` ๋ก ๊ฑธ๋ฌ์ง์ง ์๋๋ค โ `draft` ์ธ Figure ์ ์ด๋ฆ๋ ์ด๋ฏธ ์ ์ ๋ ๊ฒ์ด๋ค.\n */\n /**\n * ๋ฐํ๋ ํ๋ค โ ์ต๊ทผ ๊ฒ๋ถํฐ.\n *\n * ์ ์ ์ค ์ ์ฅ์ ์ฌ๊ธฐ ์๋ค. ํ๋ณธ์ ๋ฐํ์์๋ง ์๊ธฐ๋ฏ๋ก(`releaseFigure`), ์ด ๋ชฉ๋ก์ด ๊ณง\n * ใ์ด ํผ๊ท์ด๊ฐ ๋ช ๋ฒ ์ฝ์๋์๋ใ๋ค.\n */\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [FigureHistory], { description: 'Released versions of a figure, newest first.' })\n async figureVersions(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<FigureHistory[]> {\n const { domain } = context.state\n\n /* Its own, its parent's, or another domain's public figure (G2): releases are what a public figure shows. */\n if (!(await readableFigure(domain, id, { id: true, public: true, domain: { id: true } }))) return []\n return await getRepository(FigureHistory).find({\n where: { originalId: id },\n relations: ['updater'],\n order: { version: 'DESC' },\n take: 10\n })\n }\n\n /**\n * ์ง๊ธ ์๋น์ฒ๊ฐ ์ฐ๋ ํ.\n *\n * ํผ๊ท์ด์ ํ์ฌ ์ ๋ณธ์ ์ ์ ์ค์ผ ์ ์๋ค(์ด์). ๋ฐฐ์น๋ ๊ฒ์ด ๋ณด๋ ๊ฒ์ **๋ง์ง๋ง์ผ๋ก ๋ฐํ๋ ํ**์ด๊ณ ,\n * ๊ทธ๊ฒ์ ์ด ์๋ฆฌ๊ฐ ๋ตํ๋ค.\n */\n /** What a kept GLB holds, read again from its bytes (ADR-0129): the modeller asks when it reopens a figure. */\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => GraphQLJSON, { nullable: true, description: 'What a kept GLB holds, by its hash: bounds in mm, triangles, primitives and nodes. None when this domain does not hold it.' })\n async figureMeshSummary(@Arg('hash') hash: string, @Ctx() context: ResolverContext): Promise<unknown> {\n const { domain, tx } = context.state\n return (await meshSummaryOf(getRepository(Figure, tx).manager, domain, hash)) ?? null\n }\n\n /** What became of an AI proposal: the figures a save put it into (ADR-0097 ยง5.6 item 5). */\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [FigureProposalOutcome], {\n description: 'The figures an AI proposal was saved into, oldest first. None: it was not saved, or not in this domain.'\n })\n async figureProposalOutcome(@Arg('proposalKey') proposalKey: string, @Ctx() context: ResolverContext): Promise<FigureProposalOutcome[]> {\n const { domain, tx } = context.state\n return await proposalOutcomeOf(getRepository(Figure, tx).manager, domain, proposalKey)\n }\n\n /** The drafts reverts kept for a figure, newest first -- apart from its released versions (ADR-0097 ยง5.6). */\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [FigureReplacedDraft], { description: 'Drafts kept when a revert wrote over them, newest first. Not released versions.' })\n async figureReplacedDrafts(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<FigureReplacedDraft[]> {\n const { domain, tx } = context.state\n return await replacedDraftsOf(getRepository(FigureReplacedDraft, tx).manager, domain, id)\n }\n\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => FigureHistory, { nullable: true, description: 'The most recently released version of a figure.' })\n async figureReleased(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<FigureHistory> {\n const { domain } = context.state\n\n if (!(await readableFigure(domain, id, { id: true, public: true, domain: { id: true } }))) return null\n return await getRepository(FigureHistory).findOne({\n where: { originalId: id },\n order: { version: 'DESC' }\n })\n }\n\n /**\n * ๋ฐํํด๋ ๋๋ โ **๋๋ฅด๊ธฐ ์ ์** ๋ฌป๋ ์๋ฆฌ.\n *\n * ํ์ ์ `figure-gate.ts` ๊ฐ ํ๊ณ ์ด ์๋ฆฌ๋ ์ ๋ณธ์ ๊บผ๋ด ๋๊ธด๋ค. ๊ฐ์ ํ์ ์ `releaseFigure` ๋\n * ๋ถ๋ฅธ๋ค โ ํ๋ฉด์ด ๋ฌผ์ด ๋ณด๊ณ ํต๊ณผํ๋๋ผ๋ ๊ทธ ์ฌ์ด์ ์ ๋ณธ์ด ๋ฐ๋์์ ์ ์์ผ๋ฏ๋ก, ๋ง๋ ๊ฒ์ ์ธ์ ๋\n * ๋ฎคํ
์ด์
์ด๋ค. ์ด ์ง์๋ **์ด์ ๋ฅผ ๋ฏธ๋ฆฌ ๋ณด์ฌ ์ฃผ๊ธฐ ์ํ ๊ฒ**์ด๊ณ ํ๊ฐ์ฆ์ด ์๋๋ค.\n */\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => FigureInspection, { description: 'Whether a figure may be released, with the reasons.' })\n async inspectFigure(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<FigureInspection> {\n const { domain } = context.state\n\n const figure = await getRepository(Figure).findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id },\n /*\n `type` is read too. A asset carries no type, so the temporary-type refusal reads the row's; with only\n id and source selected it saw `undefined`, the panel enabled ใ๋ฐํํ๊ธฐใ, and the release mutation โ which\n loads the whole row โ refused on the press (2026-09-24).\n */\n select: { id: true, source: true, type: true }\n })\n\n if (!figure) {\n throw new Error(`Figure ${id} ๋ฅผ ์ฐพ์ ์ ์๋ค`)\n }\n\n /*\n **ํ๋ฉด์ด ๋ฐํ ๋ฌธ๊ณผ ๊ฐ์ ๊ฒ์ ๋ณธ๋ค.** ์ง์ ๋ฐํํ์ ์ฌ๊ธฐ์๋ ํจ๊ป ๋๊ธฐ์ง ์์ผ๋ฉด, ์ ์ ํ๋ฉด์\n ์กฐ์ฉํ๋ฐ ๋ฐํ์ ๋๋ฅธ ์๊ฐ ๊ณ์ฝ ์๋ฐ์ผ๋ก ๋งํ๋ค โ ๊ทธ๋๋ ์ด๋ฏธ ์ด ๊ตฐ๋ฐ๋ฅผ ๊ณ ์น ๋ค๋ค.\n */\n const released = await getRepository(FigureHistory)\n .createQueryBuilder('history')\n .where('history.originalId = :id', { id })\n .orderBy('history.version', 'DESC')\n .limit(1)\n .getOne()\n\n return inspectSource(figure.source, released?.source, context.t, figure.type, figure.category)\n }\n\n /**\n * The same judgement for a source that has not been saved โ what the modeller shows **while** the author edits.\n *\n * Without it a author saw nothing until they saved and opened the release panel. The judgement runs here, not\n * in the browser, because the sentences are made from the request's language (`inspectAnySource` with `context.t`)\n * and a second copy on the screen would drift from the one the release refuses with. When `id` names a saved\n * figure, its row type and last release are read as `inspectFigure` does; a figure never saved has neither.\n */\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => FigureInspection, { description: 'Whether an unsaved figure source would be released, with the reasons.' })\n async inspectFigureDraft(\n @Arg('source') source: string,\n @Ctx() context: ResolverContext,\n @Arg('id', { nullable: true }) id?: string\n ): Promise<FigureInspection> {\n const { domain } = context.state\n if (!id) return inspectSource(source, null, context.t)\n\n const figure = await getRepository(Figure).findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id },\n select: { id: true, type: true }\n })\n if (!figure) throw new Error(`Figure ${id} ๋ฅผ ์ฐพ์ ์ ์๋ค`)\n\n const released = await getRepository(FigureHistory)\n .createQueryBuilder('history')\n .where('history.originalId = :id', { id })\n .orderBy('history.version', 'DESC')\n .limit(1)\n .getOne()\n\n return inspectSource(source, released?.source, context.t, figure.type, figure.category)\n }\n\n /** The categories this server allows (G5), or null when a category is free text: the modeller offers them to choose from. */\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [String], { nullable: true, description: 'The categories this server allows, or null when a category is free text.' })\n async figureCategories(): Promise<string[] | null> {\n const codes = figureCategories()\n return codes ? [...codes] : null\n }\n\n @Directive('@privilege(category: \"figure\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [String], { description: 'All figure type names in scope โ used to check name collisions before create.' })\n async figureTypeNames(@Ctx() context: ResolverContext): Promise<string[]> {\n const { domain } = context.state\n\n const rows = await getRepository(Figure).find({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) } },\n select: { type: true }\n })\n\n return rows.map(r => r.type).filter(Boolean)\n }\n\n /**\n * ์๋น์ฒ(operato-board, operato-twin, things-scene)๊ฐ ๋ฐํ๋ ํผ๊ท์ด๋ฅผ ๋ฐ์ ๊ฐ๋ ๋ฌธ.\n *\n * ์ด๋ฆ์ ๋ณด๋์์ ๊ณ์ฝ์ด๋ผ ๊ทธ๋๋ก ๋๋ค(๋ฐ๊พธ๋ ์ผ์ ๋ฐ๋ก ํ๋ค). ๋๋ ค์ฃผ๋ ๊ฒ์ ์์ฐ์ด๋ค โ\n * `{ type, asset }`. ๊ทธ๋ฆฌ๋ ์ชฝ(`registerFigure`)์ด ์ปค๋๋ก ์ปดํ์ผํ๋ค.\n *\n * ## ๊ท์น\n * 1. ์๋น์ฒ๋ ์ด์(draft)์ ๋ณผ ์ ์๋ค โ **๋ฐ๋์ ๋ฐํ๋(released) ํ๋ง ์ ๋ฌ**ํ๋ค.\n * 2. ํ์ฌ Figure๊ฐ released ์ํ์ด๋ฉด ํ์ฌ source๋ฅผ ๋๊ธด๋ค.\n * 3. ํ์ฌ Figure๊ฐ ์ ์ ์ค(draft)์ด๋๋ผ๋ ์ด์ ์ ๋ฐํ๋ ์ด๋ ฅ(FigureHistory)์ด ์์ผ๋ฉด\n * ๊ฐ์ฅ ์ต๊ทผ์ released ํ๋ณธ์ ๋๊ธด๋ค.\n * 4. ํ ๋ฒ๋ ๋ฐํ๋ ์ ์๋ ์ด์ ์์ฐ์ด๊ฑฐ๋ ์กด์ฌํ์ง ์๋ ํ์
์ธ ๊ฒฝ์ฐ null์ ๋ฐํํ์ฌ\n * ๋ฏธ์์ฑ ์์ฐ์ด ์ฌ ํ๋ฉด์ ์ ์ถ๋๋ ๊ฒ์ ์๊ฒฉํ ์ฐจ๋จํ๋ค.\n * 5. ๋๋ฉ์ธ ์์ ์ ์์ ๋๋ฉ์ธ์ ํ์
์ด ๋ถ๋ชจ ๋๋ฉ์ธ์ ๋์ผ ํ์
์ ํญ์ ์ค๋ฒ๋ผ์ด๋ํ๋ค.\n * 6. ๊ถํ์ ์ ์(`figure`)๊ณผ **๋ค๋ฅธ category** ์ธ `figure-published` ๋ค. ์๋น์ฒ ์ฌ์ฉ์์๊ฒ\n * ์ ์ ๊ถํ์ ์๊ตฌํ๋ฉด boardยทtwin ์ ํ๋ ํธ๊ฐ ์ ๋จ๊ณ , ๊ทธ๋ ๋ค๊ณ ์ ์ธ์ ๋น์ฐ๋ฉด ์ด ์ง์์๋\n * ๋ก๊ทธ์ธ์กฐ์ฐจ ์ ํ ์ฌ๋์๊ฒ ์ด๋ฆฐ๋ค(`auth-rebuild.md` ยง1). `<module>-published` ๋\n * ใ๊ทธ ๋ชจ๋์ด ๋ฐํํ ๊ฒ์ ๋จ์ด ์ฝ๋ ๋ฌธใ์ด๋ผ๋ ๊ท์ฝ์ด๋ค โ ์ํคํ
ํธ ํ์ (2026-09-15).\n *\n * ## ์ด๊ฑฐ๋ ๋งํ ์๋ค โ ์ง๊ธ์ ์ฐ์ฐ์ด๋ค\n *\n * ์ด ๋ฌธ์ ์ด์ ๋ `type` ํ๋๋ฟ์ด๋ผ ์ด๋ฆ์ ๋ชจ๋ฅด๋ฉด ๋ชป ๊บผ๋ธ๋ค. ๊ทธ๋ฐ๋ฐ ๊ทธ๊ฒ์ด **์ค๊ณ๊ฐ ์๋๋ค** โ\n * ๋ชฉ๋ก์ ๋ด๋ `figures`ยท`figureTypeNames` ๊ฐ `figure` category ๋ก ์ ๊ฒจ ์์ด์ ๊ฒฐ๊ณผ์ ์ผ๋ก\n * ๊ทธ๋ฐ ๊ฒ๋ฟ์ด๋ค. ๋์ค์ ๋๊ฐ ์๋น์ฒ์ฉ ๋ชฉ๋ก ๋ฌธ์ ํ๋ ๋ ์ด๊ณ `figure-published` ๋ฅผ ๋ถ์ด๋ฉด\n * ์ด๊ฑฐ๊ฐ ํจ๊ป ์ด๋ฆฌ๊ณ , ใ์ด๋ฆ์ ์์์ผ ํ๋คใ์ ๊ธฐ๋๊ณ ์๋ ๊ฐ์ ์ด ์กฐ์ฉํ ์ฌ๋ผ์ง๋ค.\n * ๊ทธ ๋ฌธ์ ๋ผ ์ฌ๋์ด ์ด ๋จ๋ฝ์ ์ฝ๊ณ ๊ทธ๋ ์ ํ๋ฉด ๋๋ค.\n */\n /*\n This directive is attached by schema assembly, so a test that calls the resolver method\n directly never exercises it. `figure-blueprint-query.test.ts` reads this source for the\n declaration instead โ see the test named for it there.\n */\n @Directive('@privilege(category: \"figure-published\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => GraphQLJSON, {\n nullable: true,\n description:\n 'A released figure for its consumers (board, twin, things-scene): { type, version, asset }. The latest release, or the one numbered `version` for a consumer that pins releases (ADR-0104). Only returns released figures.'\n })\n async figureBlueprint(\n @Arg('type') type: string,\n @Ctx() context: ResolverContext,\n @Arg('version', type => Int, { nullable: true, description: 'A release number. Absent: the latest release.' }) pinned?: number\n ): Promise<any> {\n const { domain } = context.state\n\n /*\n A child domain shadows the same type in its parent, which is how a tenant replaces the standard\n CONVEYOR with its own. Only a released version shadows. When the child has just a draft, the\n parent's release is used, so starting a draft never makes placed figures disappear (chief\n architect ruling, 2026-09-17). This used to skip the fallback as soon as a child row existed and\n return null.\n */\n const latest =\n (await releasedSourceOf(domain.id, type)) ?? (domain.parentId ? await releasedSourceOf(domain.parentId, type) : null)\n\n if (!latest) {\n return null\n }\n\n /*\n A pinned release is read from the same figure the latest comes from -- the shadowing rule decides whose\n releases these are, then the number picks one. Releases are never deleted, so a number once handed out is\n always there; a number that never was is refused by name rather than answered with another release.\n */\n const found = pinned === undefined || pinned === null || pinned === latest.version ? latest : await releaseNumbered(latest.figure, pinned)\n if (!found) {\n throw new Refusal(\n 'figure-release-not-found',\n { type, version: pinned, latest: latest.version },\n '{type} has no release {version}. its latest release is {latest}.'\n )\n }\n\n const { figure, source: sourceToCompile, version } = found\n\n try {\n const text = typeof sourceToCompile === 'string' ? sourceToCompile : JSON.stringify(sourceToCompile)\n return { type, version, asset: consumablePayloadOf(text).asset }\n } catch (err) {\n console.error(`[figureBlueprint] ํ์
'${type}' (figure id: ${figure.id}) ์์ฐ ์ปดํ์ผ ์คํจ:`, err)\n\n /*\n Null says one thing here: nobody published this type (ADR-0063 ๊ฒฐ์ 2 ๋ณดํฌ). A released figure\n whose stored source no longer compiles is a different fact, and answering null for it makes the\n board draw a stand-in with the reason nowhere on screen โ the author published, the catalogue\n says released, and the only trace is the line above. That is the silence ADR-0053 refuses.\n\n The board asks per type inside a Promise.all and collects a rejection into `failed`, so this\n refusal costs that one figure its drawing and the scene still opens.\n */\n throw new Refusal(\n 'figure-release-does-not-compile',\n { type, figureId: figure.id, version },\n 'the released source of {type} does not compile. open it in the modeller and release it again.'\n )\n }\n }\n\n /**\n * Released figures a board asks for together, by full name `{namespace}/{type}` (ADR-0114 ๊ฒฐ์ 14).\n *\n * One answer per name: an item, or a refusal that names why. A refusal never takes another item away -- the board\n * draws what it got and a stand-in with the reason for the rest. This server keeps its policy: the latest release,\n * shadowed by the child domain as `figureBlueprint` does. A type map is the board server's.\n */\n @Directive('@privilege(category: \"figure-published\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => GraphQLJSON, {\n description:\n 'Released figures asked together by full name {namespace}/{type}: { items: [{ type, ref, asset }], refused: [{ type, code, message }] }. The latest release of each; one refusal never removes another item.'\n })\n async figureBlueprints(\n @Arg('types', type => [String], { description: 'Full figure names {namespace}/{type}. At most 500.' }) types: string[],\n @Ctx() context: ResolverContext\n ): Promise<any> {\n const { domain } = context.state\n const names = [...new Set(types)]\n if (names.length > FIGURE_BLUEPRINTS_MAX) {\n throw new Refusal('figure-names-too-many', { count: names.length, max: FIGURE_BLUEPRINTS_MAX }, 'at most {max} figure names can be asked at once, not {count}.')\n }\n\n const items: { type: string; ref: string; asset: unknown }[] = []\n const refused: { type: string; code: string; message: string }[] = []\n /* Plain text: a board draws the reason on a canvas, so a name with `/` is not escaped. */\n const refuse = (type: string, refusal: Refusal) =>\n refused.push({\n type,\n code: refusal.code,\n message: context.t\n ? context.t(refusalKey(refusal.code), { ...refusal.params, defaultValue: refusal.message, interpolation: { escapeValue: false } })\n : refusal.message\n })\n\n for (const type of names) {\n const name = parseFigureName(type)\n if (!name) {\n refuse(type, new Refusal('figure-name-malformed', { type }, '{type} is not a full figure name of the form namespace/type.'))\n continue\n }\n const found =\n (await releasedSourceOfName(domain.id, name)) ??\n (domain.parentId ? await releasedSourceOfName(domain.parentId, name) : null) ??\n (await publicReleasedSourceOf(name))\n if (!found) {\n refuse(type, new Refusal('figure-not-released', { type }, 'no release is published here.'))\n continue\n }\n try {\n items.push({ type, ref: formatFigureRef({ ...name, version: found.version }), asset: consumablePayloadOf(found.source).asset })\n } catch {\n refuse(\n type,\n new Refusal(\n 'figure-release-does-not-compile',\n { type, figureId: found.figure.id, version: found.version },\n 'the released source of {type} does not compile. open it in the modeller and release it again.'\n )\n )\n }\n }\n\n return { items, refused }\n }\n}\n\nconst FIGURE_BLUEPRINTS_MAX = 500\n\n/** The released source of a full name in one domain: the type there, published under that namespace. */\nasync function releasedSourceOfName(domainId: string, name: FigureName) {\n const found = await releasedSourceOf(domainId, name.type)\n return found && found.figure.namespace === name.namespace ? found : null\n}\n\n/** The released source of another domain's public figure by full name (G2): looked at after the reader's own. */\nasync function publicReleasedSourceOf(name: FigureName) {\n const figure = await publicFigureOfName(name.namespace, name.type)\n return figure?.domain ? releasedSourceOfName(figure.domain.id, name) : null\n}\n\n/** One numbered release of a figure, or null when it has none by that number. */\nasync function releaseNumbered(figure: Figure, version: number): Promise<{ figure: Figure; source: string; version: number } | null> {\n const row = await getRepository(FigureHistory).findOne({\n where: { originalId: figure.id, state: 'released', version }\n })\n return row?.source ? { figure, source: row.source, version: row.version } : null\n}\n\n/**\n * Finds the released source of a type in one domain, or null.\n *\n * Always the latest release's own copy, from history: it carries the size range written down at release (ADR-0087\n * decision 6), and the figure's row -- released or a draft -- keeps only the ends its author narrowed. A figure that\n * was never released gives null, because drafts never reach consumers.\n */\nasync function releasedSourceOf(\n domainId: string,\n type: string\n): Promise<{ figure: Figure; source: string; version: number } | null> {\n const figure = await getRepository(Figure).findOne({ where: { domain: { id: domainId }, type } })\n if (!figure) return null\n\n const latestReleased = await getRepository(FigureHistory).findOne({\n where: { domain: { id: domainId }, originalId: figure.id, state: 'released' },\n order: { version: 'DESC' }\n })\n\n /* The version travels with the source: a refusal names the edition that does not compile, and the\n row's own version is the draft being edited, not the one the board was handed. */\n return latestReleased?.source\n ? { figure, source: latestReleased.source, version: latestReleased.version }\n : null\n}\n"]}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* ## ์ ๋ฐํ ์ ์๋ง์ธ๊ฐ
|
|
5
5
|
*
|
|
6
6
|
* `type` ์ ๋๋ฉด์ ์ ํ๋ ์ด๋ฆ์ด๋ค. ๋๋ฉด์ `{ type, left, top, width, height }` ๋ง ๊ฐ๊ณ ๋ ์ต์
|
|
7
|
-
* ๋ฐํํ์ ๊ทธ๋ฆฌ๋ฏ๋ก, ๋ฐํ๋
|
|
8
|
-
* ๋๋ค. ํ ๋ฒ๋ ๋ฐํ๋์ง ์์
|
|
7
|
+
* ๋ฐํํ์ ๊ทธ๋ฆฌ๋ฏ๋ก, ๋ฐํ๋ ํผ๊ท์ด์ ์ด๋ฆ์ ๋ฐ๊พธ๋ฉด ์ด๋ฏธ ๋ฐฐ์น๋ ๋๋ฉด์ด ์๋ฌด ์ค๋ฅ ์์ด ๋น ์๋ฆฌ๊ฐ
|
|
8
|
+
* ๋๋ค. ํ ๋ฒ๋ ๋ฐํ๋์ง ์์ ํผ๊ท์ด๋ ๊ทธ๋ ค์ง ์๋ฆฌ๊ฐ ์์ผ๋ ๊ฐ๋ฆฌํค๋ ๋๋ฉด๋ ์์ ์ ์๋ค.
|
|
9
9
|
*
|
|
10
10
|
* ## ์ ์ด์ด์ผ ํ๋
|
|
11
11
|
*
|
|
@@ -24,10 +24,10 @@ export interface RenameFacts {
|
|
|
24
24
|
version?: number;
|
|
25
25
|
/** ํ๋ณธ์ด ํ๋๋ผ๋ ์๋. ๋๋๋ฆฌ๊ธฐ๋ก ํ ๋ฒํธ๊ฐ ๋๋ก ๋ฎ์์ ธ๋ ์ด๋ ฅ์ ๋จ๋๋ค. */
|
|
26
26
|
hasHistory: boolean;
|
|
27
|
-
/** ๊ฐ์ ๋๋ฉ์ธ์์ ๊ทธ ์ด๋ฆ์ ์ด๋ฏธ ์ฐ๋ **๋ค๋ฅธ**
|
|
27
|
+
/** ๊ฐ์ ๋๋ฉ์ธ์์ ๊ทธ ์ด๋ฆ์ ์ด๋ฏธ ์ฐ๋ **๋ค๋ฅธ** ํผ๊ท์ด๊ฐ ์๋. */
|
|
28
28
|
takenByAnother: boolean;
|
|
29
29
|
/**
|
|
30
|
-
* ๊ฐ์ ๋๋ฉ์ธ์์ ๊ทธ ์ด๋ฆ์ผ๋ก ๋ฐํํ ๋ค ์ง์์ง
|
|
30
|
+
* ๊ฐ์ ๋๋ฉ์ธ์์ ๊ทธ ์ด๋ฆ์ผ๋ก ๋ฐํํ ๋ค ์ง์์ง ํผ๊ท์ด๊ฐ ์๋. ๋ฐํํ ํผ๊ท์ด๋ฅผ ์ง์ธ ์ ์๊ฒ ๋๊ธฐ(G4) ์ ์ ์ง์์ง ๊ฒ์ด๋ค.
|
|
31
31
|
* ๊ทธ ์ด๋ฆ์ ๋ค์ ์ฐ๋ฉด ํ ๋ฒํธ๊ฐ 1๋ถํฐ ๋ค์ ๋งค๊ฒจ์ ธ ๊ฐ์ `ns/type@n` ์ด ๋ค๋ฅธ ๋ด์ฉ์ ๊ฐ๋ฆฌํจ๋ค.
|
|
32
32
|
*/
|
|
33
33
|
releasedBefore?: boolean;
|
|
@@ -17,7 +17,7 @@ async function typeReleasedBefore(repositories, domain, type) {
|
|
|
17
17
|
return ids.length > 0 && (await repositories.histories.count({ where: { originalId: (0, typeorm_1.In)(ids) } })) > 0;
|
|
18
18
|
}
|
|
19
19
|
/** Said when a type was released and deleted before: a new figure may not take it. */
|
|
20
|
-
const releasedBeforeMessage = (type) => `type ใ${type}ใ ๋ ์ด ๋๋ฉ์ธ์์ ๋ฐํํ ๋ค ์ง์ด
|
|
20
|
+
const releasedBeforeMessage = (type) => `type ใ${type}ใ ๋ ์ด ๋๋ฉ์ธ์์ ๋ฐํํ ๋ค ์ง์ด ํผ๊ท์ด์ ์ด๋ฆ์ด๋ค โ ๋ค์ ์ฐ๋ฉด ๊ฐ์ ํ ๋ฒํธ๊ฐ ๋ค๋ฅธ ๋ด์ฉ์ ๊ฐ๋ฆฌํค๋ฏ๋ก ๋ค๋ฅธ ์ด๋ฆ์ ๊ณ ๋ฅธ๋ค`;
|
|
21
21
|
exports.releasedBeforeMessage = releasedBeforeMessage;
|
|
22
22
|
class FigureRenameRefused extends Error {
|
|
23
23
|
constructor(code, message) {
|
|
@@ -46,7 +46,7 @@ function renameDraftType(current, wanted, facts) {
|
|
|
46
46
|
throw new FigureRenameRefused('malformed-type', `type ใ${next}ใ ๋ ์๋ฌธ์๋ก ์์ํ๊ณ ์๋ฌธ์ยท์ซ์ยทํ์ดํ ํ๋์ฉ๋ง ์ฐ๋ฉฐ ${figure_model_1.TYPE_LENGTH.min}~${figure_model_1.TYPE_LENGTH.max}์์ฌ์ผ ํ๋ค`);
|
|
47
47
|
}
|
|
48
48
|
if ((facts.version ?? 0) > 0 || facts.hasHistory) {
|
|
49
|
-
throw new FigureRenameRefused('already-released', '๋ฐํ๋
|
|
49
|
+
throw new FigureRenameRefused('already-released', '๋ฐํ๋ ํผ๊ท์ด์ type ์ ๋ฐ๊ฟ ์ ์๋ค โ ์ด๋ฏธ ๋ฐฐ์น๋ ๋๋ฉด์ด ์ด ์ด๋ฆ์ ๊ฐ๋ฆฌํจ๋ค');
|
|
50
50
|
}
|
|
51
51
|
if (facts.takenByAnother) {
|
|
52
52
|
throw new FigureRenameRefused('type-taken', `type ใ${next}ใ ๋ ์ด ๋๋ฉ์ธ์์ ์ด๋ฏธ ์ฐ๊ณ ์๋ค`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figure-rename.js","sourceRoot":"","sources":["../../../server/service/figure/figure-rename.ts"],"names":[],"mappings":";;;AAwCA,gDAeC;AAsBD,0CAuCC;AAUD,kCAgBC;AA9ID,qCAAyC;AACzC,yDAAkE;AAsClE,gHAAgH;AACzG,KAAK,UAAU,kBAAkB,CACtC,YAGC,EACD,MAAsB,EACtB,IAAY;IAEZ,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC;QAC9C,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAA,aAAG,EAAC,IAAA,gBAAM,GAAE,CAAC,EAAE;QACpE,WAAW,EAAE,IAAI;QACjB,MAAM,EAAE,CAAC,IAAI,CAAC;KACf,CAAC,CAAA;IACF,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAC5D,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,YAAY,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,IAAA,YAAE,EAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAA;AACvG,CAAC;AAED,sFAAsF;AAC/E,MAAM,qBAAqB,GAAG,CAAC,IAAY,EAAE,EAAE,CACpD,SAAS,IAAI,
|
|
1
|
+
{"version":3,"file":"figure-rename.js","sourceRoot":"","sources":["../../../server/service/figure/figure-rename.ts"],"names":[],"mappings":";;;AAwCA,gDAeC;AAsBD,0CAuCC;AAUD,kCAgBC;AA9ID,qCAAyC;AACzC,yDAAkE;AAsClE,gHAAgH;AACzG,KAAK,UAAU,kBAAkB,CACtC,YAGC,EACD,MAAsB,EACtB,IAAY;IAEZ,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC;QAC9C,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAA,aAAG,EAAC,IAAA,gBAAM,GAAE,CAAC,EAAE;QACpE,WAAW,EAAE,IAAI;QACjB,MAAM,EAAE,CAAC,IAAI,CAAC;KACf,CAAC,CAAA;IACF,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAC5D,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,YAAY,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,IAAA,YAAE,EAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAA;AACvG,CAAC;AAED,sFAAsF;AAC/E,MAAM,qBAAqB,GAAG,CAAC,IAAY,EAAE,EAAE,CACpD,SAAS,IAAI,yEAAyE,CAAA;AAD3E,QAAA,qBAAqB,yBACsD;AAExF,MAAa,mBAAoB,SAAQ,KAAK;IAC5C,YACW,IAAkG,EAC3G,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAA;QAHL,SAAI,GAAJ,IAAI,CAA8F;QAI3G,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAA;IACnC,CAAC;CACF;AARD,kDAQC;AAED;;;;;GAKG;AACH,SAAgB,eAAe,CAC7B,OAAyC,EACzC,MAAc,EACd,KAAkB;IAElB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA;IAE1B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,mBAAmB,CAAC,YAAY,EAAE,qCAAqC,CAAC,CAAA;IACpF,CAAC;IAED;;;MAGE;IACF,IAAI,CAAC,2BAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,0BAAW,CAAC,GAAG,IAAI,IAAI,CAAC,MAAM,GAAG,0BAAW,CAAC,GAAG,EAAE,CAAC;QAC/F,MAAM,IAAI,mBAAmB,CAC3B,gBAAgB,EAChB,SAAS,IAAI,oCAAoC,0BAAW,CAAC,GAAG,IAAI,0BAAW,CAAC,GAAG,QAAQ,CAC5F,CAAA;IACH,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QACjD,MAAM,IAAI,mBAAmB,CAC3B,kBAAkB,EAClB,iDAAiD,CAClD,CAAA;IACH,CAAC;IAED,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;QACzB,MAAM,IAAI,mBAAmB,CAAC,YAAY,EAAE,SAAS,IAAI,sBAAsB,CAAC,CAAA;IAClF,CAAC;IAED,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;QACzB,MAAM,IAAI,mBAAmB,CAAC,sBAAsB,EAAE,IAAA,6BAAqB,EAAC,IAAI,CAAC,CAAC,CAAA;IACpF,CAAC;IAED,qGAAqG;IACrG,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAA;AAC/C,CAAC;AAED;;;;;;;GAOG;AACI,KAAK,UAAU,WAAW,CAC/B,YAGC,EACD,MAAyC,EACzC,MAAsB,EACtB,MAAc;IAEd,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA;IAC1B,MAAM,UAAU,GAAG,CAAC,MAAM,YAAY,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAA;IACjG,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAEpH,MAAM,cAAc,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;IAE1F,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,EAAE,cAAc,EAAE,CAAA;AACnH,CAAC","sourcesContent":["import { In, IsNull, Not } from 'typeorm'\nimport { TYPE_LENGTH, TYPE_PATTERN } from '@hatiolab/figure-model'\n/**\n * ์ด์์ ํ์
์ ๊ณ ์น๋ ๊ท์น โ ADR-0063 ๊ฒฐ์ 4.\n *\n * ## ์ ๋ฐํ ์ ์๋ง์ธ๊ฐ\n *\n * `type` ์ ๋๋ฉด์ ์ ํ๋ ์ด๋ฆ์ด๋ค. ๋๋ฉด์ `{ type, left, top, width, height }` ๋ง ๊ฐ๊ณ ๋ ์ต์ \n * ๋ฐํํ์ ๊ทธ๋ฆฌ๋ฏ๋ก, ๋ฐํ๋ ํผ๊ท์ด์ ์ด๋ฆ์ ๋ฐ๊พธ๋ฉด ์ด๋ฏธ ๋ฐฐ์น๋ ๋๋ฉด์ด ์๋ฌด ์ค๋ฅ ์์ด ๋น ์๋ฆฌ๊ฐ\n * ๋๋ค. ํ ๋ฒ๋ ๋ฐํ๋์ง ์์ ํผ๊ท์ด๋ ๊ทธ๋ ค์ง ์๋ฆฌ๊ฐ ์์ผ๋ ๊ฐ๋ฆฌํค๋ ๋๋ฉด๋ ์์ ์ ์๋ค.\n *\n * ## ์ ์ด์ด์ผ ํ๋\n *\n * ๋ซ์ ๋์๋๋ ์ ์์๊ฐ ์ด๋ฆ์ **ํ ๋ฒ๋** ์ ํ์ง ๋ชปํ๋ค. ์ Figure ์๋ ๊ธฐ๊ณ๊ฐ ์ง์ ์ด๋ฆ์ด\n * ๋ถ๊ณ (`FIGURE_MU6RJH47`) ์นธ์ ์๋ฌผ์ ๊ฐ ๊ฑธ๋ ค์, ๊ทธ ์ด๋ฆ์ด ๊ทธ๋๋ก ๋๋ฉด์ ์ ํ๋ ์ด๋ฆ์ด ๋๋ค.\n * ๊ทธ๋ ๊ฒ ๋จ์ ์ด์์ด 14 ๊ฐ๋ค.\n *\n * ## ์
์ ์ฌ๊ธฐ, ์ง์๋ ๋ถ๋ฅด๋ ์ชฝ\n *\n * ์ด ํ์ผ์ ์ ์ฅ์๋ฅผ ๋ชจ๋ฅธ๋ค โ ํ ๋ฒํธ ยท ์ด๋ ฅ ์ ๋ฌด ยท ๊ฐ์ ์ด๋ฆ์ ์ฃผ์ธ์ **์ฌ์ค๋ก ๋ฐ๋๋ค.**\n * ๊ทธ๋์ผ ๊ท์น์ DB ์์ด ์ํํ๋ค. ๋ฌธ(`figure-mutation.ts`)์ด ๊ทธ ์
์ ์ฝ์ด ๋๊ธด๋ค.\n */\n\n\n/** ์ด๋ฆ์ ๋ฐ๊ฟ ๋ ์์์ผ ํ๋ ์ฌ์ค. ๋ถ๋ฅด๋ ์ชฝ์ด ์ ์ฅ์์์ ์ฝ์ด ์จ๋ค. */\nexport interface RenameFacts {\n /** ๋ฐํ ํ ๋ฒํธ. 0 ์ด๋ฉด ํ ๋ฒ๋ ๋ฐํ๋์ง ์์๋ค. */\n version?: number\n /** ํ๋ณธ์ด ํ๋๋ผ๋ ์๋. ๋๋๋ฆฌ๊ธฐ๋ก ํ ๋ฒํธ๊ฐ ๋๋ก ๋ฎ์์ ธ๋ ์ด๋ ฅ์ ๋จ๋๋ค. */\n hasHistory: boolean\n /** ๊ฐ์ ๋๋ฉ์ธ์์ ๊ทธ ์ด๋ฆ์ ์ด๋ฏธ ์ฐ๋ **๋ค๋ฅธ** ํผ๊ท์ด๊ฐ ์๋. */\n takenByAnother: boolean\n /**\n * ๊ฐ์ ๋๋ฉ์ธ์์ ๊ทธ ์ด๋ฆ์ผ๋ก ๋ฐํํ ๋ค ์ง์์ง ํผ๊ท์ด๊ฐ ์๋. ๋ฐํํ ํผ๊ท์ด๋ฅผ ์ง์ธ ์ ์๊ฒ ๋๊ธฐ(G4) ์ ์ ์ง์์ง ๊ฒ์ด๋ค.\n * ๊ทธ ์ด๋ฆ์ ๋ค์ ์ฐ๋ฉด ํ ๋ฒํธ๊ฐ 1๋ถํฐ ๋ค์ ๋งค๊ฒจ์ ธ ๊ฐ์ `ns/type@n` ์ด ๋ค๋ฅธ ๋ด์ฉ์ ๊ฐ๋ฆฌํจ๋ค.\n */\n releasedBefore?: boolean\n}\n\n/** Whether a figure of this type was released and then deleted in the domain (deleted before G4 refused it). */\nexport async function typeReleasedBefore(\n repositories: {\n figures: { find(options: any): Promise<{ id?: string }[]> }\n histories: { count(options: any): Promise<number> }\n },\n domain: { id: string },\n type: string\n): Promise<boolean> {\n const deleted = await repositories.figures.find({\n where: { domain: { id: domain.id }, type, deletedAt: Not(IsNull()) },\n withDeleted: true,\n select: ['id']\n })\n const ids = deleted.map(figure => figure.id).filter(Boolean)\n return ids.length > 0 && (await repositories.histories.count({ where: { originalId: In(ids) } })) > 0\n}\n\n/** Said when a type was released and deleted before: a new figure may not take it. */\nexport const releasedBeforeMessage = (type: string) =>\n `type ใ${type}ใ ๋ ์ด ๋๋ฉ์ธ์์ ๋ฐํํ ๋ค ์ง์ด ํผ๊ท์ด์ ์ด๋ฆ์ด๋ค โ ๋ค์ ์ฐ๋ฉด ๊ฐ์ ํ ๋ฒํธ๊ฐ ๋ค๋ฅธ ๋ด์ฉ์ ๊ฐ๋ฆฌํค๋ฏ๋ก ๋ค๋ฅธ ์ด๋ฆ์ ๊ณ ๋ฅธ๋ค`\n\nexport class FigureRenameRefused extends Error {\n constructor(\n readonly code: 'empty-type' | 'malformed-type' | 'already-released' | 'type-taken' | 'type-released-before',\n message: string\n ) {\n super(message)\n this.name = 'FigureRenameRefused'\n }\n}\n\n/**\n * ๊ณ ์น ์ด๋ฆ๊ณผ ์ ๋ณธ. ๋ชป ๊ณ ์น๋ฉด **๊น๋ญ๊ณผ ํจ๊ป ๋์ง๋ค** โ ์กฐ์ฉํ ์ ์ด๋ฆ์ผ๋ก ๋์ง ์๋๋ค.\n *\n * ์ ๋ณธ ์์๋ `type` ์ด ์์ด์ ํจ๊ป ๊ณ ์น๋ค. ํ์ชฝ๋ง ๊ณ ์น๋ฉด ์ ์ฅ๋ JSON ๊ณผ ํ์ด ๋ค๋ฅธ ์ด๋ฆ์\n * ๋งํ๊ณ , ๋ฐํํ ๋ ์ด๋ ์ชฝ์ด ๋๋ฉด์ ์ ํ๋์ง๊ฐ ๊ฐ๋ฆฐ๋ค.\n */\nexport function renameDraftType(\n current: { type: string; source: string },\n wanted: string,\n facts: RenameFacts\n): { type: string; source: string } {\n const next = wanted.trim()\n\n if (!next) {\n throw new FigureRenameRefused('empty-type', 'type ์ด ๋น์ด ์๋ค โ ๋๋ฉด์ ์ ํ๋ ์ด๋ฆ์ด๋ผ ๋น์ธ ์ ์๋ค')\n }\n\n /*\n The shape the modeller has always asked for, now asked here too (designer 2026-09-27, Q-D3): only a type being set\n is held to it -- every type in the development data already keeps it (56 of 56, 2026-09-27), and none is renamed.\n */\n if (!TYPE_PATTERN.test(next) || next.length < TYPE_LENGTH.min || next.length > TYPE_LENGTH.max) {\n throw new FigureRenameRefused(\n 'malformed-type',\n `type ใ${next}ใ ๋ ์๋ฌธ์๋ก ์์ํ๊ณ ์๋ฌธ์ยท์ซ์ยทํ์ดํ ํ๋์ฉ๋ง ์ฐ๋ฉฐ ${TYPE_LENGTH.min}~${TYPE_LENGTH.max}์์ฌ์ผ ํ๋ค`\n )\n }\n\n if ((facts.version ?? 0) > 0 || facts.hasHistory) {\n throw new FigureRenameRefused(\n 'already-released',\n '๋ฐํ๋ ํผ๊ท์ด์ type ์ ๋ฐ๊ฟ ์ ์๋ค โ ์ด๋ฏธ ๋ฐฐ์น๋ ๋๋ฉด์ด ์ด ์ด๋ฆ์ ๊ฐ๋ฆฌํจ๋ค'\n )\n }\n\n if (facts.takenByAnother) {\n throw new FigureRenameRefused('type-taken', `type ใ${next}ใ ๋ ์ด ๋๋ฉ์ธ์์ ์ด๋ฏธ ์ฐ๊ณ ์๋ค`)\n }\n\n if (facts.releasedBefore) {\n throw new FigureRenameRefused('type-released-before', releasedBeforeMessage(next))\n }\n\n /* The asset carries no `type`: the name a board uses is the row's alone, so only the row changes. */\n return { type: next, source: current.source }\n}\n\n/**\n * ์ฌ์ค ์
์ ์ ์ฅ์์์ ์ฝ๋๋ค.\n *\n * ๊ท์น์์ ๋ผ์ด ๋ ์๋ฆฌ์ด์ง๋ง **์ง์์ ๋ชจ์์ด ํ๋ฆฌ๋ฉด ์ ์์์๊ฒ๋ ์ ์ฅ ์คํจ๋ก๋ง ๋ณด์ธ๋ค.**\n * ์ค์ ๋ก ๊ทธ๋ฌ๋ค โ ํ๋ณธ์ `figure: { id }` ๋ก ๋ฌผ์๊ณ , `FigureHistory` ๋ ๊ด๊ณ ์นธ์ด ์๋๋ผ\n * `originalId` ๋ก ๊ฐ๋ฆฌํจ๋ค. TypeORM ์ด ใ๊ทธ๋ฐ ์์ฑ์ด ์๋คใ๋ก ๋์ก๊ณ ํ๋ฉด์๋ ์๋ฌธ ์ค๋ฅ ํ ์ค์ด\n * ๋ด๋ค. ๊ทธ๋์ ์ด ํจ์๋ฅผ ๋ด๋ณด๋ด sqlite ๋ฅผ ๋ค๊ณ ์๋ณต๊น์ง ๋ณธ๋ค.\n */\nexport async function renameFacts(\n repositories: {\n figures: { findOne(options: any): Promise<{ id?: string } | null>; find(options: any): Promise<{ id?: string }[]> }\n histories: { count(options: any): Promise<number> }\n },\n figure: { id?: string; version?: number },\n domain: { id: string },\n wanted: string\n): Promise<RenameFacts> {\n const next = wanted.trim()\n const hasHistory = (await repositories.histories.count({ where: { originalId: figure.id } })) > 0\n const taken = next ? await repositories.figures.findOne({ where: { domain: { id: domain.id }, type: next } }) : null\n\n const releasedBefore = next ? await typeReleasedBefore(repositories, domain, next) : false\n\n return { version: figure.version, hasHistory, takenByAnother: !!taken && taken.id !== figure.id, releasedBefore }\n}\n"]}
|
|
@@ -88,7 +88,7 @@ function requireDomainId(state) {
|
|
|
88
88
|
return id;
|
|
89
89
|
}
|
|
90
90
|
/**
|
|
91
|
-
* ์ด
|
|
91
|
+
* ์ด ํผ๊ท์ด๊ฐ ํธ์ถ์ ๋๋ฉ์ธ ๊ฒ์ธ๊ฐ.
|
|
92
92
|
*
|
|
93
93
|
* ๋ชจ๋ธ์ด ๋๊ธด id ๋ฅผ ๊ทธ๋๋ก ์ฐ์ง ์๋๋ค. ์์ผ๋ฉด ๋ชป ์ฐพ์๋ค๊ณ ๋งํ๋ค โ ใ๊ถํ์ด ์๋คใ์ ๊ตฌ๋ณํด
|
|
94
94
|
* ์๋ ค ์ค ๊ฒ์ด ์๋ค(๋ค๋ฅธ ํ
๋ํธ์ ๊ทธ id ๊ฐ ์๋ค๋ ์ฌ์ค ์์ฒด๊ฐ ์๋ ค ์ค ๊ฒ์ด ์๋๋ค).
|
|
@@ -193,8 +193,8 @@ function focusOf(host, source) {
|
|
|
193
193
|
/**
|
|
194
194
|
* ๋ฌด์์ ๊ณ ์น๋ผ๋ ๊ฒ์ธ์ง ๋ํ๋ฉด ๋ฌธ๋งฅ์์ ํด์ํ๋ค.
|
|
195
195
|
*
|
|
196
|
-
* ๋ชจ๋ธ์ด ๋์์ ์ ์คฌ์ผ๋ฉด **์ ์๋ฉด์ด ์ง๊ธ ์ด๊ณ ์๋
|
|
197
|
-
* ์๋๋ค โ ํ๋ฉด์ ๊ทธ
|
|
196
|
+
* ๋ชจ๋ธ์ด ๋์์ ์ ์คฌ์ผ๋ฉด **์ ์๋ฉด์ด ์ง๊ธ ์ด๊ณ ์๋ ํผ๊ท์ด**์ด๋ค. ์ฌ์ฉ์์๊ฒ ์๋ณ์๋ฅผ ๋๋ฌป์ง
|
|
197
|
+
* ์๋๋ค โ ํ๋ฉด์ ๊ทธ ํผ๊ท์ด๊ฐ ๋ ์๋๋ฐ ใ์ด๋ ํผ๊ท์ด์
๋๊นใ๋ฅผ ๋ฌป๋ ๊ฒ์ ๋ฌธ๋งฅ์ ์ ์ฝ์ ๊ฒ์ด๋ค.
|
|
198
198
|
*/
|
|
199
199
|
function figureIdFrom(args, host) {
|
|
200
200
|
const said = typeof args?.figureId === 'string' ? args.figureId.trim() : '';
|
|
@@ -277,7 +277,7 @@ function figureToolSpecs() {
|
|
|
277
277
|
{
|
|
278
278
|
kind: 'read',
|
|
279
279
|
name: 'listFigures',
|
|
280
|
-
/* ์ด ๋๋ฉ์ธ์
|
|
280
|
+
/* ์ด ๋๋ฉ์ธ์ ํผ๊ท์ด ๋ชฉ๋ก โ ์ ์ฅ์๋ฅผ ์ง์ ์ฝ์ง๋ง ๊ฐ์ ์ผ์ ํ๋ ๋ฌธ์ ์ด๊ฒ์ด๋ค. */
|
|
281
281
|
doors: ['Query.figures'],
|
|
282
282
|
description: 'Lists the figures in this tenant with their type names, states and part counts. ' +
|
|
283
283
|
'Call it before naming a type โ type names are stored identifiers and must not be invented. ' +
|
|
@@ -327,8 +327,8 @@ function figureToolSpecs() {
|
|
|
327
327
|
{
|
|
328
328
|
kind: 'read',
|
|
329
329
|
name: 'getFigureSource',
|
|
330
|
-
/* ์ ์ฅ๋
|
|
331
|
-
* ๊ทธ ๊ฐ๋์๋ ๋ฟ๋ ๋ฌธ์ด ์์ง๋ง `doors: []` ๋ก ์ ์ง ์๋๋ค. ๊ทธ๋ฌ๋ฉด ์ ์ฅ๋
|
|
330
|
+
/* ์ ์ฅ๋ ํผ๊ท์ด์ ์๋ณธ. **์ ์ฅ ์ ์ด์**์ ๋ฌผ์ผ๋ฉด ์ ์ฅ์์ ๊ฐ ๊ฒ์ด ์์ด ํ๋ฉด์ด ๋ณด๋ธ ๊ฒ์ ๊ทธ๋๋ก ๋๋ ค์ค๋ค โ
|
|
331
|
+
* ๊ทธ ๊ฐ๋์๋ ๋ฟ๋ ๋ฌธ์ด ์์ง๋ง `doors: []` ๋ก ์ ์ง ์๋๋ค. ๊ทธ๋ฌ๋ฉด ์ ์ฅ๋ ํผ๊ท์ด๋ฅผ ์ฝ๋ ๊ถํ ๊ฒ์ฌ๊ฐ ์ ์ธ์์ ์ฌ๋ผ์ง๋ค. */
|
|
332
332
|
doors: ['Query.figure'],
|
|
333
333
|
description: 'Returns the source (the figure asset) of one figure, with its measured cost ' +
|
|
334
334
|
'(triangles, part groups, and how many of it hold 60fps on one screen). Call it before proposing a revision โ ' +
|
|
@@ -434,12 +434,12 @@ function figureToolSpecs() {
|
|
|
434
434
|
if (!prompt)
|
|
435
435
|
throw new Error('prompt is required: there is nothing to ask for');
|
|
436
436
|
/*
|
|
437
|
-
๊ณ ์น๋ ๊ฒ์ธ์ง ๋ง๋๋ ๊ฒ์ธ์ง๋ฅผ **๋ฌธ๋งฅ์์ ์ ํ๋ค.** ์ด๋ฆฐ
|
|
438
|
-
๋ชจ๋ธ์ด `create` ๋ฅผ ์ผ๋ฉด ๋ง๋๋ ๊ฒ์ด๋ค. ์ด๊ฒ์ ๋ชจ๋ธ์ ์ง์์ ๋งก๊ธฐ๋ฉด ์ด๋ ค ์๋
|
|
437
|
+
๊ณ ์น๋ ๊ฒ์ธ์ง ๋ง๋๋ ๊ฒ์ธ์ง๋ฅผ **๋ฌธ๋งฅ์์ ์ ํ๋ค.** ์ด๋ฆฐ ํผ๊ท์ด๊ฐ ์์ผ๋ฉด ๊ณ ์น๋ ๊ฒ์ด ๊ธฐ๋ณธ์ด๊ณ ,
|
|
438
|
+
๋ชจ๋ธ์ด `create` ๋ฅผ ์ผ๋ฉด ๋ง๋๋ ๊ฒ์ด๋ค. ์ด๊ฒ์ ๋ชจ๋ธ์ ์ง์์ ๋งก๊ธฐ๋ฉด ์ด๋ ค ์๋ ํผ๊ท์ด๋ฅผ ๋ฎ์ด์ฐ๋
|
|
439
439
|
ํ๋ณด๊ฐ ์จ๋ค.
|
|
440
440
|
|
|
441
441
|
๊ณ ์น๋ ์ ์์ ๋ชจ๋ธ๋ฌ๊ฐ **์์ฒญ ๋น์์ ํ(context ยท revision)** ์์ ํ ๋จ๊ณ๋ก ์ ์ฉํ๋ค(ADR-0094).
|
|
442
|
-
๊ทธ๋์ ๊ณ ์น ์ ์๋ ๊ฒ์ ๋ชจ๋ธ๋ฌ์ ์ด๋ฆฐ
|
|
442
|
+
๊ทธ๋์ ๊ณ ์น ์ ์๋ ๊ฒ์ ๋ชจ๋ธ๋ฌ์ ์ด๋ฆฐ ํผ๊ท์ด๋ฟ์ด๊ณ , ๊ทธ ํ์ ๋ฌธ๋งฅ์ด ํจ๊ป ์ค์ด ์์ผ ํ๋ค.
|
|
443
443
|
*/
|
|
444
444
|
const host = ctx?.host;
|
|
445
445
|
const create = args?.create === true || args?.figureId === null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figure-tools.js","sourceRoot":"","sources":["../../../server/service/figure/figure-tools.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * figure ์ ์ ๋๊ตฌ๋ฅผ ์ด์์คํดํธ ๋๊ตฌ ๋ ์ง์คํธ๋ฆฌ์ ๋ฑ๋ก โ **๋ํ๋ฉด(๋ํฌ)์์ ์ ์์ ๋๊ธฐ ์ํจ.**\n *\n * ์ ํ์ํ๊ฐ: `proposeFigure` ๋ ํ ๋ฒ ์ํค๊ณ ํ ๋ฒ ๋ฐ๋๋ค. ๊ทธ๊ฒ์ผ๋ก ๋๋ ์ผ์ด ์์ง๋ง, ์ ์์\n * ๋๊ฐ ใ์ด๊ฑธ ์ด๋ ๊ฒ ๊ณ ์ณ ๋ด โ ๋ฌด๊ฒ๊ฐ ์ผ๋ง๋ ๋๋ โ ๋ฐํ์ ๋๋ใ์ฒ๋ผ ์ฌ๋ฌ ์ฐจ๋ก ์ค๊ฐ๋ค. ๊ทธ ๋ํ๋ฅผ\n * ํ๋ ค๋ฉด ์ด์์คํดํธ๊ฐ **์ง๊ธ ๋ฌด์์ด ์๋์ง ์ฝ์ ์ ์์ด์ผ** ํ๋ค. ์ฝ์ง ๋ชปํ๋ฉด ๋งค๋ฒ ์ฌ๋์ด ์ ๋ณธ์\n * ๋ถ์ฌ ๋ฃ์ด์ผ ํ๊ณ , ๊ทธ๋ฌ๋ฉด ๋ํ๊ฐ ์๋๋ค.\n *\n * ๋ฅ๋ ฅ์ ๋ณต์ ํ์ง ์๋๋ค. figure-service ๊ฐ ์ด๋ฏธ ๊ฐ์ง ์ง์
์ (`inspectSource` ยท `proposeFigureSteps` ยท\n * ์กฐํ)์ ๋ ์ง์คํธ๋ฆฌ์ ํฌ์ํ๋ค.\n *\n * โโ ์ ๋ถ ์กฐํยท์ ์ ์ ์ฉ์ด๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ๋ณธ์ ๊ณ ์น๋ ๋๊ตฌ๋ฅผ ๋ฃ์ง ์๋๋ค. ํ์์ ์ค๊ณ๊ฐ ๊ทธ๋ ๊ฒ ์ ํด์ ธ ์๋ค โ ์ด์์คํดํธ๋ **ํ๋ณด**๋ฅผ\n * ๋ด๊ณ , ๋ฐ์์ง ๋ฒ๋ฆด์ง๋ ์ ์์๊ฐ ์ ํ๋ค(`figure-propose-steps.ts`, ADR-0094). ๋๋๋ฆด ์ ์๋ ์กฐ์์ด ๋ํ๋ฉด์ผ๋ก\n * ์์ง ์์ผ๋ฏ๋ก ์ ๋ถ `kind: 'read'` ๋ค.\n *\n * ์ ์ฅ์ ์ ์๋ฉด์ด `updateFigure` ๋ก ํ๋ค. ๊ทธ mutation ์ `figure:mutation` ์ด ์งํค๊ณ , ๋ํ๋\n * `ai-assistant:mutation` ์ด ์งํจ๋ค โ ์๋ก ๋ค๋ฅธ ์ง๋ฌธ์ด๋ผ ์๋ก ๋ค๋ฅธ ๊ถํ์ด ์งํจ๋ค. figure ๊ฐ board\n * ์ ๊ถํ์ ๋น๋ฆฌ์ง ์๋๋ค.\n *\n * โโ No privilege here. The gate reads what the door declares โโโโโโโโโโโโโโโโโโโโโ\n * Until 2026-09-18 each tool carried `privilege: { category: 'figure', ... }`. It matched the door's\n * directive then, and would drift the day the door changed its declaration โ and the looser copy wins.\n * Now the gate reads the declaration of each door in `doors` from AUTH's table (ADR-0071 decision 2,\n * addendum). What stays here is **the doors it reaches**.\n *\n * โโ ๊ท์จ์ ๋๊ตฌ์ ํจ๊ป ๋ณด๋ธ๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๋๊ตฌ ๋ชฉ๋ก๋ง์ผ๋ก๋ ใ์ธ์ ๋ฐ๋์ ๋ถ๋ฌ์ผ ํ๋์งใ๋ฅผ ๋ชจ๋ฅธ๋ค. twin ์ด ๊ทธ ๊ณต๋ฐฑ์์ ์ฌ๊ณ ๋ฅผ ๋๋ค โ\n * ์กฐ์น ์์ฒญ์ ๋๊ตฌ๋ฅผ ๋ถ๋ฅด์ง ์๊ณ ใ์ ์ํด ๋์์ต๋๋คใ๋ผ๊ณ ๋ง ๋ตํด, ์ฌ์ฉ์์๊ฒ **์๋ ๋ฒํผ์ ๋๋ฅด๋ผ๊ณ \n * ์๋ดํ๋ค.** figure ๋ ๋๊ฐ์ ์๋ฆฌ๊ฐ ์๋ค: ํ๋ณด ํ๋ฉด(ใ์ง๊ธ / ํ๋ณดใ ๋ ์นธ)์ **๋๊ตฌ ํธ์ถ ๊ฒฐ๊ณผ์์๋ง**\n * ๋ง๋ค์ด์ง๋ค. ๋ฌธ์ฅ์ผ๋ก๋ ์๋ฌด ์ผ๋ ์ผ์ด๋์ง ์๋๋ค.\n *\n * โโ LLM ์ด ๋๊ธด id ๋ฅผ ๋ฏฟ์ง ์๋๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ฌ๋์ด ๋ชฉ๋ก์์ ๊ณ ๋ฅด๋ ๊ธธ์์๋ ๋๋ฌ๋์ง ์์ง๋ง, ๋ชจ๋ธ์ ๋ํ ๋ด์ฉ์ ์ด๋๋ ค ์์์ id ๋ฅผ ๋๊ธธ ์\n * ์๋ค. ๊ทธ๋์ ํธ์ถ์ ๋๋ฉ์ธ ์์์ ๋จผ์ ํ์ธํ๋ค.\n */\nimport { randomUUID } from 'crypto'\nimport { ILike } from 'typeorm'\nimport {\n aiClientFor,\n registerToolCategory,\n type AIImageMediaType,\n type ToolAttachment,\n type ToolCallContext,\n type ToolCategory,\n type ToolImageAttachment,\n type ToolSpec\n} from '@things-factory/ai-client-base'\n\nimport { FIGURE_CONTEXT_BUDGET, figureViewOf, type FigureReadRequest } from './figure-context.js'\n\n/** How many figures a list without search names. */\nconst LIST_LIMIT = 200\n\n/*\n ์๋ฒ ์์กด์ฑ์ lazy require ๋ค. ๋ฑ๋ก์ ๋ถํ
์ด๋ฐ์ ํ๊ฐ๋๊ณ ๊ทธ๋ typeorm DataSource ๊ฐ ์ค๋น๋์ง\n ์์์ ์ ์๋ค(board-import ยท twin-ai ์ ๊ฐ์ ์ ์ฑ
).\n*/\nlet _deps: any | undefined\n\nfunction getDeps(): any {\n if (!_deps) {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const shell = require('@things-factory/shell')\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const model = require('@hatiolab/figure-model')\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const entity = require('./figure.js')\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const format = require('./figure-format.js')\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const proposer = require('./figure-propose-steps.js')\n _deps = {\n getRepository: shell.getRepository,\n Figure: entity.Figure,\n /* The same doors a save and a release go through. The tool reads; it never saves. */\n inspectSource: format.inspectSource,\n parseSource: format.parseSource,\n figureCostOf: model.figureCostOf,\n figureScoreOf: model.figureScoreOf,\n proposeFigureSteps: proposer.proposeFigureSteps,\n isPlaceholderType: model.isPlaceholderType\n }\n }\n return _deps\n}\n\n/** ์ํยท๊ฒ์ฆ ํ๋ค์ค ์ ์ฉ ์ฃผ์
์์. ์ด์ ๊ฒฝ๋ก์์ ํธ์ถ ๊ธ์ง. */\nexport function __setFigureToolDepsForTest(deps: any): void {\n _deps = deps\n}\n\nfunction requireDomainId(state: any): string {\n const id = state?.domain?.id\n if (!id) {\n // ๋๋ฉ์ธ์ ๋ชจ๋ฅด๋ฉด ๋ฌด์์ ์ฝ์ด๋ ๋จ์ ๊ฒ์ผ ์ ์๋ค. ์กฐ์ฉํ ๋๊ธฐ์ง ์๋๋ค.\n throw new Error('domain context is missing โ the figure tools cannot resolve tenant scope')\n }\n return id\n}\n\n/**\n * ์ด ๋ํ์ด ํธ์ถ์ ๋๋ฉ์ธ ๊ฒ์ธ๊ฐ.\n *\n * ๋ชจ๋ธ์ด ๋๊ธด id ๋ฅผ ๊ทธ๋๋ก ์ฐ์ง ์๋๋ค. ์์ผ๋ฉด ๋ชป ์ฐพ์๋ค๊ณ ๋งํ๋ค โ ใ๊ถํ์ด ์๋คใ์ ๊ตฌ๋ณํด\n * ์๋ ค ์ค ๊ฒ์ด ์๋ค(๋ค๋ฅธ ํ
๋ํธ์ ๊ทธ id ๊ฐ ์๋ค๋ ์ฌ์ค ์์ฒด๊ฐ ์๋ ค ์ค ๊ฒ์ด ์๋๋ค).\n */\nasync function figureInDomain(figureId: string, domainId: string): Promise<any> {\n const { getRepository, Figure } = getDeps()\n const found = await getRepository(Figure).findOne({\n where: { id: figureId, domain: { id: domainId } }\n })\n if (!found) {\n throw new Error(`figure not found in this tenant: ${figureId}`)\n }\n return found\n}\n\n/** The form of a creation id: the row id a new figure's first save inserts it under (`figure-mutation.ts`). */\nconst CREATION_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\n\n/**\n * The figure a tool is about: by id, or by its type name, in the caller's domain. None named: none.\n *\n * A figure not saved yet is a subject too (ADR-0061 decision 3): the modeller names it by its creation id, which its first\n * save inserts the row under (ADR-0072 decision 6), so before that save there is no row. It is the figure open on that\n * screen and nothing else: the id the screen has open, with the draft the screen sent. What is read is that draft, put\n * through the save's door like any draft (`sourceForTool`); nothing the server holds is read for it.\n */\nasync function resolveFigureTarget(figureId: string | undefined, domainId: string, host: any): Promise<any> {\n if (!figureId) return undefined\n const { getRepository, Figure } = getDeps()\n const found =\n (await getRepository(Figure).findOne({ where: { id: figureId, domain: { id: domainId } } })) ??\n (await getRepository(Figure).findOne({ where: { type: figureId, domain: { id: domainId } } }))\n if (found) return found\n const draft = host?.draftSource\n if (CREATION_ID.test(figureId) && host?.figureId === figureId && draft && typeof draft === 'object') {\n return { id: figureId, name: typeof draft.name === 'string' ? draft.name : undefined, source: null }\n }\n throw new Error(`figure not found in this tenant: ${figureId}`)\n}\n\n/**\n * The source a tool reads: the draft on screen when the modeller has this figure open, else the stored one.\n *\n * The host context is the browser's, so it is no ground for access: the row is found in the domain first, and the\n * draft is put through the same door a save goes through before anything reads it.\n */\nconst isFigure = (source: any) => source?.version === 'figure-asset-1'\n\n/**\n * A revision is applied by the modeller on the version the model saw (ADR-0094), so only the figure open there can be\n * revised. Said as what is true, with what the assistant can do instead.\n */\nfunction figureNotOpen() {\n return {\n error: 'FIGURE_NOT_OPEN',\n message: 'A revision can be proposed only for the figure open in the modeller.',\n nextStep:\n 'Tell the person to open the figure in the modeller and ask again there. A new figure needs no open one: call proposeFigureCandidate with create: true.'\n }\n}\n\nfunction sourceForTool(row: any, host: any): { source: any; draft: boolean } {\n const draft = host?.figureId === row.id ? host?.draftSource : undefined\n if (!draft) return { source: row.source ? JSON.parse(row.source) : null, draft: false }\n\n if (typeof draft !== 'object' || Array.isArray(draft)) throw new Error('the unsaved draft is not a figure asset')\n const serialized = JSON.stringify(draft)\n /* Validity is the save door's (the kernel's 1 MiB); how much the model is shown is `figure-context`'s. */\n try {\n getDeps().parseSource(serialized)\n } catch (e: any) {\n const findings = Array.isArray(e?.findings) ? e.findings.map((one: any) => one.message).join(' ยท ') : String(e?.message ?? e)\n throw new Error(`the unsaved draft is invalid: ${findings}`)\n }\n return { source: draft, draft: true }\n}\n\n/** The finite numbers of an untrusted record, by name; none: undefined. */\nfunction numbersOf(record: any): Record<string, number> | undefined {\n if (!record || typeof record !== 'object' || Array.isArray(record)) return undefined\n const kept = Object.entries(record).filter((entry): entry is [string, number] => typeof entry[1] === 'number' && Number.isFinite(entry[1]))\n return kept.length ? Object.fromEntries(kept) : undefined\n}\n\n/**\n * What the person has in view on the open draft: the part selected and what the preview is trying (ADR-0097 ยง5.6\n * item 5). The model hears it only here, through a read (ADR-0061 decision 3). Told only when it was seen on the version\n * being read -- a selection from another version may name a part that is gone -- and a part only when the draft has it.\n */\nfunction focusOf(host: any, source: any): { selection?: { part: string }; trying?: { clips?: Record<string, number>; controls?: Record<string, number> } } {\n const onThisVersion = (seen: any) => typeof host?.context === 'string' && seen?.context === host.context && seen?.revision === host.revision\n const focus: ReturnType<typeof focusOf> = {}\n\n const part = host?.selection?.part\n const nodes = source?.document?.model?.nodes\n if (typeof part === 'string' && onThisVersion(host.selection) && Array.isArray(nodes) && nodes.some((node: any) => node?.id === part)) {\n focus.selection = { part }\n }\n\n if (onThisVersion(host?.trying)) {\n const clips = numbersOf(host.trying.clips)\n const controls = numbersOf(host.trying.controls)\n if (clips || controls) focus.trying = { ...(clips ? { clips } : {}), ...(controls ? { controls } : {}) }\n }\n return focus\n}\n\n/**\n * ๋ฌด์์ ๊ณ ์น๋ผ๋ ๊ฒ์ธ์ง ๋ํ๋ฉด ๋ฌธ๋งฅ์์ ํด์ํ๋ค.\n *\n * ๋ชจ๋ธ์ด ๋์์ ์ ์คฌ์ผ๋ฉด **์ ์๋ฉด์ด ์ง๊ธ ์ด๊ณ ์๋ ๋ํ**์ด๋ค. ์ฌ์ฉ์์๊ฒ ์๋ณ์๋ฅผ ๋๋ฌป์ง\n * ์๋๋ค โ ํ๋ฉด์ ๊ทธ ๋ํ์ด ๋ ์๋๋ฐ ใ์ด๋ ๋ํ์
๋๊นใ๋ฅผ ๋ฌป๋ ๊ฒ์ ๋ฌธ๋งฅ์ ์ ์ฝ์ ๊ฒ์ด๋ค.\n */\nfunction figureIdFrom(args: any, host: any): string | undefined {\n const said = typeof args?.figureId === 'string' ? args.figureId.trim() : ''\n if (said) return said\n\n const open = typeof host?.figureId === 'string' ? host.figureId.trim() : ''\n if (open) return open\n\n return undefined\n}\n\nfunction missingFigureTarget() {\n return {\n error: 'FIGURE_TARGET_REQUIRED',\n message: 'No figure is open on this screen.',\n nextStep: 'For an existing figure, call listFigures and match the userโs requested name or type; ask which figure only if ambiguous. For a new figure, call proposeFigureCandidate with create: true and the userโs prompt. Do not invent an id or repeat this call without a target.'\n }\n}\n\nconst FIGURE_ID_ARG = {\n figureId: {\n type: 'string',\n description: 'The figure to read. Omit to read the one open in the modeller โ with its unsaved changes, and also when it is a new figure not saved yet; the server fills it in, and you cannot see which it is. A figure not saved yet is readable only while it is open in the modeller. On the catalog nothing is open, so resolve the figure the person asked for with listFigures first.'\n }\n} as const\n\nconst PARTS_ARG = {\n parts: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Only for a figure too large to read whole (the answer then has `outline` and no `source`): the ids of the parts to read in full, from `outline.parts`. Omit to read the part selected.'\n },\n sections: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Only for a figure too large to read whole: JSON Pointers of sections to read, such as one named in `outline.omitted` or its `entries` (for example /document/capabilities/bindings/0).'\n }\n} as const\n\n/**\n * A figure too large to show whole, as the model reads it (ADR-0061 2026-10-16 decision 4): its outline and the parts\n * asked for. The full source stays here; what is measured is measured on it.\n */\nfunction partialRead(source: any, request: FigureReadRequest) {\n const view = figureViewOf(source, request)\n if (view.whole) return { source }\n return {\n outline: view.outline,\n partSources: view.parts,\n ...(Object.keys(view.sections ?? {}).length ? { sectionSources: view.sections } : {}),\n ...(view.notRead ? { notRead: view.notRead } : {}),\n note:\n `This figure is too large to read whole (${view.outline!.chars} characters; ${FIGURE_CONTEXT_BUDGET} are read at once), so this is its outline, the parts in partSources and the sections in sectionSources. ` +\n 'Read what a change touches with parts and sections, then pass the same to proposeFigureCandidate: only parts read in full may be changed, and nothing in a section in outline.omitted that was not read.'\n }\n}\n\n/** The parts the model named, as strings; anything else is dropped. */\nconst stringsOf = (list: unknown): string[] =>\n Array.isArray(list) ? list.filter((one: unknown): one is string => typeof one === 'string' && !!one.trim()).map((one: string) => one.trim()) : []\n\n/** An inspection whose findings would crowd the model's context, cut to the budget with how many there were. */\nfunction findingsWithinBudget(inspection: any) {\n const findings = Array.isArray(inspection?.findings) ? inspection.findings : []\n if (JSON.stringify(inspection).length <= FIGURE_CONTEXT_BUDGET) return inspection\n const head = JSON.stringify({ ...inspection, findings: [], truncated: { shown: findings.length, total: findings.length } }).length\n let room = FIGURE_CONTEXT_BUDGET - head\n const shown: any[] = []\n for (const finding of findings) {\n const cost = JSON.stringify(finding).length + 1\n if (cost > room) break\n shown.push(finding)\n room -= cost\n }\n return { ...inspection, findings: shown, truncated: { shown: shown.length, total: findings.length } }\n}\n\n/**\n * ๋๊ตฌ ๋ท.\n *\n * ๋ชฉ๋ก ยท ์ ๋ณธ ยท ๋ฐํ ํ์ ยท ํ๋ณด. ์ ์ ๋ํ์์ ์ค์ ๋ก ๋ฌป๋ ๊ฒ์ด ๊ทธ ๋ท์ด๋ค โ ใ๋ฌด์์ด ์๋ใ\n * ใ์ง๊ธ ์ด๋ป๊ฒ ์๊ฒผ๋ใ ใ๋ฐํ์ด ์ ์ ๋๋ใ ใ์ด๋ ๊ฒ ๊ณ ์ณ ๋ดใ.\n */\nfunction figureToolSpecs(): ToolSpec[] {\n return [\n {\n kind: 'read',\n name: 'listFigures',\n /* ์ด ๋๋ฉ์ธ์ ๋ํ ๋ชฉ๋ก โ ์ ์ฅ์๋ฅผ ์ง์ ์ฝ์ง๋ง ๊ฐ์ ์ผ์ ํ๋ ๋ฌธ์ ์ด๊ฒ์ด๋ค. */\n doors: ['Query.figures'],\n description:\n 'Lists the figures in this tenant with their type names, states and part counts. ' +\n 'Call it before naming a type โ type names are stored identifiers and must not be invented. ' +\n `Without search it lists the ${LIST_LIMIT} most recently changed; when there are more it says truncated, and a figure the person names may be among the rest - list again with search.`,\n schema: {\n type: 'object',\n properties: {\n search: {\n type: 'string',\n description: 'Part of a figure name or type name, in any case. Omit to list the most recently changed.'\n }\n }\n },\n builder: async (args: any, ctx: any) => {\n const domainId = requireDomainId(ctx?.state)\n const { getRepository, Figure } = getDeps()\n const search = typeof args?.search === 'string' ? args.search.trim() : ''\n const domain = { id: domainId }\n /* `_` and `%` in the words are LIKE wildcards: they can only widen what is found, never hide a match. */\n const where = search\n ? [\n { domain, name: ILike(`%${search}%`) },\n { domain, type: ILike(`%${search}%`) }\n ]\n : { domain }\n /* One more than is shown, to know whether there is more without counting the table. */\n const rows = await getRepository(Figure).find({ where, order: { updatedAt: 'DESC' }, take: LIST_LIMIT + 1 })\n const truncated = rows.length > LIST_LIMIT\n return {\n ...(truncated\n ? {\n truncated: true,\n note: `Only the ${LIST_LIMIT} most recently changed are listed. A figure not here may still exist: call listFigures again with search.`\n }\n : {}),\n figures: rows.slice(0, LIST_LIMIT).map((row: any) => ({\n id: row.id,\n type: row.type,\n name: row.name,\n state: row.state,\n score: row.score,\n triangles: row.triangles\n }))\n }\n }\n },\n {\n kind: 'read',\n name: 'getFigureSource',\n /* ์ ์ฅ๋ ๋ํ์ ์๋ณธ. **์ ์ฅ ์ ์ด์**์ ๋ฌผ์ผ๋ฉด ์ ์ฅ์์ ๊ฐ ๊ฒ์ด ์์ด ํ๋ฉด์ด ๋ณด๋ธ ๊ฒ์ ๊ทธ๋๋ก ๋๋ ค์ค๋ค โ\n * ๊ทธ ๊ฐ๋์๋ ๋ฟ๋ ๋ฌธ์ด ์์ง๋ง `doors: []` ๋ก ์ ์ง ์๋๋ค. ๊ทธ๋ฌ๋ฉด ์ ์ฅ๋ ๋ํ์ ์ฝ๋ ๊ถํ ๊ฒ์ฌ๊ฐ ์ ์ธ์์ ์ฌ๋ผ์ง๋ค. */\n doors: ['Query.figure'],\n description:\n 'Returns the source (the figure asset) of one figure, with its measured cost ' +\n '(triangles, part groups, and how many of it hold 60fps on one screen). Call it before proposing a revision โ ' +\n 'revising without reading it means proposing against a guess. On the figure open in the modeller it also says what ' +\n 'the person has in view: `selection.part` is the part selected - \"this part\" or \"the selected one\" means it - and ' +\n '`trying` the clip and control values the preview is trying, which are not part of the figure. ' +\n 'A figure too large to read whole comes as `outline` (every part by name, shape and what it is fastened to) and ' +\n '`partSources` (the parts read in full) instead of `source`.',\n schema: { type: 'object', properties: { ...FIGURE_ID_ARG, ...PARTS_ARG } },\n builder: async (args: any, ctx: any) => {\n const domainId = requireDomainId(ctx?.state)\n const figureId = figureIdFrom(args, ctx?.host)\n const row = await resolveFigureTarget(figureId, domainId, ctx?.host)\n if (!row) return missingFigureTarget()\n\n const current = sourceForTool(row, ctx?.host)\n if (!current.source) {\n // ์ ์ฅ๋ ์ ๋ณธ์ด ์๋ ์ํ๊ฐ ์ค์ ๋ก ์๋ค(์๋ก ๋ง๋ค๊ณ ์ ์ฅ ์ ํ ๊ฒ). ์ง์ด๋ด์ง ์๋๋ค.\n return { id: row.id, type: row.type, name: row.name, source: null, cost: null }\n }\n\n /* Measured as the catalogue measures it: triangles, draw groups, and its grade against one screen. */\n const { figureCostOf, figureScoreOf } = getDeps()\n /* What is in view belongs to the draft on screen; the stored source may be another figure than the one open. */\n const focus = current.draft ? focusOf(ctx?.host, current.source) : {}\n const asked = stringsOf(args?.parts)\n return {\n id: row.id,\n type: row.type,\n name: row.name,\n state: row.state,\n ...partialRead(current.source, { parts: asked.length ? asked : focus.selection ? [focus.selection.part] : [], sections: stringsOf(args?.sections) }),\n draft: current.draft,\n cost: figureCostOf(current.source),\n score: figureScoreOf(current.source) ?? null,\n ...focus\n }\n }\n },\n {\n kind: 'read',\n name: 'inspectFigure',\n /* ๊ฒ์ฌ ๊ฒฐ๊ณผ โ ๊ฐ์ ์ผ์ ํ๋ ๋ฌธ. */\n doors: ['Query.inspectFigure'],\n description:\n 'Says whether a figure may be released and, when it may not, what is wrong โ each finding ' +\n 'carries why it is a problem and what to change. Call it when asked about releasing, or ' +\n 'when asked to fix a figure that will not release.',\n schema: { type: 'object', properties: { ...FIGURE_ID_ARG } },\n builder: async (args: any, ctx: any) => {\n const domainId = requireDomainId(ctx?.state)\n const figureId = figureIdFrom(args, ctx?.host)\n const row = await resolveFigureTarget(figureId, domainId, ctx?.host)\n if (!row) return missingFigureTarget()\n\n const current = sourceForTool(row, ctx?.host)\n const { inspectSource } = getDeps()\n /* Inspected whole, here; only what the model is told is held to its budget. */\n return { ...findingsWithinBudget(inspectSource(current.source ? JSON.stringify(current.source) : null, null, undefined, row.type, row.category)), draft: current.draft }\n }\n },\n {\n kind: 'read',\n name: 'proposeFigureCandidate',\n /* ํ๋ณด ์์ฑ โ ์ ์ฅ์ ํ์ง ์์ง๋ง ๊ฐ์ ๋ฌธ์ ๊ถํ์ ์ด๋ค. */\n doors: ['Mutation.proposeFigure'],\n description:\n 'Asks for a proposal: the modeller commands that make a new figure or revise the one open in the modeller. ' +\n 'Returns the commands with the score and cost of the figure they make. NOTHING IS SAVED โ the author applies ' +\n 'the proposal in the modeller as one step, or leaves it. This is the only way a proposal reaches the screen.',\n schema: {\n type: 'object',\n properties: {\n prompt: {\n type: 'string',\n description: 'What to make or change, in the words the author used, with the sizes as they said them: do not turn sizes into axes.'\n },\n figureId: {\n type: 'string',\n description: 'Revise this figure; it must be the one open in the modeller. Omit to revise the open one; pass null to create anew.'\n },\n name: {\n type: 'string',\n description: 'The name a person reads for a new figure.'\n },\n create: {\n type: 'boolean',\n description: 'True to create rather than revise, even with a figure open.'\n },\n parts: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Only for a figure too large to read whole: the parts this change touches, read first with getFigureSource parts. Only these and the part selected may be changed; new parts may be added and fastened to any part.'\n },\n sections: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Only for a figure too large to read whole: JSON Pointers of the sections in outline.omitted this change touches, read first with getFigureSource sections. Nothing else in those sections may be changed.'\n }\n },\n required: ['prompt']\n },\n builder: async (args: any, ctx: ToolCallContext) => {\n const domainId = requireDomainId(ctx?.state)\n const prompt = typeof args?.prompt === 'string' ? args.prompt.trim() : ''\n if (!prompt) throw new Error('prompt is required: there is nothing to ask for')\n\n /*\n ๊ณ ์น๋ ๊ฒ์ธ์ง ๋ง๋๋ ๊ฒ์ธ์ง๋ฅผ **๋ฌธ๋งฅ์์ ์ ํ๋ค.** ์ด๋ฆฐ ๋ํ์ด ์์ผ๋ฉด ๊ณ ์น๋ ๊ฒ์ด ๊ธฐ๋ณธ์ด๊ณ ,\n ๋ชจ๋ธ์ด `create` ๋ฅผ ์ผ๋ฉด ๋ง๋๋ ๊ฒ์ด๋ค. ์ด๊ฒ์ ๋ชจ๋ธ์ ์ง์์ ๋งก๊ธฐ๋ฉด ์ด๋ ค ์๋ ๋ํ์ ๋ฎ์ด์ฐ๋\n ํ๋ณด๊ฐ ์จ๋ค.\n\n ๊ณ ์น๋ ์ ์์ ๋ชจ๋ธ๋ฌ๊ฐ **์์ฒญ ๋น์์ ํ(context ยท revision)** ์์ ํ ๋จ๊ณ๋ก ์ ์ฉํ๋ค(ADR-0094).\n ๊ทธ๋์ ๊ณ ์น ์ ์๋ ๊ฒ์ ๋ชจ๋ธ๋ฌ์ ์ด๋ฆฐ ๋ํ๋ฟ์ด๊ณ , ๊ทธ ํ์ ๋ฌธ๋งฅ์ด ํจ๊ป ์ค์ด ์์ผ ํ๋ค.\n */\n const host = ctx?.host\n const create = args?.create === true || args?.figureId === null\n let base: unknown\n let figureId: string | undefined\n let focus: ReturnType<typeof focusOf> | undefined\n if (!create) {\n const said = typeof args?.figureId === 'string' ? args.figureId.trim() : ''\n const open = typeof host?.figureId === 'string' ? host.figureId.trim() : ''\n if (said && said !== open) {\n await figureInDomain(said, domainId)\n return figureNotOpen()\n }\n if (!open) return missingFigureTarget()\n const row = await resolveFigureTarget(open, domainId, host)\n if (!row) return missingFigureTarget()\n const current = sourceForTool(row, host)\n base = current.source ?? undefined\n if (!isFigure(base)) return figureNotOpen()\n if (typeof host?.context !== 'string' || !Number.isInteger(host?.revision)) return figureNotOpen()\n figureId = open\n /* \"Make this one bigger\": the part selected is what the request points at. */\n if (current.draft) focus = focusOf(host, base)\n }\n\n /*\n The pictures the person sent with this turn, as the server checked them (ADR-0061, 2026-10-16 decision 2) --\n every one, in the order attached. Never from the host context: the client fills it.\n */\n const images = (ctx?.attachments ?? [])\n .filter((file: ToolAttachment): file is ToolImageAttachment => file.kind === 'image')\n .map(file => ({ data: file.data, mediaType: file.mediaType as AIImageMediaType }))\n\n const { proposeFigureSteps } = getDeps()\n let result: any\n try {\n result = await proposeFigureSteps({\n /* The agent of this conversation's turn - the one the person picked, or the domain default. */\n client: await aiClientFor({\n domain: ctx?.state?.domain,\n user: ctx?.state?.user,\n agentId: ctx?.state?.aiAgentId,\n modeKind: ctx?.mode?.kind\n }),\n prompt,\n base,\n name: typeof args?.name === 'string' && args.name.trim() ? args.name.trim() : undefined,\n ...(images.length ? { images } : {}),\n ...(focus && Object.keys(focus).length ? { focus } : {}),\n ...(!create && (stringsOf(args?.parts).length || stringsOf(args?.sections).length)\n ? { read: { parts: stringsOf(args?.parts), sections: stringsOf(args?.sections) } }\n : {})\n })\n } catch (error) {\n /*\n * ์ธ ๋ฒ ๊ฑฐ์ ๋ ๋์ ์ฌ์ ๋ฅผ ProposeFigureFailure.reasons ์๋ง ๋๋ฉด agentic-loop ์ ใ๋ง๋ค์ง ๋ชปํ์ต๋๋คใ๋ง\n * ๋ฐ์ ํ๋ฉด์๋ ใ์๋ต์ด ๋น์ด์์ต๋๋คใ๊ฐ ๋๋ค. ๋ค์ ์๋ํ ์ ์๋ ๋ง๋ก ๊ฒฝ๊ณ๋ฅผ ๋๊ธด๋ค.\n * ๋ค๋ฅธ ์์ธ(๊ถํยทํต์ )๋ ์๋ฌธ์ ๋ณด์กดํ๋ค.\n */\n const reasons = Array.isArray((error as any)?.reasons) ? (error as any).reasons : []\n if (reasons.length > 0) throw new Error([(error as Error).message, ...reasons].join('\\n'))\n throw error\n }\n\n /*\n **`proposed: true` ๊ฐ ์นด๋๋ฅผ ๋ง๋ ๋ค.** ์ด ํ์๊ฐ ์์ผ๋ฉด ์ ์์ ๋๊ตฌ ์ถ์ ์์ ๋ฌปํ๊ณ ํ๋ฉด์๋\n ์๋ฌด๊ฒ๋ ์๊ธฐ์ง ์๋๋ค. ์นด๋์ ์คํ ๋จ์ถ๊ฐ figure-ui ์ ์ฒ๋ฆฌ๊ธฐ์ ๋๊ธฐ๊ณ , ์ฒ๋ฆฌ๊ธฐ๊ฐ ๋ชจ๋ธ๋ฌ์ ๋ช
๋ น\n ๋ชฉ๋ก์ ํ ๋จ๊ณ๋ก ์ ์ฉํ๋ค. `args` ๋ ๊ฐ์ ์ ์์ ๋ ๋ฒ ์ธ์ง ์๊ธฐ ์ํ ์ด์ ์ ์ผ๋ถ๋ค.\n */\n const name = result.source.name || 'Figure'\n /* The card is read by a person, so the server writes it in the request's language (ADR-0061, 2026-10-16 decision 1). */\n const t = ctx.t\n return {\n proposed: true,\n /*\n The proposal's own name, given once here (ADR-0097 ยง5.6 item 5; AI lane, 09-27): the dock keys its card by\n it, a new figure made from it is created under it (the row id), and a save records it -- so what became of\n it can be asked after a reload, and the same proposal never makes two figures.\n */\n key: randomUUID(),\n icon: 'view_in_ar',\n label: create\n ? t('figure.proposal.label-create', { name, defaultValue: 'Make {name}' })\n : t('figure.proposal.label-revise', { name, defaultValue: 'Revise {name}' }),\n reason: t('figure.proposal.reason', {\n steps: result.steps.length,\n grade: result.score?.grade ?? '-',\n triangles: result.cost.triangles,\n attempts: result.attempts,\n defaultValue: '{steps} commands ยท grade {grade} ยท {triangles} triangles ยท made in {attempts} tries'\n }),\n args: { prompt, figureId, create },\n create,\n figureId,\n context: create ? undefined : host.context,\n revision: create ? undefined : host.revision,\n steps: result.steps,\n score: result.score,\n cost: result.cost,\n attempts: result.attempts\n }\n }\n }\n ] as ToolSpec[]\n}\n\n/**\n * ๋ฑ๋ก โ ๋ถํ
์ 1ํ.\n *\n * ๋ฒ์ฃผ๊ฐ ํ๋๋ค. twin ์ ๊ด์ฐฐ๊ณผ ์์ฑ์ ๋๋ก ๊ฐ๋๋๋ฐ(์ด์ ํ์์ ์์ฑ ๋๊ตฌ๊ฐ ๋ค๋ ค ์์ผ๋ฉด ๋ํ์\n * ์ฑ๊ฒฉ์ด ํ๋ ค์ง๋ค), figure ์ ๋ํ๋ฉด์ ์ ์๋ฉด ํ๋๋ฟ์ด๊ณ ๊ทธ ์๋ฆฌ์์ ์ฝ๊ธฐ์ ํ๋ณด ์์ฒญ์ด ํจ๊ป ํ์ํ๋ค.\n * ๋ํ๋ฉด์ด ๋๋ฉด ๊ทธ๋ ๊ฐ๋ฅธ๋ค.\n */\nexport function registerFigureToolCategories(): void {\n const authoring: ToolCategory = {\n name: 'figure-authoring',\n description: 'Reads the source, cost and release verdict of the figure being authored, and proposes changes (nothing is saved).',\n guidance: [\n '- **For a request to make or change a figure, always call `proposeFigureCandidate`.** A proposal exists only as the result of that call.',\n ' Writing \"I made a proposal\" or \"press apply\" without the call is **false**: no card appears, and the person looks for a button that does not exist.',\n ' A proposal is a list of modeller commands. The modeller applies it as one step only when the person runs it from the dock card, and one undo takes it all back. Do not say the figure has changed before that.',\n ' A revision can be proposed only for the figure open in the modeller. Say what the result\\'s `steps` do as they are; do not invent changes the commands do not make.',\n '- Never save the source yourself. Propose; the author decides on the screen whether to take it.',\n '- In the prompt to `proposeFigureCandidate`, pass the person\\'s words as they are: their sizes, counts and names. Do not turn them into axes; the writer knows the figure\\'s axes. When you name an axis to the person, the figure\\'s Y is up.',\n '- **For a request to change a figure, call `getFigureSource` first.** Revising without reading proposes against a guess, and a renamed part breaks the bindings of the boards it is already placed on.',\n '- On the catalog nothing is open. To read an existing figure, find the id of the name or type the person said with `listFigures`; ask which figure only when it is ambiguous. To revise an existing figure, tell the person to open it in the modeller and ask there. For a new figure, do not read existing sources: call `proposeFigureCandidate` with create: true.',\n '- Do not invent type names; check them with `listFigures`. **A type name is a stored identifier**, and boards find the figure by it. A new figure\\'s type is set by a person at its first save.',\n '- When asked why a figure will not release, call `inspectFigure`. Do not say it can be released without its verdict.',\n ' Each finding carries **why it is a problem and what to change**. Pass it on as it is; a summary makes the author look again for which axis of which part to fix.',\n '- For weight or triangle counts, use `cost` from `getFigureSource`. Do not estimate.'\n ].join('\\n'),\n specs: figureToolSpecs()\n }\n\n registerToolCategory(authoring)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"figure-tools.js","sourceRoot":"","sources":["../../../server/service/figure/figure-tools.ts"],"names":[],"mappings":";;AAwFA,gEAEC;AAkfD,oEAsBC;AAlmBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,mCAAmC;AACnC,qCAA+B;AAC/B,mEASuC;AAEvC,2DAAiG;AAEjG,oDAAoD;AACpD,MAAM,UAAU,GAAG,GAAG,CAAA;AAEtB;;;EAGE;AACF,IAAI,KAAsB,CAAA;AAE1B,SAAS,OAAO;IACd,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,8DAA8D;QAC9D,MAAM,KAAK,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAA;QAC9C,8DAA8D;QAC9D,MAAM,KAAK,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAA;QAC/C,8DAA8D;QAC9D,MAAM,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;QACrC,8DAA8D;QAC9D,MAAM,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAA;QAC5C,8DAA8D;QAC9D,MAAM,QAAQ,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAA;QACrD,KAAK,GAAG;YACN,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,qFAAqF;YACrF,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,kBAAkB,EAAE,QAAQ,CAAC,kBAAkB;YAC/C,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;SAC3C,CAAA;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,yCAAyC;AACzC,SAAgB,0BAA0B,CAAC,IAAS;IAClD,KAAK,GAAG,IAAI,CAAA;AACd,CAAC;AAED,SAAS,eAAe,CAAC,KAAU;IACjC,MAAM,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,EAAE,CAAA;IAC5B,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,4CAA4C;QAC5C,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAA;IAC7F,CAAC;IACD,OAAO,EAAE,CAAA;AACX,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,cAAc,CAAC,QAAgB,EAAE,QAAgB;IAC9D,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,CAAA;IAC3C,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;QAChD,KAAK,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE;KAClD,CAAC,CAAA;IACF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,oCAAoC,QAAQ,EAAE,CAAC,CAAA;IACjE,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,+GAA+G;AAC/G,MAAM,WAAW,GAAG,wEAAwE,CAAA;AAE5F;;;;;;;GAOG;AACH,KAAK,UAAU,mBAAmB,CAAC,QAA4B,EAAE,QAAgB,EAAE,IAAS;IAC1F,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAA;IAC/B,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,CAAA;IAC3C,MAAM,KAAK,GACT,CAAC,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;QAC5F,CAAC,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;IAChG,IAAI,KAAK;QAAE,OAAO,KAAK,CAAA;IACvB,MAAM,KAAK,GAAG,IAAI,EAAE,WAAW,CAAA;IAC/B,IAAI,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,QAAQ,KAAK,QAAQ,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACpG,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;IACtG,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,oCAAoC,QAAQ,EAAE,CAAC,CAAA;AACjE,CAAC;AAED;;;;;GAKG;AACH,MAAM,QAAQ,GAAG,CAAC,MAAW,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,gBAAgB,CAAA;AAEtE;;;GAGG;AACH,SAAS,aAAa;IACpB,OAAO;QACL,KAAK,EAAE,iBAAiB;QACxB,OAAO,EAAE,sEAAsE;QAC/E,QAAQ,EACN,wJAAwJ;KAC3J,CAAA;AACH,CAAC;AAED,SAAS,aAAa,CAAC,GAAQ,EAAE,IAAS;IACxC,MAAM,KAAK,GAAG,IAAI,EAAE,QAAQ,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,SAAS,CAAA;IACvE,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;IAEvF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;IACjH,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IACxC,0GAA0G;IAC1G,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,CAAA;IACnC,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,IAAI,CAAC,CAAC,CAAA;QAC7H,MAAM,IAAI,KAAK,CAAC,iCAAiC,QAAQ,EAAE,CAAC,CAAA;IAC9D,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;AACvC,CAAC;AAED,2EAA2E;AAC3E,SAAS,SAAS,CAAC,MAAW;IAC5B,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAA;IACpF,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAA6B,EAAE,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAC3I,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AAC3D,CAAC;AAED;;;;GAIG;AACH,SAAS,OAAO,CAAC,IAAS,EAAE,MAAW;IACrC,MAAM,aAAa,GAAG,CAAC,IAAS,EAAE,EAAE,CAAC,OAAO,IAAI,EAAE,OAAO,KAAK,QAAQ,IAAI,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC,OAAO,IAAI,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC,QAAQ,CAAA;IAC5I,MAAM,KAAK,GAA+B,EAAE,CAAA;IAE5C,MAAM,IAAI,GAAG,IAAI,EAAE,SAAS,EAAE,IAAI,CAAA;IAClC,MAAM,KAAK,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAA;IAC5C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACtI,KAAK,CAAC,SAAS,GAAG,EAAE,IAAI,EAAE,CAAA;IAC5B,CAAC;IAED,IAAI,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAC1C,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAChD,IAAI,KAAK,IAAI,QAAQ;YAAE,KAAK,CAAC,MAAM,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAA;IAC1G,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,IAAS,EAAE,IAAS;IACxC,MAAM,IAAI,GAAG,OAAO,IAAI,EAAE,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IAC3E,IAAI,IAAI;QAAE,OAAO,IAAI,CAAA;IAErB,MAAM,IAAI,GAAG,OAAO,IAAI,EAAE,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IAC3E,IAAI,IAAI;QAAE,OAAO,IAAI,CAAA;IAErB,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,SAAS,mBAAmB;IAC1B,OAAO;QACL,KAAK,EAAE,wBAAwB;QAC/B,OAAO,EAAE,mCAAmC;QAC5C,QAAQ,EAAE,4QAA4Q;KACvR,CAAA;AACH,CAAC;AAED,MAAM,aAAa,GAAG;IACpB,QAAQ,EAAE;QACR,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,gXAAgX;KAC9X;CACO,CAAA;AAEV,MAAM,SAAS,GAAG;IAChB,KAAK,EAAE;QACL,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACzB,WAAW,EACT,wLAAwL;KAC3L;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACzB,WAAW,EACT,wLAAwL;KAC3L;CACO,CAAA;AAEV;;;GAGG;AACH,SAAS,WAAW,CAAC,MAAW,EAAE,OAA0B;IAC1D,MAAM,IAAI,GAAG,IAAA,gCAAY,EAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC1C,IAAI,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,MAAM,EAAE,CAAA;IACjC,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,WAAW,EAAE,IAAI,CAAC,KAAK;QACvB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrF,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClD,IAAI,EACF,2CAA2C,IAAI,CAAC,OAAQ,CAAC,KAAK,gBAAgB,yCAAqB,2GAA2G;YAC9M,0MAA0M;KAC7M,CAAA;AACH,CAAC;AAED,uEAAuE;AACvE,MAAM,SAAS,GAAG,CAAC,IAAa,EAAY,EAAE,CAC5C,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAY,EAAiB,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;AAEnJ,gHAAgH;AAChH,SAAS,oBAAoB,CAAC,UAAe;IAC3C,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAA;IAC/E,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,MAAM,IAAI,yCAAqB;QAAE,OAAO,UAAU,CAAA;IACjF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,UAAU,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAA;IAClI,IAAI,IAAI,GAAG,yCAAqB,GAAG,IAAI,CAAA;IACvC,MAAM,KAAK,GAAU,EAAE,CAAA;IACvB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAA;QAC/C,IAAI,IAAI,GAAG,IAAI;YAAE,MAAK;QACtB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACnB,IAAI,IAAI,IAAI,CAAA;IACd,CAAC;IACD,OAAO,EAAE,GAAG,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAA;AACvG,CAAC;AAED;;;;;GAKG;AACH,SAAS,eAAe;IACtB,OAAO;QACL;YACE,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,aAAa;YACnB,mDAAmD;YACnD,KAAK,EAAE,CAAC,eAAe,CAAC;YACxB,WAAW,EACT,kFAAkF;gBAClF,6FAA6F;gBAC7F,+BAA+B,UAAU,8IAA8I;YACzL,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,MAAM,EAAE;wBACN,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,0FAA0F;qBACxG;iBACF;aACF;YACD,OAAO,EAAE,KAAK,EAAE,IAAS,EAAE,GAAQ,EAAE,EAAE;gBACrC,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;gBAC5C,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,CAAA;gBAC3C,MAAM,MAAM,GAAG,OAAO,IAAI,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;gBACzE,MAAM,MAAM,GAAG,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAA;gBAC/B,yGAAyG;gBACzG,MAAM,KAAK,GAAG,MAAM;oBAClB,CAAC,CAAC;wBACE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAA,eAAK,EAAC,IAAI,MAAM,GAAG,CAAC,EAAE;wBACtC,EAAE,MAAM,EAAE,IAAI,EAAE,IAAA,eAAK,EAAC,IAAI,MAAM,GAAG,CAAC,EAAE;qBACvC;oBACH,CAAC,CAAC,EAAE,MAAM,EAAE,CAAA;gBACd,uFAAuF;gBACvF,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,GAAG,CAAC,EAAE,CAAC,CAAA;gBAC5G,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,GAAG,UAAU,CAAA;gBAC1C,OAAO;oBACL,GAAG,CAAC,SAAS;wBACX,CAAC,CAAC;4BACE,SAAS,EAAE,IAAI;4BACf,IAAI,EAAE,YAAY,UAAU,2GAA2G;yBACxI;wBACH,CAAC,CAAC,EAAE,CAAC;oBACP,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,CAAC;wBACpD,EAAE,EAAE,GAAG,CAAC,EAAE;wBACV,IAAI,EAAE,GAAG,CAAC,IAAI;wBACd,IAAI,EAAE,GAAG,CAAC,IAAI;wBACd,KAAK,EAAE,GAAG,CAAC,KAAK;wBAChB,KAAK,EAAE,GAAG,CAAC,KAAK;wBAChB,SAAS,EAAE,GAAG,CAAC,SAAS;qBACzB,CAAC,CAAC;iBACJ,CAAA;YACH,CAAC;SACF;QACD;YACE,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,iBAAiB;YACvB;0FAC8E;YAC9E,KAAK,EAAE,CAAC,cAAc,CAAC;YACvB,WAAW,EACT,8EAA8E;gBAC9E,+GAA+G;gBAC/G,oHAAoH;gBACpH,mHAAmH;gBACnH,gGAAgG;gBAChG,iHAAiH;gBACjH,6DAA6D;YAC/D,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,GAAG,aAAa,EAAE,GAAG,SAAS,EAAE,EAAE;YAC1E,OAAO,EAAE,KAAK,EAAE,IAAS,EAAE,GAAQ,EAAE,EAAE;gBACrC,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;gBAC5C,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAA;gBAC9C,MAAM,GAAG,GAAG,MAAM,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,CAAA;gBACpE,IAAI,CAAC,GAAG;oBAAE,OAAO,mBAAmB,EAAE,CAAA;gBAEtC,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAA;gBAC7C,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;oBACpB,oDAAoD;oBACpD,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;gBACjF,CAAC;gBAED,sGAAsG;gBACtG,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAA;gBACjD,gHAAgH;gBAChH,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;gBACrE,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;gBACpC,OAAO;oBACL,EAAE,EAAE,GAAG,CAAC,EAAE;oBACV,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,KAAK,EAAE,GAAG,CAAC,KAAK;oBAChB,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;oBACpJ,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC;oBAClC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI;oBAC5C,GAAG,KAAK;iBACT,CAAA;YACH,CAAC;SACF;QACD;YACE,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,eAAe;YACrB,yBAAyB;YACzB,KAAK,EAAE,CAAC,qBAAqB,CAAC;YAC9B,WAAW,EACT,2FAA2F;gBAC3F,yFAAyF;gBACzF,mDAAmD;YACrD,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,GAAG,aAAa,EAAE,EAAE;YAC5D,OAAO,EAAE,KAAK,EAAE,IAAS,EAAE,GAAQ,EAAE,EAAE;gBACrC,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;gBAC5C,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAA;gBAC9C,MAAM,GAAG,GAAG,MAAM,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,CAAA;gBACpE,IAAI,CAAC,GAAG;oBAAE,OAAO,mBAAmB,EAAE,CAAA;gBAEtC,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAA;gBAC7C,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAA;gBACnC,+EAA+E;gBAC/E,OAAO,EAAE,GAAG,oBAAoB,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAA;YAC1K,CAAC;SACF;QACD;YACE,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,wBAAwB;YAC9B,sCAAsC;YACtC,KAAK,EAAE,CAAC,wBAAwB,CAAC;YACjC,WAAW,EACT,4GAA4G;gBAC5G,8GAA8G;gBAC9G,6GAA6G;YAC/G,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,MAAM,EAAE;wBACN,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,sHAAsH;qBACpI;oBACD,QAAQ,EAAE;wBACR,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,qHAAqH;qBACnI;oBACD,IAAI,EAAE;wBACJ,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,2CAA2C;qBACzD;oBACD,MAAM,EAAE;wBACN,IAAI,EAAE,SAAS;wBACf,WAAW,EAAE,6DAA6D;qBAC3E;oBACD,KAAK,EAAE;wBACL,IAAI,EAAE,OAAO;wBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBACzB,WAAW,EACT,oNAAoN;qBACvN;oBACD,QAAQ,EAAE;wBACR,IAAI,EAAE,OAAO;wBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBACzB,WAAW,EACT,2MAA2M;qBAC9M;iBACF;gBACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;aACrB;YACD,OAAO,EAAE,KAAK,EAAE,IAAS,EAAE,GAAoB,EAAE,EAAE;gBACjD,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;gBAC5C,MAAM,MAAM,GAAG,OAAO,IAAI,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;gBACzE,IAAI,CAAC,MAAM;oBAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAA;gBAE/E;;;;;;;kBAOE;gBACF,MAAM,IAAI,GAAG,GAAG,EAAE,IAAI,CAAA;gBACtB,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,KAAK,IAAI,IAAI,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAA;gBAC/D,IAAI,IAAa,CAAA;gBACjB,IAAI,QAA4B,CAAA;gBAChC,IAAI,KAA6C,CAAA;gBACjD,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,MAAM,IAAI,GAAG,OAAO,IAAI,EAAE,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;oBAC3E,MAAM,IAAI,GAAG,OAAO,IAAI,EAAE,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;oBAC3E,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;wBAC1B,MAAM,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;wBACpC,OAAO,aAAa,EAAE,CAAA;oBACxB,CAAC;oBACD,IAAI,CAAC,IAAI;wBAAE,OAAO,mBAAmB,EAAE,CAAA;oBACvC,MAAM,GAAG,GAAG,MAAM,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAA;oBAC3D,IAAI,CAAC,GAAG;wBAAE,OAAO,mBAAmB,EAAE,CAAA;oBACtC,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;oBACxC,IAAI,GAAG,OAAO,CAAC,MAAM,IAAI,SAAS,CAAA;oBAClC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;wBAAE,OAAO,aAAa,EAAE,CAAA;oBAC3C,IAAI,OAAO,IAAI,EAAE,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC;wBAAE,OAAO,aAAa,EAAE,CAAA;oBAClG,QAAQ,GAAG,IAAI,CAAA;oBACf,8EAA8E;oBAC9E,IAAI,OAAO,CAAC,KAAK;wBAAE,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;gBAChD,CAAC;gBAED;;;kBAGE;gBACF,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,WAAW,IAAI,EAAE,CAAC;qBACpC,MAAM,CAAC,CAAC,IAAoB,EAA+B,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC;qBACpF,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,SAA6B,EAAE,CAAC,CAAC,CAAA;gBAEpF,MAAM,EAAE,kBAAkB,EAAE,GAAG,OAAO,EAAE,CAAA;gBACxC,IAAI,MAAW,CAAA;gBACf,IAAI,CAAC;oBACH,MAAM,GAAG,MAAM,kBAAkB,CAAC;wBAChC,+FAA+F;wBAC/F,MAAM,EAAE,MAAM,IAAA,4BAAW,EAAC;4BACxB,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM;4BAC1B,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI;4BACtB,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS;4BAC9B,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI;yBAC1B,CAAC;wBACF,MAAM;wBACN,IAAI;wBACJ,IAAI,EAAE,OAAO,IAAI,EAAE,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS;wBACvF,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBACpC,GAAG,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBACxD,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,MAAM,IAAI,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC;4BAChF,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE;4BAClF,CAAC,CAAC,EAAE,CAAC;qBACR,CAAC,CAAA;gBACJ,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf;;;;uBAIG;oBACH,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAE,KAAa,EAAE,OAAO,CAAC,CAAC,CAAC,CAAE,KAAa,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;oBACpF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;wBAAE,MAAM,IAAI,KAAK,CAAC,CAAE,KAAe,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;oBAC1F,MAAM,KAAK,CAAA;gBACb,CAAC;gBAED;;;;kBAIE;gBACF,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,QAAQ,CAAA;gBAC3C,wHAAwH;gBACxH,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAA;gBACf,OAAO;oBACL,QAAQ,EAAE,IAAI;oBACd;;;;sBAIE;oBACF,GAAG,EAAE,IAAA,mBAAU,GAAE;oBACjB,IAAI,EAAE,YAAY;oBAClB,KAAK,EAAE,MAAM;wBACX,CAAC,CAAC,CAAC,CAAC,8BAA8B,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;wBAC1E,CAAC,CAAC,CAAC,CAAC,8BAA8B,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,eAAe,EAAE,CAAC;oBAC9E,MAAM,EAAE,CAAC,CAAC,wBAAwB,EAAE;wBAClC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM;wBAC1B,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,IAAI,GAAG;wBACjC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS;wBAChC,QAAQ,EAAE,MAAM,CAAC,QAAQ;wBACzB,YAAY,EAAE,qFAAqF;qBACpG,CAAC;oBACF,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE;oBAClC,MAAM;oBACN,QAAQ;oBACR,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO;oBAC1C,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ;oBAC5C,KAAK,EAAE,MAAM,CAAC,KAAK;oBACnB,KAAK,EAAE,MAAM,CAAC,KAAK;oBACnB,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;iBAC1B,CAAA;YACH,CAAC;SACF;KACY,CAAA;AACjB,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,4BAA4B;IAC1C,MAAM,SAAS,GAAiB;QAC9B,IAAI,EAAE,kBAAkB;QACxB,WAAW,EAAE,mHAAmH;QAChI,QAAQ,EAAE;YACR,0IAA0I;YAC1I,uJAAuJ;YACvJ,kNAAkN;YAClN,uKAAuK;YACvK,iGAAiG;YACjG,gPAAgP;YAChP,wMAAwM;YACxM,wWAAwW;YACxW,iMAAiM;YACjM,sHAAsH;YACtH,oKAAoK;YACpK,sFAAsF;SACvF,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,KAAK,EAAE,eAAe,EAAE;KACzB,CAAA;IAED,IAAA,qCAAoB,EAAC,SAAS,CAAC,CAAA;AACjC,CAAC","sourcesContent":["/*\n * figure ์ ์ ๋๊ตฌ๋ฅผ ์ด์์คํดํธ ๋๊ตฌ ๋ ์ง์คํธ๋ฆฌ์ ๋ฑ๋ก โ **๋ํ๋ฉด(๋ํฌ)์์ ์ ์์ ๋๊ธฐ ์ํจ.**\n *\n * ์ ํ์ํ๊ฐ: `proposeFigure` ๋ ํ ๋ฒ ์ํค๊ณ ํ ๋ฒ ๋ฐ๋๋ค. ๊ทธ๊ฒ์ผ๋ก ๋๋ ์ผ์ด ์์ง๋ง, ์ ์์\n * ๋๊ฐ ใ์ด๊ฑธ ์ด๋ ๊ฒ ๊ณ ์ณ ๋ด โ ๋ฌด๊ฒ๊ฐ ์ผ๋ง๋ ๋๋ โ ๋ฐํ์ ๋๋ใ์ฒ๋ผ ์ฌ๋ฌ ์ฐจ๋ก ์ค๊ฐ๋ค. ๊ทธ ๋ํ๋ฅผ\n * ํ๋ ค๋ฉด ์ด์์คํดํธ๊ฐ **์ง๊ธ ๋ฌด์์ด ์๋์ง ์ฝ์ ์ ์์ด์ผ** ํ๋ค. ์ฝ์ง ๋ชปํ๋ฉด ๋งค๋ฒ ์ฌ๋์ด ์ ๋ณธ์\n * ๋ถ์ฌ ๋ฃ์ด์ผ ํ๊ณ , ๊ทธ๋ฌ๋ฉด ๋ํ๊ฐ ์๋๋ค.\n *\n * ๋ฅ๋ ฅ์ ๋ณต์ ํ์ง ์๋๋ค. figure-service ๊ฐ ์ด๋ฏธ ๊ฐ์ง ์ง์
์ (`inspectSource` ยท `proposeFigureSteps` ยท\n * ์กฐํ)์ ๋ ์ง์คํธ๋ฆฌ์ ํฌ์ํ๋ค.\n *\n * โโ ์ ๋ถ ์กฐํยท์ ์ ์ ์ฉ์ด๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ๋ณธ์ ๊ณ ์น๋ ๋๊ตฌ๋ฅผ ๋ฃ์ง ์๋๋ค. ํ์์ ์ค๊ณ๊ฐ ๊ทธ๋ ๊ฒ ์ ํด์ ธ ์๋ค โ ์ด์์คํดํธ๋ **ํ๋ณด**๋ฅผ\n * ๋ด๊ณ , ๋ฐ์์ง ๋ฒ๋ฆด์ง๋ ์ ์์๊ฐ ์ ํ๋ค(`figure-propose-steps.ts`, ADR-0094). ๋๋๋ฆด ์ ์๋ ์กฐ์์ด ๋ํ๋ฉด์ผ๋ก\n * ์์ง ์์ผ๋ฏ๋ก ์ ๋ถ `kind: 'read'` ๋ค.\n *\n * ์ ์ฅ์ ์ ์๋ฉด์ด `updateFigure` ๋ก ํ๋ค. ๊ทธ mutation ์ `figure:mutation` ์ด ์งํค๊ณ , ๋ํ๋\n * `ai-assistant:mutation` ์ด ์งํจ๋ค โ ์๋ก ๋ค๋ฅธ ์ง๋ฌธ์ด๋ผ ์๋ก ๋ค๋ฅธ ๊ถํ์ด ์งํจ๋ค. figure ๊ฐ board\n * ์ ๊ถํ์ ๋น๋ฆฌ์ง ์๋๋ค.\n *\n * โโ No privilege here. The gate reads what the door declares โโโโโโโโโโโโโโโโโโโโโ\n * Until 2026-09-18 each tool carried `privilege: { category: 'figure', ... }`. It matched the door's\n * directive then, and would drift the day the door changed its declaration โ and the looser copy wins.\n * Now the gate reads the declaration of each door in `doors` from AUTH's table (ADR-0071 decision 2,\n * addendum). What stays here is **the doors it reaches**.\n *\n * โโ ๊ท์จ์ ๋๊ตฌ์ ํจ๊ป ๋ณด๋ธ๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๋๊ตฌ ๋ชฉ๋ก๋ง์ผ๋ก๋ ใ์ธ์ ๋ฐ๋์ ๋ถ๋ฌ์ผ ํ๋์งใ๋ฅผ ๋ชจ๋ฅธ๋ค. twin ์ด ๊ทธ ๊ณต๋ฐฑ์์ ์ฌ๊ณ ๋ฅผ ๋๋ค โ\n * ์กฐ์น ์์ฒญ์ ๋๊ตฌ๋ฅผ ๋ถ๋ฅด์ง ์๊ณ ใ์ ์ํด ๋์์ต๋๋คใ๋ผ๊ณ ๋ง ๋ตํด, ์ฌ์ฉ์์๊ฒ **์๋ ๋ฒํผ์ ๋๋ฅด๋ผ๊ณ \n * ์๋ดํ๋ค.** figure ๋ ๋๊ฐ์ ์๋ฆฌ๊ฐ ์๋ค: ํ๋ณด ํ๋ฉด(ใ์ง๊ธ / ํ๋ณดใ ๋ ์นธ)์ **๋๊ตฌ ํธ์ถ ๊ฒฐ๊ณผ์์๋ง**\n * ๋ง๋ค์ด์ง๋ค. ๋ฌธ์ฅ์ผ๋ก๋ ์๋ฌด ์ผ๋ ์ผ์ด๋์ง ์๋๋ค.\n *\n * โโ LLM ์ด ๋๊ธด id ๋ฅผ ๋ฏฟ์ง ์๋๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ฌ๋์ด ๋ชฉ๋ก์์ ๊ณ ๋ฅด๋ ๊ธธ์์๋ ๋๋ฌ๋์ง ์์ง๋ง, ๋ชจ๋ธ์ ๋ํ ๋ด์ฉ์ ์ด๋๋ ค ์์์ id ๋ฅผ ๋๊ธธ ์\n * ์๋ค. ๊ทธ๋์ ํธ์ถ์ ๋๋ฉ์ธ ์์์ ๋จผ์ ํ์ธํ๋ค.\n */\nimport { randomUUID } from 'crypto'\nimport { ILike } from 'typeorm'\nimport {\n aiClientFor,\n registerToolCategory,\n type AIImageMediaType,\n type ToolAttachment,\n type ToolCallContext,\n type ToolCategory,\n type ToolImageAttachment,\n type ToolSpec\n} from '@things-factory/ai-client-base'\n\nimport { FIGURE_CONTEXT_BUDGET, figureViewOf, type FigureReadRequest } from './figure-context.js'\n\n/** How many figures a list without search names. */\nconst LIST_LIMIT = 200\n\n/*\n ์๋ฒ ์์กด์ฑ์ lazy require ๋ค. ๋ฑ๋ก์ ๋ถํ
์ด๋ฐ์ ํ๊ฐ๋๊ณ ๊ทธ๋ typeorm DataSource ๊ฐ ์ค๋น๋์ง\n ์์์ ์ ์๋ค(board-import ยท twin-ai ์ ๊ฐ์ ์ ์ฑ
).\n*/\nlet _deps: any | undefined\n\nfunction getDeps(): any {\n if (!_deps) {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const shell = require('@things-factory/shell')\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const model = require('@hatiolab/figure-model')\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const entity = require('./figure.js')\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const format = require('./figure-format.js')\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const proposer = require('./figure-propose-steps.js')\n _deps = {\n getRepository: shell.getRepository,\n Figure: entity.Figure,\n /* The same doors a save and a release go through. The tool reads; it never saves. */\n inspectSource: format.inspectSource,\n parseSource: format.parseSource,\n figureCostOf: model.figureCostOf,\n figureScoreOf: model.figureScoreOf,\n proposeFigureSteps: proposer.proposeFigureSteps,\n isPlaceholderType: model.isPlaceholderType\n }\n }\n return _deps\n}\n\n/** ์ํยท๊ฒ์ฆ ํ๋ค์ค ์ ์ฉ ์ฃผ์
์์. ์ด์ ๊ฒฝ๋ก์์ ํธ์ถ ๊ธ์ง. */\nexport function __setFigureToolDepsForTest(deps: any): void {\n _deps = deps\n}\n\nfunction requireDomainId(state: any): string {\n const id = state?.domain?.id\n if (!id) {\n // ๋๋ฉ์ธ์ ๋ชจ๋ฅด๋ฉด ๋ฌด์์ ์ฝ์ด๋ ๋จ์ ๊ฒ์ผ ์ ์๋ค. ์กฐ์ฉํ ๋๊ธฐ์ง ์๋๋ค.\n throw new Error('domain context is missing โ the figure tools cannot resolve tenant scope')\n }\n return id\n}\n\n/**\n * ์ด ํผ๊ท์ด๊ฐ ํธ์ถ์ ๋๋ฉ์ธ ๊ฒ์ธ๊ฐ.\n *\n * ๋ชจ๋ธ์ด ๋๊ธด id ๋ฅผ ๊ทธ๋๋ก ์ฐ์ง ์๋๋ค. ์์ผ๋ฉด ๋ชป ์ฐพ์๋ค๊ณ ๋งํ๋ค โ ใ๊ถํ์ด ์๋คใ์ ๊ตฌ๋ณํด\n * ์๋ ค ์ค ๊ฒ์ด ์๋ค(๋ค๋ฅธ ํ
๋ํธ์ ๊ทธ id ๊ฐ ์๋ค๋ ์ฌ์ค ์์ฒด๊ฐ ์๋ ค ์ค ๊ฒ์ด ์๋๋ค).\n */\nasync function figureInDomain(figureId: string, domainId: string): Promise<any> {\n const { getRepository, Figure } = getDeps()\n const found = await getRepository(Figure).findOne({\n where: { id: figureId, domain: { id: domainId } }\n })\n if (!found) {\n throw new Error(`figure not found in this tenant: ${figureId}`)\n }\n return found\n}\n\n/** The form of a creation id: the row id a new figure's first save inserts it under (`figure-mutation.ts`). */\nconst CREATION_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\n\n/**\n * The figure a tool is about: by id, or by its type name, in the caller's domain. None named: none.\n *\n * A figure not saved yet is a subject too (ADR-0061 decision 3): the modeller names it by its creation id, which its first\n * save inserts the row under (ADR-0072 decision 6), so before that save there is no row. It is the figure open on that\n * screen and nothing else: the id the screen has open, with the draft the screen sent. What is read is that draft, put\n * through the save's door like any draft (`sourceForTool`); nothing the server holds is read for it.\n */\nasync function resolveFigureTarget(figureId: string | undefined, domainId: string, host: any): Promise<any> {\n if (!figureId) return undefined\n const { getRepository, Figure } = getDeps()\n const found =\n (await getRepository(Figure).findOne({ where: { id: figureId, domain: { id: domainId } } })) ??\n (await getRepository(Figure).findOne({ where: { type: figureId, domain: { id: domainId } } }))\n if (found) return found\n const draft = host?.draftSource\n if (CREATION_ID.test(figureId) && host?.figureId === figureId && draft && typeof draft === 'object') {\n return { id: figureId, name: typeof draft.name === 'string' ? draft.name : undefined, source: null }\n }\n throw new Error(`figure not found in this tenant: ${figureId}`)\n}\n\n/**\n * The source a tool reads: the draft on screen when the modeller has this figure open, else the stored one.\n *\n * The host context is the browser's, so it is no ground for access: the row is found in the domain first, and the\n * draft is put through the same door a save goes through before anything reads it.\n */\nconst isFigure = (source: any) => source?.version === 'figure-asset-1'\n\n/**\n * A revision is applied by the modeller on the version the model saw (ADR-0094), so only the figure open there can be\n * revised. Said as what is true, with what the assistant can do instead.\n */\nfunction figureNotOpen() {\n return {\n error: 'FIGURE_NOT_OPEN',\n message: 'A revision can be proposed only for the figure open in the modeller.',\n nextStep:\n 'Tell the person to open the figure in the modeller and ask again there. A new figure needs no open one: call proposeFigureCandidate with create: true.'\n }\n}\n\nfunction sourceForTool(row: any, host: any): { source: any; draft: boolean } {\n const draft = host?.figureId === row.id ? host?.draftSource : undefined\n if (!draft) return { source: row.source ? JSON.parse(row.source) : null, draft: false }\n\n if (typeof draft !== 'object' || Array.isArray(draft)) throw new Error('the unsaved draft is not a figure asset')\n const serialized = JSON.stringify(draft)\n /* Validity is the save door's (the kernel's 1 MiB); how much the model is shown is `figure-context`'s. */\n try {\n getDeps().parseSource(serialized)\n } catch (e: any) {\n const findings = Array.isArray(e?.findings) ? e.findings.map((one: any) => one.message).join(' ยท ') : String(e?.message ?? e)\n throw new Error(`the unsaved draft is invalid: ${findings}`)\n }\n return { source: draft, draft: true }\n}\n\n/** The finite numbers of an untrusted record, by name; none: undefined. */\nfunction numbersOf(record: any): Record<string, number> | undefined {\n if (!record || typeof record !== 'object' || Array.isArray(record)) return undefined\n const kept = Object.entries(record).filter((entry): entry is [string, number] => typeof entry[1] === 'number' && Number.isFinite(entry[1]))\n return kept.length ? Object.fromEntries(kept) : undefined\n}\n\n/**\n * What the person has in view on the open draft: the part selected and what the preview is trying (ADR-0097 ยง5.6\n * item 5). The model hears it only here, through a read (ADR-0061 decision 3). Told only when it was seen on the version\n * being read -- a selection from another version may name a part that is gone -- and a part only when the draft has it.\n */\nfunction focusOf(host: any, source: any): { selection?: { part: string }; trying?: { clips?: Record<string, number>; controls?: Record<string, number> } } {\n const onThisVersion = (seen: any) => typeof host?.context === 'string' && seen?.context === host.context && seen?.revision === host.revision\n const focus: ReturnType<typeof focusOf> = {}\n\n const part = host?.selection?.part\n const nodes = source?.document?.model?.nodes\n if (typeof part === 'string' && onThisVersion(host.selection) && Array.isArray(nodes) && nodes.some((node: any) => node?.id === part)) {\n focus.selection = { part }\n }\n\n if (onThisVersion(host?.trying)) {\n const clips = numbersOf(host.trying.clips)\n const controls = numbersOf(host.trying.controls)\n if (clips || controls) focus.trying = { ...(clips ? { clips } : {}), ...(controls ? { controls } : {}) }\n }\n return focus\n}\n\n/**\n * ๋ฌด์์ ๊ณ ์น๋ผ๋ ๊ฒ์ธ์ง ๋ํ๋ฉด ๋ฌธ๋งฅ์์ ํด์ํ๋ค.\n *\n * ๋ชจ๋ธ์ด ๋์์ ์ ์คฌ์ผ๋ฉด **์ ์๋ฉด์ด ์ง๊ธ ์ด๊ณ ์๋ ํผ๊ท์ด**์ด๋ค. ์ฌ์ฉ์์๊ฒ ์๋ณ์๋ฅผ ๋๋ฌป์ง\n * ์๋๋ค โ ํ๋ฉด์ ๊ทธ ํผ๊ท์ด๊ฐ ๋ ์๋๋ฐ ใ์ด๋ ํผ๊ท์ด์
๋๊นใ๋ฅผ ๋ฌป๋ ๊ฒ์ ๋ฌธ๋งฅ์ ์ ์ฝ์ ๊ฒ์ด๋ค.\n */\nfunction figureIdFrom(args: any, host: any): string | undefined {\n const said = typeof args?.figureId === 'string' ? args.figureId.trim() : ''\n if (said) return said\n\n const open = typeof host?.figureId === 'string' ? host.figureId.trim() : ''\n if (open) return open\n\n return undefined\n}\n\nfunction missingFigureTarget() {\n return {\n error: 'FIGURE_TARGET_REQUIRED',\n message: 'No figure is open on this screen.',\n nextStep: 'For an existing figure, call listFigures and match the userโs requested name or type; ask which figure only if ambiguous. For a new figure, call proposeFigureCandidate with create: true and the userโs prompt. Do not invent an id or repeat this call without a target.'\n }\n}\n\nconst FIGURE_ID_ARG = {\n figureId: {\n type: 'string',\n description: 'The figure to read. Omit to read the one open in the modeller โ with its unsaved changes, and also when it is a new figure not saved yet; the server fills it in, and you cannot see which it is. A figure not saved yet is readable only while it is open in the modeller. On the catalog nothing is open, so resolve the figure the person asked for with listFigures first.'\n }\n} as const\n\nconst PARTS_ARG = {\n parts: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Only for a figure too large to read whole (the answer then has `outline` and no `source`): the ids of the parts to read in full, from `outline.parts`. Omit to read the part selected.'\n },\n sections: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Only for a figure too large to read whole: JSON Pointers of sections to read, such as one named in `outline.omitted` or its `entries` (for example /document/capabilities/bindings/0).'\n }\n} as const\n\n/**\n * A figure too large to show whole, as the model reads it (ADR-0061 2026-10-16 decision 4): its outline and the parts\n * asked for. The full source stays here; what is measured is measured on it.\n */\nfunction partialRead(source: any, request: FigureReadRequest) {\n const view = figureViewOf(source, request)\n if (view.whole) return { source }\n return {\n outline: view.outline,\n partSources: view.parts,\n ...(Object.keys(view.sections ?? {}).length ? { sectionSources: view.sections } : {}),\n ...(view.notRead ? { notRead: view.notRead } : {}),\n note:\n `This figure is too large to read whole (${view.outline!.chars} characters; ${FIGURE_CONTEXT_BUDGET} are read at once), so this is its outline, the parts in partSources and the sections in sectionSources. ` +\n 'Read what a change touches with parts and sections, then pass the same to proposeFigureCandidate: only parts read in full may be changed, and nothing in a section in outline.omitted that was not read.'\n }\n}\n\n/** The parts the model named, as strings; anything else is dropped. */\nconst stringsOf = (list: unknown): string[] =>\n Array.isArray(list) ? list.filter((one: unknown): one is string => typeof one === 'string' && !!one.trim()).map((one: string) => one.trim()) : []\n\n/** An inspection whose findings would crowd the model's context, cut to the budget with how many there were. */\nfunction findingsWithinBudget(inspection: any) {\n const findings = Array.isArray(inspection?.findings) ? inspection.findings : []\n if (JSON.stringify(inspection).length <= FIGURE_CONTEXT_BUDGET) return inspection\n const head = JSON.stringify({ ...inspection, findings: [], truncated: { shown: findings.length, total: findings.length } }).length\n let room = FIGURE_CONTEXT_BUDGET - head\n const shown: any[] = []\n for (const finding of findings) {\n const cost = JSON.stringify(finding).length + 1\n if (cost > room) break\n shown.push(finding)\n room -= cost\n }\n return { ...inspection, findings: shown, truncated: { shown: shown.length, total: findings.length } }\n}\n\n/**\n * ๋๊ตฌ ๋ท.\n *\n * ๋ชฉ๋ก ยท ์ ๋ณธ ยท ๋ฐํ ํ์ ยท ํ๋ณด. ์ ์ ๋ํ์์ ์ค์ ๋ก ๋ฌป๋ ๊ฒ์ด ๊ทธ ๋ท์ด๋ค โ ใ๋ฌด์์ด ์๋ใ\n * ใ์ง๊ธ ์ด๋ป๊ฒ ์๊ฒผ๋ใ ใ๋ฐํ์ด ์ ์ ๋๋ใ ใ์ด๋ ๊ฒ ๊ณ ์ณ ๋ดใ.\n */\nfunction figureToolSpecs(): ToolSpec[] {\n return [\n {\n kind: 'read',\n name: 'listFigures',\n /* ์ด ๋๋ฉ์ธ์ ํผ๊ท์ด ๋ชฉ๋ก โ ์ ์ฅ์๋ฅผ ์ง์ ์ฝ์ง๋ง ๊ฐ์ ์ผ์ ํ๋ ๋ฌธ์ ์ด๊ฒ์ด๋ค. */\n doors: ['Query.figures'],\n description:\n 'Lists the figures in this tenant with their type names, states and part counts. ' +\n 'Call it before naming a type โ type names are stored identifiers and must not be invented. ' +\n `Without search it lists the ${LIST_LIMIT} most recently changed; when there are more it says truncated, and a figure the person names may be among the rest - list again with search.`,\n schema: {\n type: 'object',\n properties: {\n search: {\n type: 'string',\n description: 'Part of a figure name or type name, in any case. Omit to list the most recently changed.'\n }\n }\n },\n builder: async (args: any, ctx: any) => {\n const domainId = requireDomainId(ctx?.state)\n const { getRepository, Figure } = getDeps()\n const search = typeof args?.search === 'string' ? args.search.trim() : ''\n const domain = { id: domainId }\n /* `_` and `%` in the words are LIKE wildcards: they can only widen what is found, never hide a match. */\n const where = search\n ? [\n { domain, name: ILike(`%${search}%`) },\n { domain, type: ILike(`%${search}%`) }\n ]\n : { domain }\n /* One more than is shown, to know whether there is more without counting the table. */\n const rows = await getRepository(Figure).find({ where, order: { updatedAt: 'DESC' }, take: LIST_LIMIT + 1 })\n const truncated = rows.length > LIST_LIMIT\n return {\n ...(truncated\n ? {\n truncated: true,\n note: `Only the ${LIST_LIMIT} most recently changed are listed. A figure not here may still exist: call listFigures again with search.`\n }\n : {}),\n figures: rows.slice(0, LIST_LIMIT).map((row: any) => ({\n id: row.id,\n type: row.type,\n name: row.name,\n state: row.state,\n score: row.score,\n triangles: row.triangles\n }))\n }\n }\n },\n {\n kind: 'read',\n name: 'getFigureSource',\n /* ์ ์ฅ๋ ํผ๊ท์ด์ ์๋ณธ. **์ ์ฅ ์ ์ด์**์ ๋ฌผ์ผ๋ฉด ์ ์ฅ์์ ๊ฐ ๊ฒ์ด ์์ด ํ๋ฉด์ด ๋ณด๋ธ ๊ฒ์ ๊ทธ๋๋ก ๋๋ ค์ค๋ค โ\n * ๊ทธ ๊ฐ๋์๋ ๋ฟ๋ ๋ฌธ์ด ์์ง๋ง `doors: []` ๋ก ์ ์ง ์๋๋ค. ๊ทธ๋ฌ๋ฉด ์ ์ฅ๋ ํผ๊ท์ด๋ฅผ ์ฝ๋ ๊ถํ ๊ฒ์ฌ๊ฐ ์ ์ธ์์ ์ฌ๋ผ์ง๋ค. */\n doors: ['Query.figure'],\n description:\n 'Returns the source (the figure asset) of one figure, with its measured cost ' +\n '(triangles, part groups, and how many of it hold 60fps on one screen). Call it before proposing a revision โ ' +\n 'revising without reading it means proposing against a guess. On the figure open in the modeller it also says what ' +\n 'the person has in view: `selection.part` is the part selected - \"this part\" or \"the selected one\" means it - and ' +\n '`trying` the clip and control values the preview is trying, which are not part of the figure. ' +\n 'A figure too large to read whole comes as `outline` (every part by name, shape and what it is fastened to) and ' +\n '`partSources` (the parts read in full) instead of `source`.',\n schema: { type: 'object', properties: { ...FIGURE_ID_ARG, ...PARTS_ARG } },\n builder: async (args: any, ctx: any) => {\n const domainId = requireDomainId(ctx?.state)\n const figureId = figureIdFrom(args, ctx?.host)\n const row = await resolveFigureTarget(figureId, domainId, ctx?.host)\n if (!row) return missingFigureTarget()\n\n const current = sourceForTool(row, ctx?.host)\n if (!current.source) {\n // ์ ์ฅ๋ ์ ๋ณธ์ด ์๋ ์ํ๊ฐ ์ค์ ๋ก ์๋ค(์๋ก ๋ง๋ค๊ณ ์ ์ฅ ์ ํ ๊ฒ). ์ง์ด๋ด์ง ์๋๋ค.\n return { id: row.id, type: row.type, name: row.name, source: null, cost: null }\n }\n\n /* Measured as the catalogue measures it: triangles, draw groups, and its grade against one screen. */\n const { figureCostOf, figureScoreOf } = getDeps()\n /* What is in view belongs to the draft on screen; the stored source may be another figure than the one open. */\n const focus = current.draft ? focusOf(ctx?.host, current.source) : {}\n const asked = stringsOf(args?.parts)\n return {\n id: row.id,\n type: row.type,\n name: row.name,\n state: row.state,\n ...partialRead(current.source, { parts: asked.length ? asked : focus.selection ? [focus.selection.part] : [], sections: stringsOf(args?.sections) }),\n draft: current.draft,\n cost: figureCostOf(current.source),\n score: figureScoreOf(current.source) ?? null,\n ...focus\n }\n }\n },\n {\n kind: 'read',\n name: 'inspectFigure',\n /* ๊ฒ์ฌ ๊ฒฐ๊ณผ โ ๊ฐ์ ์ผ์ ํ๋ ๋ฌธ. */\n doors: ['Query.inspectFigure'],\n description:\n 'Says whether a figure may be released and, when it may not, what is wrong โ each finding ' +\n 'carries why it is a problem and what to change. Call it when asked about releasing, or ' +\n 'when asked to fix a figure that will not release.',\n schema: { type: 'object', properties: { ...FIGURE_ID_ARG } },\n builder: async (args: any, ctx: any) => {\n const domainId = requireDomainId(ctx?.state)\n const figureId = figureIdFrom(args, ctx?.host)\n const row = await resolveFigureTarget(figureId, domainId, ctx?.host)\n if (!row) return missingFigureTarget()\n\n const current = sourceForTool(row, ctx?.host)\n const { inspectSource } = getDeps()\n /* Inspected whole, here; only what the model is told is held to its budget. */\n return { ...findingsWithinBudget(inspectSource(current.source ? JSON.stringify(current.source) : null, null, undefined, row.type, row.category)), draft: current.draft }\n }\n },\n {\n kind: 'read',\n name: 'proposeFigureCandidate',\n /* ํ๋ณด ์์ฑ โ ์ ์ฅ์ ํ์ง ์์ง๋ง ๊ฐ์ ๋ฌธ์ ๊ถํ์ ์ด๋ค. */\n doors: ['Mutation.proposeFigure'],\n description:\n 'Asks for a proposal: the modeller commands that make a new figure or revise the one open in the modeller. ' +\n 'Returns the commands with the score and cost of the figure they make. NOTHING IS SAVED โ the author applies ' +\n 'the proposal in the modeller as one step, or leaves it. This is the only way a proposal reaches the screen.',\n schema: {\n type: 'object',\n properties: {\n prompt: {\n type: 'string',\n description: 'What to make or change, in the words the author used, with the sizes as they said them: do not turn sizes into axes.'\n },\n figureId: {\n type: 'string',\n description: 'Revise this figure; it must be the one open in the modeller. Omit to revise the open one; pass null to create anew.'\n },\n name: {\n type: 'string',\n description: 'The name a person reads for a new figure.'\n },\n create: {\n type: 'boolean',\n description: 'True to create rather than revise, even with a figure open.'\n },\n parts: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Only for a figure too large to read whole: the parts this change touches, read first with getFigureSource parts. Only these and the part selected may be changed; new parts may be added and fastened to any part.'\n },\n sections: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Only for a figure too large to read whole: JSON Pointers of the sections in outline.omitted this change touches, read first with getFigureSource sections. Nothing else in those sections may be changed.'\n }\n },\n required: ['prompt']\n },\n builder: async (args: any, ctx: ToolCallContext) => {\n const domainId = requireDomainId(ctx?.state)\n const prompt = typeof args?.prompt === 'string' ? args.prompt.trim() : ''\n if (!prompt) throw new Error('prompt is required: there is nothing to ask for')\n\n /*\n ๊ณ ์น๋ ๊ฒ์ธ์ง ๋ง๋๋ ๊ฒ์ธ์ง๋ฅผ **๋ฌธ๋งฅ์์ ์ ํ๋ค.** ์ด๋ฆฐ ํผ๊ท์ด๊ฐ ์์ผ๋ฉด ๊ณ ์น๋ ๊ฒ์ด ๊ธฐ๋ณธ์ด๊ณ ,\n ๋ชจ๋ธ์ด `create` ๋ฅผ ์ผ๋ฉด ๋ง๋๋ ๊ฒ์ด๋ค. ์ด๊ฒ์ ๋ชจ๋ธ์ ์ง์์ ๋งก๊ธฐ๋ฉด ์ด๋ ค ์๋ ํผ๊ท์ด๋ฅผ ๋ฎ์ด์ฐ๋\n ํ๋ณด๊ฐ ์จ๋ค.\n\n ๊ณ ์น๋ ์ ์์ ๋ชจ๋ธ๋ฌ๊ฐ **์์ฒญ ๋น์์ ํ(context ยท revision)** ์์ ํ ๋จ๊ณ๋ก ์ ์ฉํ๋ค(ADR-0094).\n ๊ทธ๋์ ๊ณ ์น ์ ์๋ ๊ฒ์ ๋ชจ๋ธ๋ฌ์ ์ด๋ฆฐ ํผ๊ท์ด๋ฟ์ด๊ณ , ๊ทธ ํ์ ๋ฌธ๋งฅ์ด ํจ๊ป ์ค์ด ์์ผ ํ๋ค.\n */\n const host = ctx?.host\n const create = args?.create === true || args?.figureId === null\n let base: unknown\n let figureId: string | undefined\n let focus: ReturnType<typeof focusOf> | undefined\n if (!create) {\n const said = typeof args?.figureId === 'string' ? args.figureId.trim() : ''\n const open = typeof host?.figureId === 'string' ? host.figureId.trim() : ''\n if (said && said !== open) {\n await figureInDomain(said, domainId)\n return figureNotOpen()\n }\n if (!open) return missingFigureTarget()\n const row = await resolveFigureTarget(open, domainId, host)\n if (!row) return missingFigureTarget()\n const current = sourceForTool(row, host)\n base = current.source ?? undefined\n if (!isFigure(base)) return figureNotOpen()\n if (typeof host?.context !== 'string' || !Number.isInteger(host?.revision)) return figureNotOpen()\n figureId = open\n /* \"Make this one bigger\": the part selected is what the request points at. */\n if (current.draft) focus = focusOf(host, base)\n }\n\n /*\n The pictures the person sent with this turn, as the server checked them (ADR-0061, 2026-10-16 decision 2) --\n every one, in the order attached. Never from the host context: the client fills it.\n */\n const images = (ctx?.attachments ?? [])\n .filter((file: ToolAttachment): file is ToolImageAttachment => file.kind === 'image')\n .map(file => ({ data: file.data, mediaType: file.mediaType as AIImageMediaType }))\n\n const { proposeFigureSteps } = getDeps()\n let result: any\n try {\n result = await proposeFigureSteps({\n /* The agent of this conversation's turn - the one the person picked, or the domain default. */\n client: await aiClientFor({\n domain: ctx?.state?.domain,\n user: ctx?.state?.user,\n agentId: ctx?.state?.aiAgentId,\n modeKind: ctx?.mode?.kind\n }),\n prompt,\n base,\n name: typeof args?.name === 'string' && args.name.trim() ? args.name.trim() : undefined,\n ...(images.length ? { images } : {}),\n ...(focus && Object.keys(focus).length ? { focus } : {}),\n ...(!create && (stringsOf(args?.parts).length || stringsOf(args?.sections).length)\n ? { read: { parts: stringsOf(args?.parts), sections: stringsOf(args?.sections) } }\n : {})\n })\n } catch (error) {\n /*\n * ์ธ ๋ฒ ๊ฑฐ์ ๋ ๋์ ์ฌ์ ๋ฅผ ProposeFigureFailure.reasons ์๋ง ๋๋ฉด agentic-loop ์ ใ๋ง๋ค์ง ๋ชปํ์ต๋๋คใ๋ง\n * ๋ฐ์ ํ๋ฉด์๋ ใ์๋ต์ด ๋น์ด์์ต๋๋คใ๊ฐ ๋๋ค. ๋ค์ ์๋ํ ์ ์๋ ๋ง๋ก ๊ฒฝ๊ณ๋ฅผ ๋๊ธด๋ค.\n * ๋ค๋ฅธ ์์ธ(๊ถํยทํต์ )๋ ์๋ฌธ์ ๋ณด์กดํ๋ค.\n */\n const reasons = Array.isArray((error as any)?.reasons) ? (error as any).reasons : []\n if (reasons.length > 0) throw new Error([(error as Error).message, ...reasons].join('\\n'))\n throw error\n }\n\n /*\n **`proposed: true` ๊ฐ ์นด๋๋ฅผ ๋ง๋ ๋ค.** ์ด ํ์๊ฐ ์์ผ๋ฉด ์ ์์ ๋๊ตฌ ์ถ์ ์์ ๋ฌปํ๊ณ ํ๋ฉด์๋\n ์๋ฌด๊ฒ๋ ์๊ธฐ์ง ์๋๋ค. ์นด๋์ ์คํ ๋จ์ถ๊ฐ figure-ui ์ ์ฒ๋ฆฌ๊ธฐ์ ๋๊ธฐ๊ณ , ์ฒ๋ฆฌ๊ธฐ๊ฐ ๋ชจ๋ธ๋ฌ์ ๋ช
๋ น\n ๋ชฉ๋ก์ ํ ๋จ๊ณ๋ก ์ ์ฉํ๋ค. `args` ๋ ๊ฐ์ ์ ์์ ๋ ๋ฒ ์ธ์ง ์๊ธฐ ์ํ ์ด์ ์ ์ผ๋ถ๋ค.\n */\n const name = result.source.name || 'Figure'\n /* The card is read by a person, so the server writes it in the request's language (ADR-0061, 2026-10-16 decision 1). */\n const t = ctx.t\n return {\n proposed: true,\n /*\n The proposal's own name, given once here (ADR-0097 ยง5.6 item 5; AI lane, 09-27): the dock keys its card by\n it, a new figure made from it is created under it (the row id), and a save records it -- so what became of\n it can be asked after a reload, and the same proposal never makes two figures.\n */\n key: randomUUID(),\n icon: 'view_in_ar',\n label: create\n ? t('figure.proposal.label-create', { name, defaultValue: 'Make {name}' })\n : t('figure.proposal.label-revise', { name, defaultValue: 'Revise {name}' }),\n reason: t('figure.proposal.reason', {\n steps: result.steps.length,\n grade: result.score?.grade ?? '-',\n triangles: result.cost.triangles,\n attempts: result.attempts,\n defaultValue: '{steps} commands ยท grade {grade} ยท {triangles} triangles ยท made in {attempts} tries'\n }),\n args: { prompt, figureId, create },\n create,\n figureId,\n context: create ? undefined : host.context,\n revision: create ? undefined : host.revision,\n steps: result.steps,\n score: result.score,\n cost: result.cost,\n attempts: result.attempts\n }\n }\n }\n ] as ToolSpec[]\n}\n\n/**\n * ๋ฑ๋ก โ ๋ถํ
์ 1ํ.\n *\n * ๋ฒ์ฃผ๊ฐ ํ๋๋ค. twin ์ ๊ด์ฐฐ๊ณผ ์์ฑ์ ๋๋ก ๊ฐ๋๋๋ฐ(์ด์ ํ์์ ์์ฑ ๋๊ตฌ๊ฐ ๋ค๋ ค ์์ผ๋ฉด ๋ํ์\n * ์ฑ๊ฒฉ์ด ํ๋ ค์ง๋ค), figure ์ ๋ํ๋ฉด์ ์ ์๋ฉด ํ๋๋ฟ์ด๊ณ ๊ทธ ์๋ฆฌ์์ ์ฝ๊ธฐ์ ํ๋ณด ์์ฒญ์ด ํจ๊ป ํ์ํ๋ค.\n * ๋ํ๋ฉด์ด ๋๋ฉด ๊ทธ๋ ๊ฐ๋ฅธ๋ค.\n */\nexport function registerFigureToolCategories(): void {\n const authoring: ToolCategory = {\n name: 'figure-authoring',\n description: 'Reads the source, cost and release verdict of the figure being authored, and proposes changes (nothing is saved).',\n guidance: [\n '- **For a request to make or change a figure, always call `proposeFigureCandidate`.** A proposal exists only as the result of that call.',\n ' Writing \"I made a proposal\" or \"press apply\" without the call is **false**: no card appears, and the person looks for a button that does not exist.',\n ' A proposal is a list of modeller commands. The modeller applies it as one step only when the person runs it from the dock card, and one undo takes it all back. Do not say the figure has changed before that.',\n ' A revision can be proposed only for the figure open in the modeller. Say what the result\\'s `steps` do as they are; do not invent changes the commands do not make.',\n '- Never save the source yourself. Propose; the author decides on the screen whether to take it.',\n '- In the prompt to `proposeFigureCandidate`, pass the person\\'s words as they are: their sizes, counts and names. Do not turn them into axes; the writer knows the figure\\'s axes. When you name an axis to the person, the figure\\'s Y is up.',\n '- **For a request to change a figure, call `getFigureSource` first.** Revising without reading proposes against a guess, and a renamed part breaks the bindings of the boards it is already placed on.',\n '- On the catalog nothing is open. To read an existing figure, find the id of the name or type the person said with `listFigures`; ask which figure only when it is ambiguous. To revise an existing figure, tell the person to open it in the modeller and ask there. For a new figure, do not read existing sources: call `proposeFigureCandidate` with create: true.',\n '- Do not invent type names; check them with `listFigures`. **A type name is a stored identifier**, and boards find the figure by it. A new figure\\'s type is set by a person at its first save.',\n '- When asked why a figure will not release, call `inspectFigure`. Do not say it can be released without its verdict.',\n ' Each finding carries **why it is a problem and what to change**. Pass it on as it is; a summary makes the author look again for which axis of which part to fix.',\n '- For weight or triangle counts, use `cost` from `getFigureSource`. Do not estimate.'\n ].join('\\n'),\n specs: figureToolSpecs()\n }\n\n registerToolCategory(authoring)\n}\n"]}
|