@specset/cli 0.6.0 → 2.0.0
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/LICENSE +103 -201
- package/README.md +56 -2
- package/THIRD_PARTY_NOTICES.md +7 -1
- package/dist/main.js +40827 -14280
- package/package.json +8 -4
- package/plugin/specset/.claude-plugin/plugin.json +2 -2
- package/plugin/specset/.codex-plugin/plugin.json +7 -4
- package/plugin/specset/README.md +1 -0
- package/plugin/specset/assets/icon.png +0 -0
- package/plugin/specset/skills/specset/SKILL.md +24 -5
- package/plugin/specset/skills/specset-admin/SKILL.md +21 -7
- package/plugin/specset/skills/specset-agent/SKILL.md +138 -1
- package/plugin/specset/skills/specset-closeout/SKILL.md +300 -52
- package/plugin/specset/skills/specset-issues/SKILL.md +27 -0
- package/plugin/specset/skills/specset-projects/SKILL.md +42 -17
- package/plugin/specset/skills/specset-search/SKILL.md +23 -5
- package/plugin/specset/skills/specset-submittals/SKILL.md +4 -2
- package/plugin/specset/skills/specset-tools/SKILL.md +60 -21
- package/skills/specset/SKILL.md +24 -5
- package/skills/specset-admin/SKILL.md +21 -7
- package/skills/specset-agent/SKILL.md +138 -1
- package/skills/specset-closeout/SKILL.md +300 -52
- package/skills/specset-issues/SKILL.md +27 -0
- package/skills/specset-projects/SKILL.md +42 -17
- package/skills/specset-search/SKILL.md +23 -5
- package/skills/specset-submittals/SKILL.md +4 -2
- package/skills/specset-tools/SKILL.md +60 -21
|
@@ -1,94 +1,342 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: specset-closeout
|
|
3
|
-
description: Use when managing Specset closeout and facilities data — assets, locations, products, companies, warranties,
|
|
3
|
+
description: Use when managing Specset closeout and facilities data — assets, locations, products, companies, warranties, procedures, maintenance plans, work orders, and their documents and links.
|
|
4
4
|
allowed-tools: Bash Read AskUserQuestion
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Closeout & Facilities Data
|
|
8
8
|
|
|
9
|
-
Run every operation with `specset api`. All ids are plain UUIDs. Inline enums, numbers, lists, and input objects in the operation text (`-F`
|
|
9
|
+
Run every operation with `specset api`. All ids are plain UUIDs. Inline enums, numbers, lists, and input objects in the operation text (`-F` sends strings only; Variable Limitations and Schema Discovery live in the `specset` skill).
|
|
10
10
|
|
|
11
11
|
## Entity Model
|
|
12
12
|
|
|
13
|
-
**Locations** are the spatial scaffold (site → building → level → room), nesting
|
|
13
|
+
**Locations** are the spatial scaffold (site → building → level → room), nesting through `parentId`. **Systems** are disciplines and equipment groups, also nested. **Products** are specified make/models. **Assets** are installed instances: each asset has a location, may reference a product and responsible company, and can join multiple systems. **Warranties** attach to assets.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Maintenance has three layers:
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
- **Procedure** — reusable checklist content: ordered typed fields, descriptions, and source references.
|
|
18
|
+
- **MaintenancePlan** — a schedule on exactly one Product, Asset, Location, or System. Product plans fan out to installed assets. Its `tiers` are independent schedule items that pair a Procedure with a calendar cadence, meter trigger, or both.
|
|
19
|
+
- **WorkOrder** — a concrete occurrence or ad-hoc job. Generated work orders snapshot their checklist fields, so history remains stable when a Procedure changes.
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|---|---|
|
|
21
|
-
| `<entity>(id: ID!)` | Single record (`null` if missing or in another org) |
|
|
22
|
-
| `paginated<Entities>(projectId: ID!, limit: Int, offset: Int, ...)` | Returns `{ items { ... } totalFilteredCount }` |
|
|
23
|
-
| `search<Entities>(projectId: ID!, search: String)` | Fuzzy text lookup |
|
|
24
|
-
| `create<Entity>(input: ...)` / `update<Entity>(input: ...)` | Update inputs take `id` plus only the fields to change |
|
|
25
|
-
| `delete<Entity>(id: ID!)` | Hard delete — see Safety |
|
|
21
|
+
`MaintenanceTask` and its completion API no longer exist. Use Procedure, MaintenancePlan, and WorkOrder operations below.
|
|
26
22
|
|
|
27
|
-
|
|
23
|
+
## Discover Before Mutating
|
|
28
24
|
|
|
29
|
-
|
|
30
|
-
- **Warranty / MaintenanceTask** — asset-scoped: create inputs take `assetId` (not `projectId`); no `search<Entities>` query, and `search` on their paginated lists is ignored — scope by asset with `warrantiesByAsset(assetId)` / `maintenanceTasksByAsset(assetId)` instead.
|
|
31
|
-
- Batch deletes exist for some entities (`deleteLocations(ids)`, `deleteCompanies(ids)`, `deleteSystems(ids)`, `deleteWarranties(ids)`, `deleteMaintenanceTasks(ids)`) — same confirmation rules as single deletes.
|
|
25
|
+
Input objects evolve, especially checklist fields and plan tiers. Introspect the relevant input before composing a mutation:
|
|
32
26
|
|
|
33
|
-
|
|
27
|
+
```bash
|
|
28
|
+
specset api --query '{
|
|
29
|
+
createPlan: __type(name: "CreateMaintenancePlanInput") {
|
|
30
|
+
inputFields { name type { kind name ofType { kind name } } }
|
|
31
|
+
}
|
|
32
|
+
tier: __type(name: "MaintenancePlanTierInput") {
|
|
33
|
+
inputFields { name type { kind name ofType { kind name } } }
|
|
34
|
+
}
|
|
35
|
+
complete: __type(name: "CompleteWorkOrderInput") {
|
|
36
|
+
inputFields { name type { kind name ofType { kind name } } }
|
|
37
|
+
}
|
|
38
|
+
}'
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Inline input objects and enums in the operation text. Use `-F` for UUIDs, dates, and other scalar strings.
|
|
42
|
+
|
|
43
|
+
## Core Closeout Records
|
|
44
|
+
|
|
45
|
+
Asset, Location, Product, Company, System, and Warranty retain the standard surface:
|
|
46
|
+
|
|
47
|
+
| Operation | Shape |
|
|
48
|
+
| ------------------------------------------------------------------- | ------------------------------------------- |
|
|
49
|
+
| `<entity>(id: ID!)` | Single record; nullable when missing |
|
|
50
|
+
| `paginated<Entities>(projectId: ID!, limit: Int, offset: Int, ...)` | `{ items { ... } totalFilteredCount }` |
|
|
51
|
+
| `create<Entity>(input: ...)` / `update<Entity>(input: ...)` | Update inputs take `id` plus changed fields |
|
|
52
|
+
| `delete<Entity>(id: ID!)` | Hard delete; follow Safety below |
|
|
53
|
+
|
|
54
|
+
Notable differences:
|
|
55
|
+
|
|
56
|
+
- Asset creation requires `projectId` and `locationId`. `paginatedAssets` accepts `search` and filters such as `statuses`, `locationIds`, `productIds`, `systemIds`, `responsibleCompanyIds`, `parentIds`, and `archived`.
|
|
57
|
+
- Warranty is asset-scoped; use `warrantiesByAsset(assetId)` to browse one asset's warranties.
|
|
58
|
+
- Location, Product, Company, System, and Asset updates support reversible `archived` state. Prefer archiving to deletion.
|
|
59
|
+
- Batch-delete availability varies. Introspect the mutation root rather than guessing an operation name.
|
|
60
|
+
|
|
61
|
+
Asset link setters replace the complete set for the given role/relationship; omitted ids are removed and `[]` clears the set:
|
|
34
62
|
|
|
35
|
-
|
|
63
|
+
- `setAssetSystems(assetId, role, systemIds)` / `assetSystemMemberships(assetId)`
|
|
64
|
+
- `setAssetSubmittals(assetId, relationship, submittalIds)` / `assetSubmittalLinks(assetId)`
|
|
65
|
+
- `setAssetDrawingSheets(assetId, role, drawingSheetIds)` / `assetDrawingSheetLinks(assetId)`
|
|
36
66
|
|
|
37
|
-
##
|
|
67
|
+
## Procedures
|
|
38
68
|
|
|
39
|
-
|
|
69
|
+
Use `procedure(id)` and `paginatedProcedures(projectId, filters, limit, offset)`. Procedure list filters include `search` and `archived`.
|
|
40
70
|
|
|
41
|
-
|
|
42
|
-
- `setAssetSubmittals(assetId: ID!, relationship: ..., submittalIds: [ID!]!)` — relationships: `Source`, `Revision`, `Substitution`, `Addendum`. Read back with `assetSubmittalLinks(assetId)`.
|
|
43
|
-
- `setAssetDrawingSheets(assetId: ID!, role: ..., drawingSheetIds: [ID!]!)` — roles include `Plan`, `Schedule`, `Diagram`, `Detail`, `AsBuilt`, `Other`. Read back with `assetDrawingSheetLinks(assetId)`.
|
|
71
|
+
Create a reusable checklist with its fields atomically:
|
|
44
72
|
|
|
45
73
|
```bash
|
|
46
|
-
specset api --query 'mutation($
|
|
47
|
-
|
|
48
|
-
|
|
74
|
+
specset api --query 'mutation($projectId: ID!) {
|
|
75
|
+
createProcedure(input: {
|
|
76
|
+
projectId: $projectId
|
|
77
|
+
name: "Quarterly AHU service"
|
|
78
|
+
fields: [
|
|
79
|
+
{ name: "Inspect belts", fieldType: Checkbox }
|
|
80
|
+
{ name: "Record supply temperature", fieldType: Number, unit: "°F" }
|
|
81
|
+
]
|
|
82
|
+
}) {
|
|
83
|
+
id name updatedAt
|
|
84
|
+
fields { id name fieldType position required }
|
|
49
85
|
}
|
|
50
|
-
}' -F
|
|
86
|
+
}' -F projectId=<project-id>
|
|
51
87
|
```
|
|
52
88
|
|
|
53
|
-
|
|
89
|
+
The fields' array order sets their `position`; neither `CreateProcedureFieldInput` nor `UpdateProcedureFieldInput` accepts a `position` property. `updateProcedure(input: { id, ... })` is partial for scalar fields. Supplying `fields` performs a full checklist replacement; first read the current fields and include the `id` of every row that should retain its identity. `deleteProcedure(id, force)` is guarded when active plans use it. Do not set `force: true` without naming the affected plans and confirming the destructive change.
|
|
90
|
+
|
|
91
|
+
## Maintenance Plans and Tiers
|
|
92
|
+
|
|
93
|
+
Read with `maintenancePlan(id)`, `paginatedMaintenancePlans(projectId, filters, limit, offset)`, or `maintenancePlansForAsset(assetId, includeProductPlans)`.
|
|
94
|
+
|
|
95
|
+
Create requires exactly one subject id (`productId`, `assetId`, `locationId`, or `systemId`) and a `frequencyKind`. Prefer `tiers`; the top-level procedure and interval fields remain a single-item compatibility surface. Supply either:
|
|
96
|
+
|
|
97
|
+
- single-tier compatibility fields: `procedureId` (or inline `procedure`) plus `intervalValue` / `intervalUnit`; or
|
|
98
|
+
- `tiers: [MaintenancePlanTierInput!]` for independent schedule items. Each item selects one `procedureId` or creates one inline.
|
|
99
|
+
|
|
100
|
+
Do not mix `tiers` with the single-tier procedure/cadence fields. Calendar item units are `Days`, `Weeks`, `Months`, or `Years`. Optional meter conditions live on each item as the pair `meterUnit` (`Hours` or `Cycles`) and `meterThreshold`; provide both or neither. Calendar cadences are independent and do not need to be multiples of one another. Set `skipLowerTiersOnSharedDate: true` to suppress a shorter calendar item when it naturally shares a date with a longer one; each work order still contains only its own Procedure. A suppressed item's meter condition stays armed and may create that item's work order later. `gateOnOpen` prevents repeated meter-generated work while an occurrence remains open.
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
specset api --query 'mutation($assetId: ID!, $monthlyId: ID!, $quarterlyId: ID!) {
|
|
104
|
+
createMaintenancePlan(input: {
|
|
105
|
+
assetId: $assetId
|
|
106
|
+
name: "AHU PM program"
|
|
107
|
+
frequencyKind: Calendar
|
|
108
|
+
skipLowerTiersOnSharedDate: true
|
|
109
|
+
gateOnOpen: true
|
|
110
|
+
tiers: [
|
|
111
|
+
{ procedureId: $monthlyId, intervalValue: 1, intervalUnit: Months }
|
|
112
|
+
{
|
|
113
|
+
procedureId: $quarterlyId
|
|
114
|
+
intervalValue: 3
|
|
115
|
+
intervalUnit: Months
|
|
116
|
+
meterUnit: Hours
|
|
117
|
+
meterThreshold: 500
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
}) {
|
|
121
|
+
id name frequencyKind skipLowerTiersOnSharedDate gateOnOpen
|
|
122
|
+
tiers {
|
|
123
|
+
id intervalValue intervalUnit meterUnit meterThreshold
|
|
124
|
+
procedure { id name }
|
|
125
|
+
}
|
|
126
|
+
openWorkOrderCount
|
|
127
|
+
}
|
|
128
|
+
}' -F assetId=<asset-id> -F monthlyId=<procedure-id> -F quarterlyId=<procedure-id>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
For a meter-only plan, prefer the typed input: `schedule: { meter: { unit: Hours|Cycles, threshold: <n>, gateOnOpen } }` with a single tier. The legacy encoding (`frequencyKind: RuntimeHours` or `Cycles`) additionally requires plan-level `intervalValue` set to the threshold and `intervalUnit: Hours`/`Cycles` — a threshold on the item alone is rejected. For an on-demand plan, use `AsNeeded`, `EventTriggered`, or `Other` and omit calendar and meter fields.
|
|
132
|
+
|
|
133
|
+
`updateMaintenancePlan(input: { id, ... })` can retarget the subject: pass exactly one of `productId`/`assetId`/`locationId`/`systemId` (same project). Open work orders for the old subject are retired — untouched ones removed, in-progress ones canceled — and fresh chains generate for the new subject. Supplying `tiers` fully replaces the schedule-item set: include the `id` of every existing item to update/retain, omit an item only when it should be removed, and omit `id` only for new items. Read the plan and its item ids immediately before updating.
|
|
134
|
+
|
|
135
|
+
Use `createWorkOrderFromPlan(planId, targetAssetId, dueDate, coveredTierIds)` for an early/manual occurrence of a plan. Product plans require the concrete `targetAssetId`. `coveredTierIds` is optional; when supplied it states exactly which tiers the occurrence performs.
|
|
136
|
+
|
|
137
|
+
## Work Orders
|
|
138
|
+
|
|
139
|
+
Use `workOrder(id)`, `paginatedWorkOrders(projectId, filters, limit, offset)`, and `paginatedGroupedWorkOrders(projectId, groupBy, groupKeys, filters, limit, offset)`. Grouped reads require both the grouping dimensions and the current group-key path. Useful fields include `status`, `dueDate`, `performedDate`, `priority`, `assignee`, `plan`, `planTier`, `coveredTiers`, `fields`, and `documents`.
|
|
140
|
+
|
|
141
|
+
`createWorkOrder(input)` creates ad-hoc work and requires exactly one of `assetId`, `locationId`, or `systemId`, plus `name`. Optional `fields` create a reusable inline Procedure; optional `recurrence` also creates a MaintenancePlan. Use `updateWorkOrder(input: { id, ... })` for editable metadata.
|
|
142
|
+
|
|
143
|
+
Checklist responses use `setWorkOrderFieldResponse(input)` or `setWorkOrderFieldResponses(inputs)`. Introspect `SetWorkOrderFieldResponseInput`: answer columns vary by field type (`valueNumber`, `valueText`, `valueChoice`, `status`, and `note`).
|
|
144
|
+
|
|
145
|
+
Complete work through the batch mutation even for one row:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
specset api --query 'mutation($id: ID!, $performedDate: DateTime!) {
|
|
149
|
+
completeWorkOrders(inputs: [{ id: $id, performedDate: $performedDate }]) {
|
|
150
|
+
workOrder { id status performedDate }
|
|
151
|
+
nextWorkOrder { id status dueDate }
|
|
152
|
+
}
|
|
153
|
+
}' -F id=<work-order-id> -F performedDate=2026-08-04
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Other lifecycle operations:
|
|
157
|
+
|
|
158
|
+
- `skipWorkOrder(id, notes, mode)` — closes the occurrence as skipped; omit `mode` for normal independent-item plans. Non-default modes exist only for historical merged work orders.
|
|
159
|
+
- `reopenWorkOrder(id)` — reopens completed/skipped work when allowed.
|
|
160
|
+
- `makeWorkOrderRecurring(workOrderId, recurrence)` — converts eligible ad-hoc work into a recurring plan.
|
|
161
|
+
- `deleteWorkOrder(id)` — hard delete.
|
|
162
|
+
- `bulkAssignWorkOrders(selection, assigneeId)` and `bulkDeleteWorkOrders(selection)` operate on an explicit selection object.
|
|
163
|
+
- `addWorkOrderDocument(workOrderId, documentId, workOrderFieldId)` and `removeWorkOrderDocument(id)` manage evidence. Removal takes the WorkOrderDocument pivot id.
|
|
164
|
+
|
|
165
|
+
## Entity Documents and Documentation
|
|
166
|
+
|
|
167
|
+
Asset, Location, Product, Company, System, and Warranty link project Documents through entity-specific role-tagged pivots. Read `<entity>Documents(<entity>Id)`, then call `set<Entity>DocumentRoles(<entity>Id, documentId, roles)` after introspecting that entity's role enum (`AssetDocumentRole`, `ProductDocumentRole`, `SystemDocumentRole`, `LocationDocumentRole`, `CompanyDocumentRole`, `WarrantyDocumentRole`). The roles array is replaced atomically; an empty role list removes the pivot and may delete the underlying Document when it becomes orphaned. Asset also exposes `deleteAssetDocument(id)`.
|
|
168
|
+
|
|
169
|
+
Attaching a new file is a three-step flow — the same Document can then be linked to several entities (a family IOM shared by every product in the family):
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
CLOUD_FILE=$(specset files upload ./aaon-rn-iom.pdf --type application/pdf --json | jq -r .id)
|
|
173
|
+
specset api --query "mutation { createDocumentsFromCloudFiles(cloudFileIds: [\"$CLOUD_FILE\"], projectId: \"<project-id>\") { id title } }"
|
|
174
|
+
specset api --query 'mutation { updateDocument(id: "<document-id>", title: "AAON RN Series — IOM") { id } }' # title drives lists and PDF bookmarks; the default is the filename
|
|
175
|
+
specset api --query 'mutation { setProductDocumentRoles(productId: "<product-id>", documentId: "<document-id>", roles: [OperationManual, MaintenanceManual]) { id } }'
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Existing project Documents work too — a submittal attachment's `document { id }` (from `paginatedSubmittals … attachments { document { id title } }`) can be linked directly as `SubmittalPackage`/`Datasheet`; the only check is that the Document belongs to the same project. To bind a slice of a large file, `extractPagesFromFileResource(id: <fileResourceId>, pages: [3, 4, 5])` returns a new CloudFile to feed into `createDocumentsFromCloudFiles`. Only PDF files merge into the O&M package export; images and other types are listed as references.
|
|
179
|
+
|
|
180
|
+
Asset, Location, Product, Company, and System also have markdown documentation blocks. `update<Entity>Documentation(id, markdown)` replaces the block; `mark<Entity>DocumentationComplete(id)` attests that it is current. Any later create/update/link on the entity (a new document pivot, a warranty document, a field edit) marks the documentation stale again, so when seeding a graph write documentation **last**. Calling `mark<Entity>DocumentationComplete` with an empty block sets the state to `NotApplicable`, which the package readiness report accepts — use it for entities that don't warrant prose rather than writing filler.
|
|
181
|
+
|
|
182
|
+
### Writing documentation that reads well in the O&M package export
|
|
183
|
+
|
|
184
|
+
The rules below are the same ones the in-app documentation agent follows (they are one shared block; a test keeps this copy in sync).
|
|
185
|
+
|
|
186
|
+
### Where Documentation Renders
|
|
187
|
+
|
|
188
|
+
The documentation block renders on the entity's show page and in the compiled O&M closeout package PDF — a formal handover manual the owner's facilities team keeps for decades. The manual already prints the following from structured data, so documentation never restates it:
|
|
54
189
|
|
|
55
|
-
|
|
190
|
+
- Identity: tag, serial number, status, install and commissioning dates, quantity, location path, manufacturer, model, spec section, classification, data-package tier.
|
|
191
|
+
- Warranties: kind, start and expiration dates, duration, claims contact and the terms text.
|
|
192
|
+
- Maintenance schedule: every plan, procedure, frequency, craft and estimated hours, built from the maintenance plan records.
|
|
193
|
+
- Spare parts: name, SKU, manufacturer part number, quantity and vendor, from the part records.
|
|
194
|
+
- Contacts: the responsible company with phone and email, plus a per-system contacts rollup.
|
|
195
|
+
- Linked documents: every datasheet, manual, warranty and report, listed and bound directly behind the entity's page.
|
|
56
196
|
|
|
57
|
-
|
|
58
|
-
- `set<Entity>DocumentRoles(<entity>Id: ID!, documentId: ID!, roles: [...]!)` — upsert the linkage; an empty `roles` list removes it (and the document itself if orphaned). Roles are per-entity enums — e.g. `ProductDocumentRole` is `Datasheet`, `InstallationManual`, `OperationManual`, `MaintenanceManual`, `Warranty`, `SubmittalPackage`, `Other`; introspect each entity's enum before use.
|
|
59
|
-
- `delete<Entity>Document(id: ID!)` — takes the **pivot** id from the list query, not the document id.
|
|
197
|
+
### What to Write
|
|
60
198
|
|
|
61
|
-
|
|
199
|
+
Spend the narrative on what tables cannot say: sequences of operation with real setpoints, startup and shutdown, seasonal and emergency procedures, troubleshooting, safety warnings, cross-system interfaces, and callouts where sources conflict. Describe the equipment, not the records — state how it works and how it is cared for, and fold genuine unknowns into one short "Open Items" list, one line each, without citations. A short block with two real sections beats a full template of filler: omit every section the sources don't genuinely cover, and leaving the block blank is a valid outcome for an entity with nothing to add.
|
|
62
200
|
|
|
63
|
-
|
|
201
|
+
Write for the building operator in plain language. Paraphrase manual procedures as proper markdown lists, and fix concatenation artifacts (double periods, misspelled manufacturer names) from sources.
|
|
64
202
|
|
|
65
|
-
|
|
203
|
+
Keep the block free of what the manual already prints and of anything that goes stale:
|
|
66
204
|
|
|
67
|
-
-
|
|
68
|
-
-
|
|
205
|
+
- No warranty terms or dates in prose, no frequency lists or task inventories, no tag/serial/model/quantity dossiers, no contractor names or phone numbers, and no parts tables pasted from manuals — replacement-parts data belongs in part records.
|
|
206
|
+
- No claims about the state of the records ("no dates are populated", "this task is recorded on the checklist") — they end up contradicting the printed tables.
|
|
207
|
+
- No restatement of the entity's `description` field as the opening — both print in sequence.
|
|
208
|
+
- No internal vocabulary ("portal", "normalized", "occurrence basis", "identity guard", "MaintenanceTask", "sourceMarkdown"), entity UUIDs, or extraction and slug references.
|
|
209
|
+
- No all-caps sentences or blockquote dumps of manual text, and no sections whose only content is "not established in reviewed source" or "see the linked manual".
|
|
69
210
|
|
|
70
|
-
|
|
211
|
+
### Citations
|
|
71
212
|
|
|
72
|
-
|
|
213
|
+
Citations are clickable in the app and plain text in the printed manual, so keep them sparse and short: at most one per section, placed at the end of the claim it supports, as a markdown link whose display text is a short label such as "Siemens O&M p. 712" or "Warranty Table p. 5". Use citation URLs exactly as returned by the tools. The entity's bound-documents list already anchors provenance, so there are no per-sentence citations, multi-citation parentheticals, full source filenames, paragraph numbers, spreadsheet cell references, or dedicated "Source:" lines (print strips those).
|
|
73
214
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
-
|
|
77
|
-
|
|
215
|
+
### Headings
|
|
216
|
+
|
|
217
|
+
The entity name renders as the page title, the block is embedded under a "Documentation" heading on the show page, and it may be re-rendered inside a parent entity's hierarchical view, so heading levels must compose:
|
|
218
|
+
|
|
219
|
+
- Top-level sections use `##`; sub-sections use `###`, then `####`, without skipping levels.
|
|
220
|
+
- Begin with the first content section (for example `## Description`). The entity's own name is never a heading and `#` is never used — that level is the page title, and a leading H1 matching the entity name is suppressed in print.
|
|
221
|
+
- Keep section names consistent with the templates below so sibling entities render with the same structure.
|
|
222
|
+
|
|
223
|
+
### Section Templates
|
|
224
|
+
|
|
225
|
+
Use these section orderings with the operator-facing names shown; most entities warrant only one to three of them.
|
|
226
|
+
|
|
227
|
+
**Product** — the canonical home for manufacturer operating knowledge. A product with any linked submittal, datasheet, manual or warranty document gets a block; only a product with no linked source documents is left blank. Location and system blocks may roll product knowledge up but never replace it.
|
|
228
|
+
|
|
229
|
+
```markdown
|
|
230
|
+
## Description (1-3 sentences: what it is and its role — not metadata)
|
|
231
|
+
## Operation (sequence of operation, setpoints, modes, interlocks)
|
|
232
|
+
## Routine Maintenance (procedure steps and precautions — never frequencies; the schedule table prints those)
|
|
233
|
+
## Troubleshooting
|
|
234
|
+
## Safety
|
|
235
|
+
## Open Items
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
**System** — the system in its own words, spanning multiple products. A parent system covers only what is true of the whole (shared operation, shared safety): the manual prints the subsystems list and rolls up schedules, warranties and contacts, so content common to sibling systems lives once on the parent and each child gets at most one sentence of scope.
|
|
239
|
+
|
|
240
|
+
```markdown
|
|
241
|
+
## Description (what the system is and its boundary, 2-4 sentences)
|
|
242
|
+
## Sequence of Operation
|
|
243
|
+
## Interfaces (only real cross-system relationships: what feeds, releases, or controls what)
|
|
244
|
+
## Seasonal & Emergency Procedures
|
|
245
|
+
## Troubleshooting
|
|
246
|
+
## Safety
|
|
247
|
+
## Open Items
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Location** — building or area overview.
|
|
251
|
+
|
|
252
|
+
```markdown
|
|
253
|
+
## Description
|
|
254
|
+
## Access & Safety
|
|
255
|
+
## Open Items
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**Asset** — installation-specific facts only; most assets need very little.
|
|
259
|
+
|
|
260
|
+
```markdown
|
|
261
|
+
## As-Installed Configuration (field settings, orientations, connections not captured by structured fields)
|
|
262
|
+
## Commissioning Notes
|
|
263
|
+
## Open Items
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**Company** — only what the contacts block cannot carry.
|
|
267
|
+
|
|
268
|
+
```markdown
|
|
269
|
+
## Escalation
|
|
270
|
+
## Supplier Portal
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Example (Product)
|
|
274
|
+
|
|
275
|
+
```markdown
|
|
276
|
+
## Description
|
|
277
|
+
Passive rubber check valves preventing backflow from rivers, oceans, and storm water into outfall lines.
|
|
278
|
+
|
|
279
|
+
## Operation
|
|
280
|
+
Flow opens the bill section; back-pressure closes it. No power or operator action required. Do not exceed 25 psi back-pressure [Manual p. 3](sb://doc/...).
|
|
281
|
+
|
|
282
|
+
## Routine Maintenance
|
|
283
|
+
1. Clear debris from the bill opening.
|
|
284
|
+
2. Inspect the elastomer for cuts or abrasion; replace on any through-cut.
|
|
285
|
+
|
|
286
|
+
## Troubleshooting
|
|
287
|
+
Standing water upstream usually means debris is holding the bill open — clear before assuming valve failure.
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## Parts and Meter Readings
|
|
291
|
+
|
|
292
|
+
`createPart(input: { projectId, name, sku, manufacturerPartNumber, unit, quantity, minQuantity, maxQuantity, unitCost, stocked, bin, vendorId, assetLinks: [{ assetId, quantity }] })` creates a stocked part with its per-asset quantities; `createPartMovement(input: { partId, quantity, note })` records receipts (positive) and consumption (negative), and `countedQuantity` records a cycle count. Read with `paginatedParts(projectId, filters)`.
|
|
293
|
+
|
|
294
|
+
`logMeterReading(assetId, unit: Hours|Cycles, value, readAt)` records a runtime or cycle reading; meter-triggered plan tiers (`meterUnit`/`meterThreshold`) generate work from these. `meterReadings(assetId, unit, limit)` lists them.
|
|
295
|
+
|
|
296
|
+
## Closeout Packages (O&M manual export)
|
|
297
|
+
|
|
298
|
+
A closeout package compiles the graph into one bookmarked PDF: front matter (cover, directory, warranty log, hyperlinked TOC), a slip sheet and overview per system (or location), a data page per asset, and every linked PDF document bound behind its owner (each unique file once). Scope is `Project` (everything), `Systems`, `Assets`, or `Locations` with `targetIds`; `orderingAxis` is `System` (default) or `Location`.
|
|
299
|
+
|
|
300
|
+
Check readiness first — it is deterministic and the same builder the compile uses, so a clean report means a clean manual:
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
specset api --query '{ closeoutPackageReadiness(projectId: "<project-id>", scopeKind: Project) { warningCount warnings } }'
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Warning kinds and how to clear them: `DocumentationMissing`/`DocumentationOutdated` (write or mark documentation complete on the named Asset/Product/System/Location), `AssetFieldMissing` (serial number or install date), `WarrantyMissing` (every asset needs at least one Warranty), `ProductManualMissing` (each Product needs an `OperationManual` or `MaintenanceManual` document), `PlanWithoutProcedure` (a plan with no tiers), `AttachmentNotMergeable` (non-PDF), `TargetDeleted`. `EmptyScope` blocks creation.
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
specset api --query 'mutation { createCloseoutPackageExport(input: { projectId: "<project-id>", scopeKind: Project, orderingAxis: System, includeAttachments: true, title: "… O&M Manual" }) { id workflow { status } } }'
|
|
310
|
+
specset api --query '{ closeoutPackageExport(id: "<export-id>") { completedAt warnings workflow { status progress error } fileResource { id name } } }'
|
|
311
|
+
specset files download <file-resource-id> --out manual.pdf # once workflow.status is Completed
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
`paginatedCloseoutPackageExports(projectId)` lists prior exports; exports are immutable records — regenerate by creating a new one; `deleteCloseoutPackageExport(id)` removes one and its file. In the app the same flow lives under the project's Closeout → Packages page.
|
|
315
|
+
|
|
316
|
+
## Enabling closeout
|
|
317
|
+
|
|
318
|
+
`CloseoutAuthService.isCloseoutActive` requires the org SKU **and** (unless the org is in `fmMode`) the project toggle. Both are superadmin operations; `updateOrg(skus)` replaces the whole SKU object, so read the current flags and resend them:
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
specset api --query '{ org(id: "<org-id>") { skus { closeout fmMode dailyLog scheduling estimation agentSessions agentSkills customAgents whitelabel modelRoutingV2 } } }'
|
|
322
|
+
specset api --query 'mutation { updateOrg(id: "<org-id>", skus: { closeout: true, dailyLog: true, scheduling: true }) { id } updateProject(id: "<project-id>", toolSettings: { closeout: true }) { id } }'
|
|
323
|
+
```
|
|
78
324
|
|
|
79
|
-
## Dedup / Re-
|
|
325
|
+
## Dedup / Re-pointing
|
|
80
326
|
|
|
81
327
|
For duplicate products P1 (loser) and P2 (survivor):
|
|
82
328
|
|
|
83
|
-
1. `paginatedAssets(projectId
|
|
84
|
-
2. `updateAsset(input: { id
|
|
85
|
-
3. Re-run
|
|
86
|
-
4. `updateProduct(input: { id:
|
|
329
|
+
1. Query `paginatedAssets(projectId, filters: { productIds: [P1] })` and collect impacted assets.
|
|
330
|
+
2. `updateAsset(input: { id, productId: P2 })` for each asset.
|
|
331
|
+
3. Re-run the filtered query and confirm zero remaining references.
|
|
332
|
+
4. Archive P1 with `updateProduct(input: { id: P1, archived: true })`.
|
|
87
333
|
|
|
88
|
-
|
|
334
|
+
Use the same impact-first pattern for duplicate companies, locations, and systems.
|
|
89
335
|
|
|
90
336
|
## Safety
|
|
91
337
|
|
|
92
|
-
- Deletes
|
|
93
|
-
- Prefer
|
|
94
|
-
-
|
|
338
|
+
- Deletes are hard and have no undo. Before executing, name the exact record and id and confirm the impact.
|
|
339
|
+
- Prefer partial updates, and prefer `archived: true` to delete where supported.
|
|
340
|
+
- Read Procedure fields and MaintenancePlan tiers before any full-replacement update.
|
|
341
|
+
- Deleting plans or force-deleting Procedures can alter future generated work. Check active plan/open-work-order counts first.
|
|
342
|
+
- Removing a document linkage can delete an orphaned underlying Document; disclose that before confirming.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: specset-issues
|
|
3
|
+
description: Use when working with a Specset project's design-review issues from the CLI — listing the queue by severity, tier, or verification state, and reading each issue's verdict.
|
|
4
|
+
allowed-tools: Bash Read AskUserQuestion
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Specset Issues
|
|
8
|
+
|
|
9
|
+
Design reviews (Design Review, Drawing Review, Design Quality Review, Project Review) and issue-finding skills file **issues** on a project. Each issue can be **verified** by an adversarial agent that re-reads the cited sheets and sections and records a verdict — `Confirmed` or `Rejected` — with a short justification. New review issues are verified automatically; skill-run issues, issues filed before verification existed, and issues whose runs ended without a verdict are verified on demand.
|
|
10
|
+
|
|
11
|
+
## Reading the queue
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
specset issues list --project <projectId> # active, non-Cleanup issues
|
|
15
|
+
specset issues list --project <projectId> --severity High,Medium --notVerified --limit 500
|
|
16
|
+
specset issues list --project <projectId> --thread <reviewThreadId> --json # one review's findings
|
|
17
|
+
specset issues list --project <projectId> --thread <runThreadId> --org <slug> # a skill run, by the id agent chat printed
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
- `--severity` takes a comma list (`High`, `Medium`, `Low`); `--notVerified` keeps only issues with no verdict; `--archived` switches to the archived set.
|
|
21
|
+
- `--thread` matches the thread and every review thread under it: a skill's issues belong to its delegated review, so the run id `specset agent chat` prints finds them directly. `--org` pins the organization like the other commands.
|
|
22
|
+
- Cleanup-tier issues (real but self-resolving, kept out of the review queue) are excluded unless you pass `--includeCleanup` — the same rule the app's default queue uses.
|
|
23
|
+
- The table shows `#number severity tier verdict title`; `verdict` is `Confirmed`, `Rejected`, `verifying` (run in flight) or `unverified`. `--json` returns the full rows including the originating review thread.
|
|
24
|
+
|
|
25
|
+
## Verification
|
|
26
|
+
|
|
27
|
+
Verdicts come from the app's own verification runs: new review issues are verified automatically, and a member can start verification for an individual issue from the issue in the app. `specset issues list` shows the verdict on every row (`--notVerified` to find the ones still waiting).
|
|
@@ -8,6 +8,10 @@ allowed-tools: Bash Read AskUserQuestion
|
|
|
8
8
|
|
|
9
9
|
This skill mutates data — confirm the project name and which files belong to it before creating anything. Inline enums, ints, lists, and input objects in the operation text (`-F` is strings-only; Variable Limitations and Schema Discovery live in the `specset` skill).
|
|
10
10
|
|
|
11
|
+
## Find a project
|
|
12
|
+
|
|
13
|
+
Use `specset projects list --json` to list the active organization's projects with IDs and links. `--org <slug|id>` pins another organization, `--limit 20` bounds output, and `--archived` lists archived projects. Pass a returned ID or link to other project commands.
|
|
14
|
+
|
|
11
15
|
## Reading Projects
|
|
12
16
|
|
|
13
17
|
```graphql
|
|
@@ -20,17 +24,17 @@ project(id: ID!): Project!
|
|
|
20
24
|
|
|
21
25
|
## Creating a Project
|
|
22
26
|
|
|
23
|
-
`createProject` does **not** add the creator as a project member, so the new project won't appear in the default `projects` list — fetch it by `project(id)
|
|
27
|
+
`createProject` does **not** add the creator as a project member, so the new project won't appear in the default `projects` list until someone adds them — fetch it by `project(id)`. The `createProject` mutation takes `userIds` and `teamIds` to add members in the same call; `specset projects create` doesn't, so add them as a second step.
|
|
24
28
|
|
|
25
|
-
1. Create it:
|
|
29
|
+
1. Create it with the project command. New projects automatically support drawing graphs; no opt-in is required:
|
|
26
30
|
|
|
27
31
|
```bash
|
|
28
|
-
specset
|
|
29
|
-
createProject(orgId: $orgId, name: $name) { id name }
|
|
30
|
-
}' -F orgId=<org-id> -F name='Riverside Medical Center'
|
|
32
|
+
specset projects create 'Riverside Medical Center' --json
|
|
31
33
|
```
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
Select the active organization first with `specset org use <slug>`. Pass `--host <url>` to both commands when targeting a specific deployment. JSON output includes `id`, `name`, and `drawingGraphEnabled`. Existing projects qualify when every current sheet supports graph resolution (node version 5 or later); ledger failures do not disable graphs.
|
|
36
|
+
|
|
37
|
+
2. Get your own user id with `{ me { id } }`, then add yourself (and anyone else the user names) as a member. `role` is an optional `OrgMemberTeamRole` enum — `Member`, `Manager`, or `Admin` — inlined when specified. To add several people or whole teams at once, use `addProjectMembers(projectId: ID!, userIds: [ID!], teamIds: [ID!])` (inline the lists); a team puts everyone on it on the project, and `teams(orgId)` lists them:
|
|
34
38
|
|
|
35
39
|
```bash
|
|
36
40
|
specset api --query 'mutation($projectId: ID!, $userId: ID!) {
|
|
@@ -38,27 +42,31 @@ specset api --query 'mutation($projectId: ID!, $userId: ID!) {
|
|
|
38
42
|
}' -F projectId=<project-id> -F userId=<user-id>
|
|
39
43
|
```
|
|
40
44
|
|
|
45
|
+
## Review Settings
|
|
46
|
+
|
|
47
|
+
Drawing graphs rebuild automatically as project inputs change. Automatic
|
|
48
|
+
verification of newly filed review issues is a platform setting managed by
|
|
49
|
+
Specset; it does not verify the existing queue. Project Review has no separate
|
|
50
|
+
project toggle; its availability in the app comes from the organization's
|
|
51
|
+
configured agents.
|
|
52
|
+
|
|
41
53
|
## Importing Documents
|
|
42
54
|
|
|
43
|
-
|
|
44
|
-
|
|
55
|
+
For an existing project, inspect drawing review readiness with `specset projects drawing-graph --project <id> --json`. Add `--rebuild` to queue resolution from already extracted drawing content; this does not start sheet extraction or element backfill. Re-run the command without mutation flags to inspect readiness after the background rebuild. Eligibility is automatic for new projects and existing projects whose current sheets are all at node version 5 or later. Pin `--host` and `--org` when targeting a particular deployment or organization.
|
|
56
|
+
|
|
57
|
+
Use the document-import command for local files; it uploads them, registers them on the project, and publishes the generated drawing/specification files automatically:
|
|
45
58
|
|
|
46
59
|
```bash
|
|
47
|
-
specset
|
|
48
|
-
|
|
49
|
-
projectId: $projectId
|
|
50
|
-
cloudFileIds: [$f1, $f2]
|
|
51
|
-
autoImport: true
|
|
52
|
-
}) { id totalCount completedCount failedCount }
|
|
53
|
-
}' -F projectId=<project-id> -F f1=<cloud-file-id> -F f2=<cloud-file-id>
|
|
60
|
+
specset projects add-docs --project <project-id> ./drawings.pdf ./specifications.pdf --json
|
|
61
|
+
specset projects ingest-status --project <project-id> --wait --timeout 1800 --json
|
|
54
62
|
```
|
|
55
63
|
|
|
56
|
-
|
|
64
|
+
`add-docs` returns upload metadata and the background bulk action immediately. `ingest-status --wait` follows processing and publication; omit `--wait` for a snapshot. Processing extracts each document's outline and content, indexes it for search, and splits it into candidate spec files and drawing files by page range. The status command checks workflow completion and file publication; use drawing-element or graph tools to inspect content quality.
|
|
57
65
|
|
|
58
66
|
### `autoImport`: publish automatically or curate
|
|
59
67
|
|
|
60
68
|
- `autoImport: true` — every generated spec/drawing file is classified and published into default sets automatically. Use when the user wants everything live immediately.
|
|
61
|
-
-
|
|
69
|
+
- Pass `--noAutoImport` to `add-docs` — files land **unpromoted** for manual curation below. Use when the user wants to control set titles, membership, or ordering. The raw `createProjectDocuments` API defaults to unpromoted when `autoImport` is omitted.
|
|
62
70
|
|
|
63
71
|
Ask the user when their intent is ambiguous — this choice changes what gets published. The input also supports folders: `parentFolderId` / `newFolderName` for flat imports, or `folderTree` + `files` to mirror a directory structure — introspect `CreateProjectDocumentsInput` for those shapes.
|
|
64
72
|
|
|
@@ -98,6 +106,21 @@ updateDrawingSetPrecedence(projectId: ID!, drawingSetIds: [ID!]!): [DrawingSet!]
|
|
|
98
106
|
|
|
99
107
|
4. Verify and summarize — query `project(id)` (not the membership-filtered `projects` list) with `specSets { id title }` and `drawingSets { id title }`, and report what was created.
|
|
100
108
|
|
|
109
|
+
## Downloading Project Material
|
|
110
|
+
|
|
111
|
+
`specset projects hydrate` pulls a project's source material into a local directory so an agent (or a person) can read the PDFs directly instead of fetching sections one at a time:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
specset projects hydrate <projectId|link> --out ./pier-romeo # specs/, drawings/, docs/
|
|
115
|
+
specset projects hydrate <projectId|link> --out ./pier-romeo --include specs,drawings
|
|
116
|
+
specset projects hydrate <projectId|link> --json # default --out: ~/Specset/<host>/<project-name>-<projectId>/
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
- `specs/` holds one PDF per spec section (`<number> - <title>.pdf`), `drawings/` one PDF per drawing sheet (`<sheet> - <title>.pdf`, the rendered image for legacy sheets), and `docs/` the project's other documents (reports, permits, manuals). The spec book and drawing set PDFs themselves are not repeated under `docs/` — fetch a whole book with `specset specs download <ref> --asset book` when needed.
|
|
120
|
+
- Re-running is idempotent: files already present at the stored size are skipped, so run it again after new documents are processed to pick up only what changed.
|
|
121
|
+
- `--json` returns `{ projectId, out, files: [{ path, kind, ref, bytes, sha256 }], skipped, failures }`; `ref` is the public link of the source entity. **Cite that link, never the local path**, when reporting findings from a downloaded file.
|
|
122
|
+
- Large projects can be hundreds of files; start with `--include specs` when only the specifications matter. A non-zero exit means some downloads failed — re-run the same command to retry just those.
|
|
123
|
+
|
|
101
124
|
## Archiving and Deleting
|
|
102
125
|
|
|
103
126
|
- **Prefer `archiveProject(id: ID!)`** — reversible via `unarchiveProject(id: ID!)`. Archived projects drop out of default lists but keep all data.
|
|
@@ -108,3 +131,5 @@ updateDrawingSetPrecedence(projectId: ID!, drawingSetIds: [ID!]!): [DrawingSet!]
|
|
|
108
131
|
- Authorization error on a mutation — the user lacks that permission; the same rules as the UI apply. Surface the message, don't retry.
|
|
109
132
|
- A freshly created project "missing" from `projects` — that's the membership gotcha above, not a failure.
|
|
110
133
|
- A document reports a failed processing status on the BulkAction — report it to the user; re-uploading is their call.
|
|
134
|
+
|
|
135
|
+
Hydration records each file's Specset link, version id and checksum in `.specset/manifest.json`. Inside a local run's workspace (`specset agent serve` with **Native tools** on) the single `… download` commands record there too, and a version already present is not fetched again.
|
|
@@ -37,7 +37,22 @@ search(
|
|
|
37
37
|
At least one of `query` or `keywords` is required; they can be combined. Results:
|
|
38
38
|
|
|
39
39
|
```graphql
|
|
40
|
-
{
|
|
40
|
+
{
|
|
41
|
+
groups {
|
|
42
|
+
referenceType
|
|
43
|
+
totalCount
|
|
44
|
+
items {
|
|
45
|
+
id
|
|
46
|
+
url
|
|
47
|
+
title
|
|
48
|
+
previewText
|
|
49
|
+
score
|
|
50
|
+
projectId
|
|
51
|
+
projectName
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
nextOffset
|
|
55
|
+
}
|
|
41
56
|
```
|
|
42
57
|
|
|
43
58
|
### Project Scope (`ProjectScope`)
|
|
@@ -48,7 +63,7 @@ At least one of `query` or `keywords` is required; they can be combined. Results
|
|
|
48
63
|
|
|
49
64
|
### Record Types (`SourceReferenceType`)
|
|
50
65
|
|
|
51
|
-
Filter
|
|
66
|
+
Filter semantic `search` with the record types it materializes: `SpecSection`, `DrawingSheet`, `Document`, `Submittal`, and `Rfi`. Other values exist in the shared `SourceReferenceType` enum but are not necessarily supported by this operation.
|
|
52
67
|
|
|
53
68
|
## Quick Search: `quickSearch`
|
|
54
69
|
|
|
@@ -67,6 +82,8 @@ quickSearch(
|
|
|
67
82
|
|
|
68
83
|
Results: `{ items { id url number title referenceType score projectId projectName summary } totalCount }`
|
|
69
84
|
|
|
85
|
+
`quickSearch` also supports explicitly requested closeout title records: `Company`, `Location`, `System`, `Product`, `Asset`, and `MaintenancePlan`. It does not currently return `Warranty`, `Procedure`, or `WorkOrder` rows. `MaintenanceTask` is a deprecated legacy-link redirect, not a searchable record type. Omit `referenceTypes` for the standard global-search defaults, or introspect `SourceReferenceType` and use only a type supported by the selected operation.
|
|
86
|
+
|
|
70
87
|
## Precise Lookups
|
|
71
88
|
|
|
72
89
|
When the user hands you a section or sheet number, look it up directly:
|
|
@@ -90,15 +107,16 @@ Useful item fields: `id sectionNumber title numberAndTitle` on SpecSection, `id
|
|
|
90
107
|
```bash
|
|
91
108
|
specset api --query 'query($orgId: ID!) {
|
|
92
109
|
search(orgId: $orgId, keywords: ["AHU-1"],
|
|
93
|
-
referenceTypes: [Submittal
|
|
110
|
+
referenceTypes: [Submittal],
|
|
94
111
|
projectScope: MyProjects, limit: 20) {
|
|
95
112
|
groups { referenceType totalCount
|
|
96
|
-
items { url title previewText projectName } }
|
|
113
|
+
items { id url title previewText projectName } }
|
|
97
114
|
}
|
|
98
115
|
}' -F orgId=<org-id>
|
|
99
116
|
```
|
|
100
117
|
|
|
101
118
|
## Working With Results
|
|
102
119
|
|
|
103
|
-
- Each result's `url` is
|
|
120
|
+
- Each result's `id` is the UUID for follow-up GraphQL calls. Its `url` is the clickable source link (`https://app.specbook.ai/go/spec/<uuid>`, `https://app.specbook.ai/go/sub/<uuid>`, …) and can be passed directly into Specset tools and download commands.
|
|
121
|
+
- In user-facing answers, include the most relevant returned `url` values as descriptive Markdown source links so the user can open the result in Specset. Never synthesize a `/go` link from a UUID that was not returned as a source link.
|
|
104
122
|
- For follow-up work on what you found — updating submittals, answering RFIs, closeout records, or project/document changes — hand off to the `specset-submittals`, `specset-rfis`, `specset-closeout`, or `specset-projects` skill.
|