@stratta/mcp 0.15.0 → 1.16.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/README.md +34 -30
- package/dist/confirm.js +2 -1
- package/dist/index.js +2 -0
- package/dist/tools/catalog.gen.js +80 -2
- package/dist/tools/dossier.d.ts +60 -2
- package/dist/tools/dossier.js +61 -1
- package/dist/tools/library.d.ts +8 -0
- package/dist/tools/library.js +40 -0
- package/package.json +1 -1
- package/skills/consult-stratta/SKILL.md +10 -12
- package/skills/handoff-to-word/SKILL.md +41 -0
- package/skills/instruct-structure/SKILL.md +48 -0
- package/skills/project-basis/SKILL.md +89 -0
- package/skills/review-open-questions/SKILL.md +50 -0
- package/skills/site-chapter/SKILL.md +58 -0
- package/skills/use-agreement/SKILL.md +69 -0
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@ https://stratta.ch/mcp
|
|
|
34
34
|
That is the shorter path, the one the dashboard walks you through for Claude,
|
|
35
35
|
ChatGPT, Claude Code, Codex, Cursor, VS Code, Gemini CLI and Windsurf, and the
|
|
36
36
|
only one that works in an agent running in the cloud (claude.ai, ChatGPT). It
|
|
37
|
-
serves
|
|
37
|
+
serves 58 of the 59 tools below, **ingestion included**: the pre-pass script is
|
|
38
38
|
downloaded from https://stratta.ch/ingest-prepass.py when it is not on disk.
|
|
39
39
|
See https://stratta.ch/docs/en/guides/connect-remote.
|
|
40
40
|
|
|
@@ -176,8 +176,8 @@ named `E2E dossier <timestamp>` and does not delete it.
|
|
|
176
176
|
|
|
177
177
|
## Tools exposed
|
|
178
178
|
|
|
179
|
-
|
|
180
|
-
serves the same
|
|
179
|
+
59 tools, generated from one catalogue shared with the remote connector (which
|
|
180
|
+
serves the same 58, everything minus `add_attachment`).
|
|
181
181
|
|
|
182
182
|
**Read** (10 tools — query the norms of your workspace):
|
|
183
183
|
|
|
@@ -211,33 +211,37 @@ serves the same 54, everything minus `add_attachment`).
|
|
|
211
211
|
|
|
212
212
|
**Dossier** (25 tools — keep what was decided on a project, and everything the dossier page can do to a question):
|
|
213
213
|
|
|
214
|
-
| Tool | Purpose
|
|
215
|
-
| ---------------------- |
|
|
216
|
-
| `list_dossiers` | Your organisation's dossiers, most recently touched first, with open-question counts and site id.
|
|
217
|
-
| `open_dossier` | Open a project's dossier, creating it if needed. Idempotent on the name.
|
|
218
|
-
| `open_question` | Open one question to settle, with optional named options. Idempotent on the title.
|
|
219
|
-
| `save_finding` | Record one piece of evidence: a cited article, a retained value and why, an observation.
|
|
220
|
-
| `record_decision` | Settle a question with a decision the engineer has confirmed, and the retained option.
|
|
221
|
-
| `load_dossier` | Reload everything: questions with their evidence and decisions, open ones first.
|
|
222
|
-
| `resolve_question` | Close a question without a decision, or reopen one. The evidence stays.
|
|
223
|
-
| `list_attachments` | The project attachments of a dossier: site reports, borehole logs, minutes, data sheets.
|
|
224
|
-
| `read_attachment` | Read an attachment's text as Markdown, page by page.
|
|
225
|
-
| `search_in_dossier` | Full-text search over a dossier's attachments, with the page of each hit.
|
|
226
|
-
| `add_attachment` | Upload a file from the user's machine to a dossier (PDF, DOCX, XLSX, images, text). Local server only.
|
|
227
|
-
| `list_templates` | The checklists the organisation wrote for its types of structure.
|
|
228
|
-
| `apply_template` | Open a template's questions in a dossier and file the clauses that resolve in the corpus.
|
|
229
|
-
| `
|
|
230
|
-
| `
|
|
231
|
-
| `
|
|
232
|
-
| `
|
|
233
|
-
| `
|
|
234
|
-
| `
|
|
235
|
-
| `
|
|
236
|
-
| `
|
|
237
|
-
| `
|
|
238
|
-
| `
|
|
239
|
-
| `
|
|
240
|
-
| `
|
|
214
|
+
| Tool | Purpose |
|
|
215
|
+
| ---------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
216
|
+
| `list_dossiers` | Your organisation's dossiers, most recently touched first, with open-question counts and site id. |
|
|
217
|
+
| `open_dossier` | Open a project's dossier, creating it if needed. Idempotent on the name. |
|
|
218
|
+
| `open_question` | Open one question to settle, with optional named options. Idempotent on the title. |
|
|
219
|
+
| `save_finding` | Record one piece of evidence: a cited article, a retained value and why, an observation. |
|
|
220
|
+
| `record_decision` | Settle a question with a decision the engineer has confirmed, and the retained option. |
|
|
221
|
+
| `load_dossier` | Reload everything: questions with their evidence and decisions, open ones first. |
|
|
222
|
+
| `resolve_question` | Close a question without a decision, or reopen one. The evidence stays. |
|
|
223
|
+
| `list_attachments` | The project attachments of a dossier: site reports, borehole logs, minutes, data sheets. |
|
|
224
|
+
| `read_attachment` | Read an attachment's text as Markdown, page by page. |
|
|
225
|
+
| `search_in_dossier` | Full-text search over a dossier's attachments, with the page of each hit. |
|
|
226
|
+
| `add_attachment` | Upload a file from the user's machine to a dossier (PDF, DOCX, XLSX, images, text). Local server only. |
|
|
227
|
+
| `list_templates` | The checklists the organisation wrote for its types of structure. |
|
|
228
|
+
| `apply_template` | Open a template's questions in a dossier and file the clauses that resolve in the corpus. |
|
|
229
|
+
| `draft_deliverable` | Open the document a dossier produces (project basis, use agreement, report) and get its plan and sources. |
|
|
230
|
+
| `write_section` | Write one section of a deliverable with what it rests on; a section without a source is refused. |
|
|
231
|
+
| `list_skills` | The procedures the agent follows for a repeatable task: the ones Stratta ships and the ones the office wrote. |
|
|
232
|
+
| `get_skill` | Read one procedure in full; the office version wins over the Stratta one of the same name. |
|
|
233
|
+
| `list_questions` | The questions of a dossier, paginated, with status, assignee, due date, options and decision title. |
|
|
234
|
+
| `get_question` | One question in full: options, decision, evidence with every citation field, comments with authors. |
|
|
235
|
+
| `get_dossier_activity` | The history of a dossier, most recent first, paginated: who did what, from the app or an agent. |
|
|
236
|
+
| `list_exports` | The verification notes and journals exported from a dossier, with hash and trusted timestamp. |
|
|
237
|
+
| `update_question` | Reword a question, assign it by e-mail address, set or clear its due date. |
|
|
238
|
+
| `add_option` | Add one way of settling a question. Idempotent on the name. |
|
|
239
|
+
| `update_option` | Rename or describe an option, or mark it retained (the others are released). |
|
|
240
|
+
| `delete_option` | Remove an option; its evidence stays on the question. Asks the user first. |
|
|
241
|
+
| `delete_question` | Delete a question opened by mistake; its evidence stays, unfiled. Asks the user first. |
|
|
242
|
+
| `add_comment` | Leave a signed remark on a dossier, a question or an entry. |
|
|
243
|
+
| `update_entry` | Correct an entry's wording, value, confidence or citation in place. |
|
|
244
|
+
| `attach_entry` | File an entry under a question and optionally an option, or unfile it. |
|
|
241
245
|
|
|
242
246
|
A dossier is read, annotated, reviewed and exported from
|
|
243
247
|
[stratta.ch/dossiers](https://stratta.ch/dossiers).
|
package/dist/confirm.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const decisionSummary = (args) => [
|
|
2
|
+
args.question ? `${String(args.question)}:` : null,
|
|
2
3
|
args.title,
|
|
3
4
|
args.value ? `= ${String(args.value)}` : null,
|
|
4
5
|
args.retainedOption ? `(option ${String(args.retainedOption)})` : null,
|
|
@@ -32,7 +33,7 @@ export const CONFIRMED_TOOLS = {
|
|
|
32
33
|
summary: () => 'remove this option; the evidence filed under it stays on the question',
|
|
33
34
|
prompt: 'Remove it?',
|
|
34
35
|
},
|
|
35
|
-
// The third deletion, gated since
|
|
36
|
+
// The third deletion, gated since 1.15.0 on both transports: it is the one
|
|
36
37
|
// that empties a corpus rather than a dossier.
|
|
37
38
|
ingest_delete: {
|
|
38
39
|
what: 'Document',
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,7 @@ import { confirmWithUser } from './confirm.js';
|
|
|
12
12
|
import { readTools } from './tools/read.js';
|
|
13
13
|
import { ingestTools } from './tools/ingest.js';
|
|
14
14
|
import { dossierTools } from './tools/dossier.js';
|
|
15
|
+
import { libraryTools } from './tools/library.js';
|
|
15
16
|
import { siteTools } from './tools/site.js';
|
|
16
17
|
import { SESSION_ID, usageDigest } from './usage.js';
|
|
17
18
|
import { SERVER_INSTRUCTIONS } from './tools/catalog.gen.js';
|
|
@@ -107,6 +108,7 @@ for (const def of [
|
|
|
107
108
|
...readTools,
|
|
108
109
|
...siteTools,
|
|
109
110
|
...dossierTools,
|
|
111
|
+
...libraryTools,
|
|
110
112
|
...ingestTools,
|
|
111
113
|
]) {
|
|
112
114
|
server.registerTool(def.name, {
|
|
@@ -471,7 +471,7 @@ export const CATALOG = [
|
|
|
471
471
|
{
|
|
472
472
|
"name": "record_decision",
|
|
473
473
|
"title": "Record a decision",
|
|
474
|
-
"description": "
|
|
474
|
+
"description": "Record what the engineer retained: the decision in one line, why, and the clause it rests on. Pass questionId when the question already exists; otherwise pass dossierId and question (what is settled, in one line) and the question is opened on the spot, already decided. Name the retained option when the question listed some; put the number in value and set confidence when the decision is a value. Only after the user confirmed the decision, never on your own reasoning. Returns entryId.",
|
|
475
475
|
"annotations": {
|
|
476
476
|
"readOnlyHint": false,
|
|
477
477
|
"destructiveHint": false,
|
|
@@ -483,7 +483,9 @@ export const CATALOG = [
|
|
|
483
483
|
"remote"
|
|
484
484
|
],
|
|
485
485
|
"params": {
|
|
486
|
-
"questionId": "Question id returned by open_question or load_dossier.",
|
|
486
|
+
"questionId": "Question id returned by open_question or load_dossier, when the question exists.",
|
|
487
|
+
"dossierId": "Without questionId: the dossier the decision belongs to (open_dossier, load_dossier).",
|
|
488
|
+
"question": "Without questionId: what is settled, in one line (\"Friction angle of the moraine\"). The same words find the question already opened.",
|
|
487
489
|
"retainedOption": "The option that was retained, by the name it was given. An option not listed yet is created.",
|
|
488
490
|
"title": "The decision in one line, as it would be written in a report.",
|
|
489
491
|
"detail": "Why, in one or two sentences, and what it rests on.",
|
|
@@ -647,6 +649,82 @@ export const CATALOG = [
|
|
|
647
649
|
"templateId": "The template, from list_templates."
|
|
648
650
|
}
|
|
649
651
|
},
|
|
652
|
+
{
|
|
653
|
+
"name": "draft_deliverable",
|
|
654
|
+
"title": "Open a deliverable",
|
|
655
|
+
"description": "Open the document a dossier produces (project basis, use agreement, geotechnical report, verification note) and get its plan: one section per chapter, each with a path, a title, a hint of what belongs there, its state (gap, current, stale: a source moved, the reason says which) and an excerpt of what is already written. The plan is the office template of that kind when the organization validated one, otherwise the plan Stratta proposes. Also returns the decisions of the dossier with their ids, so write_section can cite them, and the site id when there is one. Calling it again on the same dossier and kind returns the same document, never a second one. Then read the skill of that kind (get_skill) and fill the sections with write_section.",
|
|
656
|
+
"annotations": {
|
|
657
|
+
"readOnlyHint": false,
|
|
658
|
+
"destructiveHint": false,
|
|
659
|
+
"idempotentHint": true,
|
|
660
|
+
"openWorldHint": false
|
|
661
|
+
},
|
|
662
|
+
"transports": [
|
|
663
|
+
"stdio",
|
|
664
|
+
"remote"
|
|
665
|
+
],
|
|
666
|
+
"params": {
|
|
667
|
+
"dossierId": "The dossier the document belongs to (open_dossier, load_dossier).",
|
|
668
|
+
"kind": "project_basis, use_agreement, geotechnical_report, verification_note or other.",
|
|
669
|
+
"title": "The document title, when the user named it. Default: the kind and the dossier name."
|
|
670
|
+
}
|
|
671
|
+
},
|
|
672
|
+
{
|
|
673
|
+
"name": "write_section",
|
|
674
|
+
"title": "Write a section",
|
|
675
|
+
"description": "Write one section of a deliverable: the text as it would be printed, and what it rests on. Every sentence of substance must come from a source the section lists: a decision or piece of evidence of the dossier (kind entry, ref the entry id), a fact of the site (kind fact, ref the fact key such as groundwater.level), a clause read in a norm (kind clause, ref the norm code and the section path as in \"SIA 267 s. 9.5.2\"), a page of an attachment (kind attachment, ref the id with #p12), or a reading recorded by the dossier (kind reading, ref the reading id). A section without a source is refused; when the dossier has nothing for it, pass gap true with a body that says what is missing, and the section is printed as something to establish. Replaces what the section held. Never invent a value: a section written from memory is worse than a gap.",
|
|
676
|
+
"annotations": {
|
|
677
|
+
"readOnlyHint": false,
|
|
678
|
+
"destructiveHint": false,
|
|
679
|
+
"idempotentHint": true,
|
|
680
|
+
"openWorldHint": false
|
|
681
|
+
},
|
|
682
|
+
"transports": [
|
|
683
|
+
"stdio",
|
|
684
|
+
"remote"
|
|
685
|
+
],
|
|
686
|
+
"params": {
|
|
687
|
+
"deliverableId": "The deliverable id from draft_deliverable.",
|
|
688
|
+
"path": "The section path from the plan, e.g. \"2\" or \"3.1\".",
|
|
689
|
+
"body": "The text of the section, plain prose or Markdown, up to 12000 characters.",
|
|
690
|
+
"sources": "What the text rests on: a list of {kind, ref, label?}. At least one unless gap is true.",
|
|
691
|
+
"gap": "true when the dossier holds nothing for this section; the body then says what is missing."
|
|
692
|
+
}
|
|
693
|
+
},
|
|
694
|
+
{
|
|
695
|
+
"name": "list_skills",
|
|
696
|
+
"title": "Skills of this workspace",
|
|
697
|
+
"description": "List the procedures an agent follows for a repeatable task: drafting the project basis or the use agreement, writing the terrain chapter of a report, instructing a type of structure, preparing a review, the verification note. Two sources: the skills Stratta ships and the ones this organization wrote; an organization skill with the same name replaces the Stratta one. Call it before drafting a document or starting such a task, then get_skill on the one that fits.",
|
|
698
|
+
"annotations": {
|
|
699
|
+
"readOnlyHint": true,
|
|
700
|
+
"destructiveHint": false,
|
|
701
|
+
"idempotentHint": true,
|
|
702
|
+
"openWorldHint": false
|
|
703
|
+
},
|
|
704
|
+
"transports": [
|
|
705
|
+
"stdio",
|
|
706
|
+
"remote"
|
|
707
|
+
],
|
|
708
|
+
"params": {}
|
|
709
|
+
},
|
|
710
|
+
{
|
|
711
|
+
"name": "get_skill",
|
|
712
|
+
"title": "Read a skill",
|
|
713
|
+
"description": "Read one skill in full: Markdown with its front matter (name, description) and its steps, rules and output shape. Follow it for the task at hand. The organization version wins over the Stratta version of the same name, because it carries the office plan and wording. Returns null when no skill has that name.",
|
|
714
|
+
"annotations": {
|
|
715
|
+
"readOnlyHint": true,
|
|
716
|
+
"destructiveHint": false,
|
|
717
|
+
"idempotentHint": true,
|
|
718
|
+
"openWorldHint": false
|
|
719
|
+
},
|
|
720
|
+
"transports": [
|
|
721
|
+
"stdio",
|
|
722
|
+
"remote"
|
|
723
|
+
],
|
|
724
|
+
"params": {
|
|
725
|
+
"name": "The skill name from list_skills, e.g. \"project-basis\"."
|
|
726
|
+
}
|
|
727
|
+
},
|
|
650
728
|
{
|
|
651
729
|
"name": "list_questions",
|
|
652
730
|
"title": "Questions of a dossier",
|
package/dist/tools/dossier.d.ts
CHANGED
|
@@ -47,7 +47,9 @@ export declare const recordDecision: import("./define.js").ToolDef<{
|
|
|
47
47
|
sectionPath: z.ZodOptional<z.ZodString>;
|
|
48
48
|
page: z.ZodOptional<z.ZodNumber>;
|
|
49
49
|
normEdition: z.ZodOptional<z.ZodString>;
|
|
50
|
-
questionId: z.ZodString
|
|
50
|
+
questionId: z.ZodOptional<z.ZodString>;
|
|
51
|
+
dossierId: z.ZodOptional<z.ZodString>;
|
|
52
|
+
question: z.ZodOptional<z.ZodString>;
|
|
51
53
|
retainedOption: z.ZodOptional<z.ZodString>;
|
|
52
54
|
}>;
|
|
53
55
|
export declare const loadDossier: import("./define.js").ToolDef<{
|
|
@@ -59,6 +61,34 @@ export declare const resolveQuestion: import("./define.js").ToolDef<{
|
|
|
59
61
|
resolved: z.ZodOptional<z.ZodBoolean>;
|
|
60
62
|
confirmed: z.ZodOptional<z.ZodBoolean>;
|
|
61
63
|
}>;
|
|
64
|
+
export declare const draftDeliverable: import("./define.js").ToolDef<{
|
|
65
|
+
dossierId: z.ZodString;
|
|
66
|
+
kind: z.ZodEnum<{
|
|
67
|
+
project_basis: "project_basis";
|
|
68
|
+
use_agreement: "use_agreement";
|
|
69
|
+
geotechnical_report: "geotechnical_report";
|
|
70
|
+
verification_note: "verification_note";
|
|
71
|
+
other: "other";
|
|
72
|
+
}>;
|
|
73
|
+
title: z.ZodOptional<z.ZodString>;
|
|
74
|
+
}>;
|
|
75
|
+
export declare const writeSection: import("./define.js").ToolDef<{
|
|
76
|
+
deliverableId: z.ZodString;
|
|
77
|
+
path: z.ZodString;
|
|
78
|
+
body: z.ZodString;
|
|
79
|
+
sources: z.ZodArray<z.ZodObject<{
|
|
80
|
+
kind: z.ZodEnum<{
|
|
81
|
+
entry: "entry";
|
|
82
|
+
fact: "fact";
|
|
83
|
+
clause: "clause";
|
|
84
|
+
attachment: "attachment";
|
|
85
|
+
reading: "reading";
|
|
86
|
+
}>;
|
|
87
|
+
ref: z.ZodString;
|
|
88
|
+
label: z.ZodOptional<z.ZodString>;
|
|
89
|
+
}, z.core.$strip>>;
|
|
90
|
+
gap: z.ZodOptional<z.ZodBoolean>;
|
|
91
|
+
}>;
|
|
62
92
|
export declare const listAttachments: import("./define.js").ToolDef<{
|
|
63
93
|
dossierId: z.ZodString;
|
|
64
94
|
}>;
|
|
@@ -201,7 +231,9 @@ export declare const dossierTools: (import("./define.js").ToolDef<{}> | import("
|
|
|
201
231
|
sectionPath: z.ZodOptional<z.ZodString>;
|
|
202
232
|
page: z.ZodOptional<z.ZodNumber>;
|
|
203
233
|
normEdition: z.ZodOptional<z.ZodString>;
|
|
204
|
-
questionId: z.ZodString
|
|
234
|
+
questionId: z.ZodOptional<z.ZodString>;
|
|
235
|
+
dossierId: z.ZodOptional<z.ZodString>;
|
|
236
|
+
question: z.ZodOptional<z.ZodString>;
|
|
205
237
|
retainedOption: z.ZodOptional<z.ZodString>;
|
|
206
238
|
}> | import("./define.js").ToolDef<{
|
|
207
239
|
dossierId: z.ZodOptional<z.ZodString>;
|
|
@@ -210,6 +242,32 @@ export declare const dossierTools: (import("./define.js").ToolDef<{}> | import("
|
|
|
210
242
|
questionId: z.ZodString;
|
|
211
243
|
resolved: z.ZodOptional<z.ZodBoolean>;
|
|
212
244
|
confirmed: z.ZodOptional<z.ZodBoolean>;
|
|
245
|
+
}> | import("./define.js").ToolDef<{
|
|
246
|
+
dossierId: z.ZodString;
|
|
247
|
+
kind: z.ZodEnum<{
|
|
248
|
+
project_basis: "project_basis";
|
|
249
|
+
use_agreement: "use_agreement";
|
|
250
|
+
geotechnical_report: "geotechnical_report";
|
|
251
|
+
verification_note: "verification_note";
|
|
252
|
+
other: "other";
|
|
253
|
+
}>;
|
|
254
|
+
title: z.ZodOptional<z.ZodString>;
|
|
255
|
+
}> | import("./define.js").ToolDef<{
|
|
256
|
+
deliverableId: z.ZodString;
|
|
257
|
+
path: z.ZodString;
|
|
258
|
+
body: z.ZodString;
|
|
259
|
+
sources: z.ZodArray<z.ZodObject<{
|
|
260
|
+
kind: z.ZodEnum<{
|
|
261
|
+
entry: "entry";
|
|
262
|
+
fact: "fact";
|
|
263
|
+
clause: "clause";
|
|
264
|
+
attachment: "attachment";
|
|
265
|
+
reading: "reading";
|
|
266
|
+
}>;
|
|
267
|
+
ref: z.ZodString;
|
|
268
|
+
label: z.ZodOptional<z.ZodString>;
|
|
269
|
+
}, z.core.$strip>>;
|
|
270
|
+
gap: z.ZodOptional<z.ZodBoolean>;
|
|
213
271
|
}> | import("./define.js").ToolDef<{
|
|
214
272
|
dossierId: z.ZodString;
|
|
215
273
|
}> | import("./define.js").ToolDef<{
|
package/dist/tools/dossier.js
CHANGED
|
@@ -127,7 +127,16 @@ export const saveFinding = defineTool({
|
|
|
127
127
|
export const recordDecision = defineTool({
|
|
128
128
|
...headOf('record_decision'),
|
|
129
129
|
inputSchema: {
|
|
130
|
-
|
|
130
|
+
// Either the question, or the dossier and what is settled: since 1.16.0
|
|
131
|
+
// a decision no longer needs a question opened beforehand.
|
|
132
|
+
questionId: questionId('record_decision').optional(),
|
|
133
|
+
dossierId: dossierId('record_decision').optional(),
|
|
134
|
+
question: z
|
|
135
|
+
.string()
|
|
136
|
+
.min(3)
|
|
137
|
+
.max(200)
|
|
138
|
+
.optional()
|
|
139
|
+
.describe(param('record_decision', 'question')),
|
|
131
140
|
retainedOption: z
|
|
132
141
|
.string()
|
|
133
142
|
.max(120)
|
|
@@ -188,6 +197,55 @@ export const resolveQuestion = defineTool({
|
|
|
188
197
|
return { ok: true };
|
|
189
198
|
},
|
|
190
199
|
});
|
|
200
|
+
/* ------------------------------------------------------------ deliverables */
|
|
201
|
+
const deliverableKind = z.enum([
|
|
202
|
+
'project_basis',
|
|
203
|
+
'use_agreement',
|
|
204
|
+
'geotechnical_report',
|
|
205
|
+
'verification_note',
|
|
206
|
+
'other',
|
|
207
|
+
]);
|
|
208
|
+
const sourceSchema = z.object({
|
|
209
|
+
kind: z.enum(['entry', 'fact', 'clause', 'attachment', 'reading']),
|
|
210
|
+
ref: z.string().min(1).max(120),
|
|
211
|
+
label: z.string().max(120).optional(),
|
|
212
|
+
});
|
|
213
|
+
export const draftDeliverable = defineTool({
|
|
214
|
+
...headOf('draft_deliverable'),
|
|
215
|
+
inputSchema: {
|
|
216
|
+
dossierId: dossierId('draft_deliverable'),
|
|
217
|
+
kind: deliverableKind.describe(param('draft_deliverable', 'kind')),
|
|
218
|
+
title: z
|
|
219
|
+
.string()
|
|
220
|
+
.max(160)
|
|
221
|
+
.optional()
|
|
222
|
+
.describe(param('draft_deliverable', 'title')),
|
|
223
|
+
},
|
|
224
|
+
run: (client, args) => client.action(api.dossiersApi.draftDeliverable, {
|
|
225
|
+
apiKey: requireApiKey(),
|
|
226
|
+
...args,
|
|
227
|
+
}),
|
|
228
|
+
});
|
|
229
|
+
export const writeSection = defineTool({
|
|
230
|
+
...headOf('write_section'),
|
|
231
|
+
inputSchema: {
|
|
232
|
+
deliverableId: z
|
|
233
|
+
.string()
|
|
234
|
+
.min(1)
|
|
235
|
+
.describe(param('write_section', 'deliverableId')),
|
|
236
|
+
path: z.string().min(1).max(20).describe(param('write_section', 'path')),
|
|
237
|
+
body: z.string().max(12_000).describe(param('write_section', 'body')),
|
|
238
|
+
sources: z
|
|
239
|
+
.array(sourceSchema)
|
|
240
|
+
.max(30)
|
|
241
|
+
.describe(param('write_section', 'sources')),
|
|
242
|
+
gap: z.boolean().optional().describe(param('write_section', 'gap')),
|
|
243
|
+
},
|
|
244
|
+
run: (client, args) => client.action(api.dossiersApi.writeSection, {
|
|
245
|
+
apiKey: requireApiKey(),
|
|
246
|
+
...args,
|
|
247
|
+
}),
|
|
248
|
+
});
|
|
191
249
|
const MIME_BY_EXT = {
|
|
192
250
|
'.pdf': 'application/pdf',
|
|
193
251
|
'.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
@@ -642,6 +700,8 @@ export const dossierTools = [
|
|
|
642
700
|
addAttachment,
|
|
643
701
|
listTemplates,
|
|
644
702
|
applyTemplate,
|
|
703
|
+
draftDeliverable,
|
|
704
|
+
writeSection,
|
|
645
705
|
listQuestions,
|
|
646
706
|
getQuestion,
|
|
647
707
|
getDossierActivity,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const listSkills: import("./define.js").ToolDef<{}>;
|
|
3
|
+
export declare const getSkill: import("./define.js").ToolDef<{
|
|
4
|
+
name: z.ZodString;
|
|
5
|
+
}>;
|
|
6
|
+
export declare const libraryTools: (import("./define.js").ToolDef<{}> | import("./define.js").ToolDef<{
|
|
7
|
+
name: z.ZodString;
|
|
8
|
+
}>)[];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { api } from '../client.js';
|
|
3
|
+
import { requireApiKey } from '../auth.js';
|
|
4
|
+
import { catalogEntry, param } from './catalog.gen.js';
|
|
5
|
+
import { defineTool } from './define.js';
|
|
6
|
+
/**
|
|
7
|
+
* The library: the procedures the agent follows for a repeatable task, the
|
|
8
|
+
* ones Stratta ships and the ones the office wrote (ADR 48). Served as tools
|
|
9
|
+
* so that every client reads them, whether or not it supports resources or
|
|
10
|
+
* installed the skills folder of this package.
|
|
11
|
+
*/
|
|
12
|
+
const headOf = (name) => {
|
|
13
|
+
const entry = catalogEntry(name);
|
|
14
|
+
return {
|
|
15
|
+
name,
|
|
16
|
+
title: entry.title,
|
|
17
|
+
description: entry.description,
|
|
18
|
+
annotations: entry.annotations,
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export const listSkills = defineTool({
|
|
22
|
+
...headOf('list_skills'),
|
|
23
|
+
inputSchema: {},
|
|
24
|
+
run: async (client) => ({
|
|
25
|
+
skills: await client.action(api.libraryApi.listSkills, {
|
|
26
|
+
apiKey: requireApiKey(),
|
|
27
|
+
}),
|
|
28
|
+
}),
|
|
29
|
+
});
|
|
30
|
+
export const getSkill = defineTool({
|
|
31
|
+
...headOf('get_skill'),
|
|
32
|
+
inputSchema: {
|
|
33
|
+
name: z.string().min(1).max(64).describe(param('get_skill', 'name')),
|
|
34
|
+
},
|
|
35
|
+
run: (client, args) => client.action(api.libraryApi.getSkill, {
|
|
36
|
+
apiKey: requireApiKey(),
|
|
37
|
+
name: args.name,
|
|
38
|
+
}),
|
|
39
|
+
});
|
|
40
|
+
export const libraryTools = [listSkills, getSkill];
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stratta/mcp",
|
|
3
3
|
"mcpName": "ch.stratta/mcp",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "1.16.0",
|
|
5
5
|
"description": "MCP server exposing the engineering norms your firm is licensed for (SIA / Eurocodes) to any MCP client, via Stratta TreeRAG.",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
7
|
"author": "SmartFlow <hello@stratta.ch>",
|
|
@@ -42,25 +42,23 @@ DEMO 001 is a fictional document shipped with Stratta so that navigation and cit
|
|
|
42
42
|
|
|
43
43
|
## Dossier
|
|
44
44
|
|
|
45
|
-
A conversation disappears, a project lasts months. The dossier is what remains: what was
|
|
45
|
+
A conversation disappears, a project lasts months. The dossier is what remains: what was read, what was retained, and what is still open. Keeping it costs the user nothing: every section you read is filed under the project by itself, and one call records a decision.
|
|
46
46
|
|
|
47
|
-
**
|
|
47
|
+
**Name the project once.** When the user names a project, a structure, a site or a mandate, call `list_dossiers` then `load_dossier` (or `open_dossier` for a new one) BEFORE answering. It reloads what was already decided so it is not decided twice, and from then on each `get_section` you make is journaled under that dossier without any further call. Do not open a dossier for a one-off lookup with no project behind it.
|
|
48
48
|
|
|
49
|
-
**
|
|
49
|
+
**Record what is retained** (`record_decision`) as soon as the user fixes a value or a choice for the design ("we take 30 degrees", "keep pile P38"): the decision in one line, why, the clause it rests on (`normCode`, `sectionPath`, `page`, `normEdition` from the header of the section read), the number in `value` with its unit and `confidence` (established, judgement or to_confirm; in geotechnics a retained value is a judgement). Pass `dossierId` and `question` (what is settled, in one line): the question is opened already decided. Pass `questionId` instead when the question exists. ONLY after the user confirmed it, never on your own reasoning.
|
|
50
|
+
|
|
51
|
+
**Open a question** (`open_question`) only when something is left to settle later, or when the user weighs several options and wants them on the table. File what backs it with `save_finding` (one clause, one value or one fact per call, under its `questionId`): reference, hypothesis or observation. `get_question` reads one in full; `update_question` edits it; never delete one unless the user says so.
|
|
50
52
|
|
|
51
53
|
**Read its attachments.** A dossier carries the project's own documents (site reports, borehole logs, meeting minutes): `list_attachments`, then `read_attachment` on what bears on the question, or `search_in_dossier` when the dossier holds many. A fact from a piece is evidence like a clause: cite it as [name, p. N] and file it with `attachmentId` and `attachmentPage`.
|
|
52
54
|
|
|
53
|
-
**Start from a template when one fits
|
|
55
|
+
**Start from a template when one fits** (`list_templates`, `apply_template`): the office's checklist for a type of structure opens the questions with the clauses they rest on, and says which clauses the corpus lacks.
|
|
54
56
|
|
|
55
|
-
**
|
|
57
|
+
**What not to write:** your own prose, the intermediate steps, anything the user did not treat as a decision. The dossier documents the engineer's reasoning; it does not replace it: never conclude that a structure complies, never write a decision the user has not confirmed.
|
|
56
58
|
|
|
57
|
-
|
|
58
|
-
- reference: what the norm says, with `normCode`, `sectionPath`, `page`, and `normEdition` taken from the header of the section read;
|
|
59
|
-
- hypothesis: the retained value AND the reasoning; in geotechnics a retained value is a judgement, not the output of a calculation;
|
|
60
|
-
- observation: what the site showed, with the date when known;
|
|
61
|
-
- decision (`record_decision`): what was decided, why, the clause it rests on and the retained option, ONLY after the user confirmed it.
|
|
59
|
+
## Skills
|
|
62
60
|
|
|
63
|
-
|
|
61
|
+
Before drafting a document (project basis, use agreement, terrain chapter, verification note) or starting a repeatable task (instructing a type of structure, preparing a review), call `list_skills` then `get_skill` on the one that fits, and follow it. The organization's own skill replaces Stratta's of the same name: it carries the office's plan and wording. When no skill fits, say so and proceed with the method above.
|
|
64
62
|
|
|
65
63
|
## Boundaries
|
|
66
64
|
|
|
@@ -70,4 +68,4 @@ A conversation disappears, a project lasts months. The dossier is what remains:
|
|
|
70
68
|
- Do not expose internal identifiers unless the next Stratta tool call requires them.
|
|
71
69
|
- Ingesting a new norm starts from a PDF on the user's own machine: it goes through the local `@stratta/mcp` server and its `ingest-norm` skill, never through the remote connector.
|
|
72
70
|
|
|
73
|
-
methodology:
|
|
71
|
+
methodology: v3
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: handoff-to-word
|
|
3
|
+
description: Hand a document drafted in the conversation to the office's Word template: clean Markdown with a stable heading plan, tables, citations and visible gaps, plus the two lines the person needs to paste it. Use only for a text that was not written with draft_deliverable, which the dossier page exports to Word itself. Trigger phrases: "mets-le en forme pour Word", "prepare pour le gabarit", "export pour Word", "paste into Word".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Handoff to Word
|
|
7
|
+
|
|
8
|
+
Use this skill when a document was drafted in the conversation (a terrain chapter, a
|
|
9
|
+
note) and the office wants it in its own Word template. A document written with
|
|
10
|
+
`draft_deliverable` and `write_section` does not need it: the dossier page exports it to
|
|
11
|
+
Word under Livrables, headings and sources included; tell the user so.
|
|
12
|
+
|
|
13
|
+
Do not use it to write the document: it formats one that exists.
|
|
14
|
+
|
|
15
|
+
## What to produce
|
|
16
|
+
|
|
17
|
+
1. The document as Markdown with a stable plan: `#` for the title, `##` for chapters
|
|
18
|
+
numbered as the office numbers them, `###` at most. No deeper level: Word templates
|
|
19
|
+
rarely style a fourth.
|
|
20
|
+
2. Tables as Markdown tables with a header row; one table per subject, no merged cells.
|
|
21
|
+
3. Provenance marks kept exactly as the source skill wrote them: `(#xxxxxx)` for dossier
|
|
22
|
+
entries, `[CODE section, p. N]` for clauses, `(fait: topic.key)` for site facts. They
|
|
23
|
+
are what the reviewer checks; a Word document without them is prose.
|
|
24
|
+
4. Gaps kept as `[A etablir : ...]`, `[A confirmer : ...]` or `[A convenir : ...]`, on
|
|
25
|
+
their own line when they replace a paragraph, so they show up in a search.
|
|
26
|
+
5. A final section **Sources** listing every clause cited with its edition and every
|
|
27
|
+
attachment cited with its page.
|
|
28
|
+
|
|
29
|
+
## Then tell the user, in two lines
|
|
30
|
+
|
|
31
|
+
- How to paste: in Word, paste as text, then apply the template's heading styles to the
|
|
32
|
+
`#` levels (or use the office's Markdown import when it has one).
|
|
33
|
+
- That the dossier page produces the verification note as a PDF, hashed and
|
|
34
|
+
timestamped, and that the two documents should agree.
|
|
35
|
+
|
|
36
|
+
## Rules
|
|
37
|
+
|
|
38
|
+
- Change nothing in the content: no rewording, no reordering, no gap filled.
|
|
39
|
+
- Keep the closing sentence of the source document ("Document prepare par un agent...").
|
|
40
|
+
- The office may have its own `handoff-to-word` skill (`list_skills`), for instance
|
|
41
|
+
with its heading numbering or its table style: it replaces this one.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: instruct-structure
|
|
3
|
+
description: Instruct a type of structure in a Stratta dossier (a bored pile, a retaining wall, a slope, a raft) by opening the questions it raises from the office's template or from the norm's own chapters, then gathering the clauses each one rests on, stopping short of any decision. Trigger phrases: "instruis", "prepare les questions pour", "checklist pour", "instruct the pile", "what do we need to settle for".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Instruct a type of structure
|
|
7
|
+
|
|
8
|
+
Use this skill when the user starts on a type of structure and wants the questions it
|
|
9
|
+
raises laid out with the clauses that govern them, before deciding anything: "instruis
|
|
10
|
+
le pieu P38", "qu'est-ce qu'on doit trancher pour ce mur de soutenement".
|
|
11
|
+
|
|
12
|
+
Do not use it to answer one technical question (that is the ordinary method) and do not
|
|
13
|
+
record decisions with it: it prepares the work, the engineer decides.
|
|
14
|
+
|
|
15
|
+
## Steps
|
|
16
|
+
|
|
17
|
+
1. `list_dossiers` then `load_dossier` (or `open_dossier` when the project is new). If
|
|
18
|
+
questions already cover the structure, do not open them twice: list what exists first.
|
|
19
|
+
2. `list_templates`. When a template matches the type of structure, `apply_template`: it
|
|
20
|
+
opens the questions with the clauses they rest on and says which clauses the corpus
|
|
21
|
+
lacks. Report both to the user and stop here unless the user asks for more.
|
|
22
|
+
3. Without a template: `get_toc` on the norm that governs the structure (SIA 267 for
|
|
23
|
+
geotechnics, SIA 262 for concrete, and so on, only if `list_norms` holds it), then
|
|
24
|
+
`get_subtree` on the chapter of the structure. Propose the questions, one per thing to
|
|
25
|
+
settle, in the user's words ("Quel angle de frottement retenir pour la moraine ?",
|
|
26
|
+
"Le pieu peut-il etre conserve ?"), and open them with `open_question` after the user
|
|
27
|
+
agreed on the list. Name the options when the chapter offers several methods.
|
|
28
|
+
4. For each question, read the clauses that govern it (`get_section`, follow resolvable
|
|
29
|
+
references) and file each as a `reference` with `save_finding`: the clause, its page,
|
|
30
|
+
its edition, one clause per call.
|
|
31
|
+
5. Summarise: the questions opened, the clauses filed, what the corpus does not hold, and
|
|
32
|
+
which question the user wants to work on first.
|
|
33
|
+
|
|
34
|
+
## Rules
|
|
35
|
+
|
|
36
|
+
- Open questions only with the user's agreement on the list; ten precise questions beat
|
|
37
|
+
one that bundles them.
|
|
38
|
+
- File clauses you read in this conversation, never from memory.
|
|
39
|
+
- Do not write a hypothesis, an observation or a decision here. The office may have its
|
|
40
|
+
own `instruct-structure` skill (`list_skills`): it replaces this one.
|
|
41
|
+
|
|
42
|
+
## Example
|
|
43
|
+
|
|
44
|
+
User: "instruis le mur de soutenement de la villa Morges". Agent: loads the dossier, finds
|
|
45
|
+
no template, reads the SIA 267 chapter on retaining structures, proposes six questions
|
|
46
|
+
(earth pressure model, drainage, bearing capacity of the base, sliding, overturning,
|
|
47
|
+
serviceability), opens them once the user agrees, files nine clauses, and reports that
|
|
48
|
+
the corpus does not hold the SIA 261 clause on traffic loads behind the wall.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: project-basis
|
|
3
|
+
description: Draft the project basis (base du projet, Projektbasis) required by SIA 260 clause 2.5 from a Stratta dossier and its site sheet, chapter by chapter, every statement traced to a decision, a site fact or a clause, every gap written as a gap. Trigger phrases: "redige la base du projet", "base du projet", "Projektbasis", "project basis".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Project basis (SIA 260 clause 2.5)
|
|
7
|
+
|
|
8
|
+
Use this skill when the user asks for the project basis of a structure, in any of its
|
|
9
|
+
names: base du projet, Projektbasis, project basis. The document states the conditions the
|
|
10
|
+
design rests on: the site, the actions, the retained values and the norms. Stratta holds
|
|
11
|
+
most of that matter already; the skill assembles it and shows what is missing.
|
|
12
|
+
|
|
13
|
+
Do not use it for the use agreement (convention d'utilisation, clause 2.2): that is the
|
|
14
|
+
`use-agreement` skill. Do not use it to decide anything: a gap stays a gap.
|
|
15
|
+
|
|
16
|
+
## Before writing
|
|
17
|
+
|
|
18
|
+
1. `list_skills`: if the office wrote its own `project-basis`, that version replaces this
|
|
19
|
+
one entirely. Read it with `get_skill` and follow it.
|
|
20
|
+
2. `list_dossiers` then `load_dossier` on the project. Read its decisions and its open
|
|
21
|
+
questions; `get_question` on any decision whose clause you need in full.
|
|
22
|
+
3. `get_site_context` on the dossier's site when it has one (`siteId` in `load_dossier`),
|
|
23
|
+
then `get_boreholes` when the terrain chapter needs them.
|
|
24
|
+
4. `get_toc("SIA 260", maxDepth: 2)` and read the clause on the project basis with
|
|
25
|
+
`get_section` when the corpus holds SIA 260. If it does not, say so once at the top of
|
|
26
|
+
the document and keep the chapter plan below.
|
|
27
|
+
|
|
28
|
+
## How to write it
|
|
29
|
+
|
|
30
|
+
The document lives in Stratta, not in the conversation:
|
|
31
|
+
|
|
32
|
+
1. `draft_deliverable` with the dossier id and `kind: "project_basis"`. It returns the
|
|
33
|
+
plan (the office template when one was validated, otherwise the plan below), the
|
|
34
|
+
decisions of the dossier with their entry ids, the open questions and the site id.
|
|
35
|
+
Calling it twice returns the same document.
|
|
36
|
+
2. For each section of the plan, `write_section` with the text and its sources. Every
|
|
37
|
+
sentence of substance rests on one of:
|
|
38
|
+
- a decision or piece of evidence: `{kind: "entry", ref: "<entryId>"}`;
|
|
39
|
+
- a site fact: `{kind: "fact", ref: "groundwater.level"}`;
|
|
40
|
+
- a clause you read in this conversation: `{kind: "clause", ref: "SIA 261 s. 16.2.1"}`;
|
|
41
|
+
- a page of an attachment: `{kind: "attachment", ref: "<id>#p12"}`.
|
|
42
|
+
A section with no source is refused. When the dossier holds nothing for a section,
|
|
43
|
+
call `write_section` with `gap: true` and a body that says what is missing and who
|
|
44
|
+
can supply it.
|
|
45
|
+
3. Tell the user the document is on the dossier page, under Livrables, where they read
|
|
46
|
+
it section by section, correct, and export it to Word. Do not paste the whole
|
|
47
|
+
document in the conversation; summarise what was written and list the gaps.
|
|
48
|
+
|
|
49
|
+
## The plan
|
|
50
|
+
|
|
51
|
+
Unless the office's own skill says otherwise:
|
|
52
|
+
|
|
53
|
+
1. **Objet et situation**: the structure, the address, the parcel, the mandate.
|
|
54
|
+
2. **Terrain de fondation**: one paragraph per site topic (geology, groundwater, hazards,
|
|
55
|
+
contamination, protection sectors, boreholes), built with the `site-chapter` skill's
|
|
56
|
+
rules: an `established` fact is a statement with its source and date; an `indicative`
|
|
57
|
+
fact is written as `[A confirmer : ...]`; an `uncovered` topic is `[A etablir : ...]`.
|
|
58
|
+
3. **Actions**: seismic zone and ground class, snow, wind, from the site facts that carry
|
|
59
|
+
a SIA 261 clause; each value with its clause and page.
|
|
60
|
+
4. **Hypotheses et valeurs retenues**: one line per decision of the dossier: the value,
|
|
61
|
+
its confidence (established, judgement, to confirm), the clause it rests on.
|
|
62
|
+
5. **Bases normatives**: the norms and editions cited in the dossier, one line each.
|
|
63
|
+
6. **Points ouverts**: the open questions, with their due date and assignee when set.
|
|
64
|
+
|
|
65
|
+
The text of a section is plain prose: the sources go in the `sources` argument, not in
|
|
66
|
+
the text. Stratta prints them under each section.
|
|
67
|
+
|
|
68
|
+
## Rules
|
|
69
|
+
|
|
70
|
+
- Write nothing the dossier, the site sheet or a clause you read does not carry. A
|
|
71
|
+
plausible sentence with no source is the one mistake this document cannot afford.
|
|
72
|
+
- A value retained by judgement stays a judgement in the text; do not upgrade it.
|
|
73
|
+
- A site fact is a register's answer, not a design value: it goes in chapter 2 or 3 with
|
|
74
|
+
its source, and the retained value goes in chapter 4 only if the dossier decided it.
|
|
75
|
+
- Do not conclude that the structure complies, and do not write a decision the user has
|
|
76
|
+
not confirmed.
|
|
77
|
+
- Stratta prints the closing sentence ("Document prepare par un agent...") and the
|
|
78
|
+
signature belongs to the engineer, on the dossier page. Do not sign anything.
|
|
79
|
+
|
|
80
|
+
## After drafting
|
|
81
|
+
|
|
82
|
+
List the gaps in one short table (chapter, what is missing, which tool or which person can
|
|
83
|
+
fill it), and ask which one to settle first. A gap settled later is written with
|
|
84
|
+
`write_section` on the same path; the document keeps its version history.
|
|
85
|
+
|
|
86
|
+
When the user comes back and `draft_deliverable` returns sections in state `stale`, start
|
|
87
|
+
with those: `staleReason` says which source moved (a decision retaken, a fact changed by a
|
|
88
|
+
rescan, a clause changed by a new edition). Reread the source, rewrite the section or tell
|
|
89
|
+
the user it still holds.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: review-open-questions
|
|
3
|
+
description: Prepare the review of a Stratta dossier for the senior engineer: what is decided and on what, what is still open with its due date, which values are marked to confirm, in one brief that proposes nothing new. Trigger phrases: "prepare la revue", "ou en est le dossier", "qu'est-ce qui reste a trancher", "brief pour le chef de projet", "review the dossier".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Review of the open questions
|
|
7
|
+
|
|
8
|
+
Use this skill when someone is about to review a dossier: the project lead before a
|
|
9
|
+
meeting, the senior engineer before signing, the colleague who picks the project up.
|
|
10
|
+
The brief tells them what was retained, on what it rests, and what is still open, in
|
|
11
|
+
the order they need to read it.
|
|
12
|
+
|
|
13
|
+
Do not use it to decide, to propose values or to reopen questions: a review reads first.
|
|
14
|
+
|
|
15
|
+
## Steps
|
|
16
|
+
|
|
17
|
+
1. `list_dossiers` then `load_dossier`; `list_questions` with `status: "open"` when the
|
|
18
|
+
dossier is large; `get_question` on each open question that has evidence, to read
|
|
19
|
+
its options and what backs them.
|
|
20
|
+
2. `get_dossier_activity` for what changed since the last review, when the user names a
|
|
21
|
+
date or the dossier has been worked on by several people.
|
|
22
|
+
3. Write the brief.
|
|
23
|
+
|
|
24
|
+
## What to produce
|
|
25
|
+
|
|
26
|
+
Markdown, in the user's language, four parts, short:
|
|
27
|
+
|
|
28
|
+
1. **Etat**: the dossier name, its status, the counts (open, decided, closed), the site
|
|
29
|
+
when there is one.
|
|
30
|
+
2. **A trancher**: one line per open question, ordered by due date then by how much
|
|
31
|
+
backs it: the question, its assignee, its due date, the options on the table, what is
|
|
32
|
+
filed (n references, n hypotheses, n observations), and what is missing to settle
|
|
33
|
+
it. A question with no evidence is marked as such.
|
|
34
|
+
3. **Retenu**: one line per decision: what was decided, the value with its confidence,
|
|
35
|
+
the clause it rests on `[CODE section, p. N]`, who confirmed it and when. Values marked
|
|
36
|
+
`to_confirm` are listed apart, with what would confirm them.
|
|
37
|
+
4. **Depuis la derniere revue**: the changes, when step 2 was run.
|
|
38
|
+
|
|
39
|
+
Every line ends with `(#xxxxxx)` when it rests on an entry.
|
|
40
|
+
|
|
41
|
+
## Rules
|
|
42
|
+
|
|
43
|
+
- Read, do not judge: no opinion on a decision, no new option, no value proposed.
|
|
44
|
+
- A gap is named as a gap; the reviewer's job is to see them, not to be spared them.
|
|
45
|
+
- The office may have its own `review-open-questions` skill (`list_skills`): it replaces
|
|
46
|
+
this one.
|
|
47
|
+
|
|
48
|
+
## After the brief
|
|
49
|
+
|
|
50
|
+
Ask which open question to work on first, and only then switch to the ordinary method.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: site-chapter
|
|
3
|
+
description: Write the terrain chapter of a report (situation, geology, groundwater, boreholes, hazards, constraints) from a Stratta site sheet, one sentence per fact with its source and date, register answers kept apart from design values. Trigger phrases: "chapitre terrain", "chapitre situation", "decris le site", "site chapter", "conditions du terrain".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Terrain chapter
|
|
7
|
+
|
|
8
|
+
Use this skill when the user needs the part of a report that describes the site: the
|
|
9
|
+
geotechnical report's situation chapter, the terrain chapter of a project basis, the
|
|
10
|
+
site paragraph of an offer. The site sheet already holds what the public registers say,
|
|
11
|
+
with a source and a date on each fact; the chapter is that sheet, written in prose,
|
|
12
|
+
without adding a single value.
|
|
13
|
+
|
|
14
|
+
Do not use it to interpret the ground (a retained soil parameter is a decision of the
|
|
15
|
+
dossier, not a fact of the sheet), and do not use it when the dossier has no site: say
|
|
16
|
+
so and offer `scan_site`.
|
|
17
|
+
|
|
18
|
+
## Before writing
|
|
19
|
+
|
|
20
|
+
1. `list_skills`: an office version named `site-chapter` replaces this one.
|
|
21
|
+
2. `load_dossier`, then `get_site_context` on its `siteId`. When the chapter needs the
|
|
22
|
+
boreholes, `get_boreholes` (nearest first; `withStrataOnly` when only logged strata
|
|
23
|
+
matter).
|
|
24
|
+
|
|
25
|
+
## What to produce
|
|
26
|
+
|
|
27
|
+
Markdown, in the user's language, ordered as the sheet is: situation (address, parcel,
|
|
28
|
+
elevation), geology, boreholes and groundwater, natural hazards, contamination and water
|
|
29
|
+
protection, other constraints (noise, radon, zoning, forest), actions (seismic zone and
|
|
30
|
+
ground class, snow, wind).
|
|
31
|
+
|
|
32
|
+
One sentence per fact, then its provenance in brackets: the register that answered, the
|
|
33
|
+
date of the answer, and the clause when the fact carries one:
|
|
34
|
+
|
|
35
|
+
- `established`: state it. "La parcelle repose sur des alluvions recentes (cadastre
|
|
36
|
+
geologique VD, 2026-09-14)."
|
|
37
|
+
- `indicative`: state it with the reserve the register itself puts on it, and mark
|
|
38
|
+
`[A confirmer]`. "La classe de sol de fondation indiquee par la carte est C, carte non
|
|
39
|
+
precise a l'echelle de la parcelle (SIA 261 §16.2, p. 51) [A confirmer par sondage]."
|
|
40
|
+
- `uncovered`: say the register did not answer, in one line, marked `[A etablir]`.
|
|
41
|
+
|
|
42
|
+
For boreholes: their number in the radius, the nearest with its distance and depth, how
|
|
43
|
+
many have logged strata, the measured water levels with their dates. No interpolation
|
|
44
|
+
between boreholes: the sheet's cross-section is an interpretation and says so.
|
|
45
|
+
|
|
46
|
+
## Rules
|
|
47
|
+
|
|
48
|
+
- A fact of the sheet is a register's answer. It never becomes a design value in this
|
|
49
|
+
chapter; if the dossier retained one, cite the decision `(#xxxxxx)` in a separate
|
|
50
|
+
sentence.
|
|
51
|
+
- Keep the date. A fact without its date reads as permanent, and a cadastre changes.
|
|
52
|
+
- Do not complete a missing topic from general knowledge of the region.
|
|
53
|
+
- Do not conclude on the feasibility of the structure.
|
|
54
|
+
|
|
55
|
+
## After drafting
|
|
56
|
+
|
|
57
|
+
Name the `[A etablir]` and `[A confirmer]` items in one list, with what would settle each
|
|
58
|
+
(a borehole, a cantonal request, a site visit).
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: use-agreement
|
|
3
|
+
description: Draft the use agreement (convention d'utilisation, Nutzungsvereinbarung) required by SIA 260 clause 2.2 from a Stratta dossier, as a document the owner and the engineer sign together, every requirement traced to a decision and every open point left visible. Trigger phrases: "convention d'utilisation", "Nutzungsvereinbarung", "use agreement".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Use agreement (SIA 260 clause 2.2)
|
|
7
|
+
|
|
8
|
+
Use this skill when the user asks for the use agreement of a structure: the document in
|
|
9
|
+
which the owner and the engineer agree on what the structure is for, how long, under
|
|
10
|
+
which requirements and with which risks accepted. It is written in the owner's language,
|
|
11
|
+
for the owner to read and sign; the engineer keeps the technical basis in the project
|
|
12
|
+
basis (`project-basis` skill).
|
|
13
|
+
|
|
14
|
+
Do not use it to draft the project basis, and do not fill a requirement the owner has
|
|
15
|
+
not stated: an open point in this document is a question for the next meeting, not a
|
|
16
|
+
default.
|
|
17
|
+
|
|
18
|
+
## Before writing
|
|
19
|
+
|
|
20
|
+
1. `list_skills`: an office version named `use-agreement` replaces this one; read it with
|
|
21
|
+
`get_skill` and follow it.
|
|
22
|
+
2. `list_dossiers` then `load_dossier`. The decisions that concern use (service life,
|
|
23
|
+
categories of use, loads the owner asked for, tolerances, special risks) are the
|
|
24
|
+
matter; the open questions are the points to raise with the owner.
|
|
25
|
+
3. `get_toc("SIA 260", maxDepth: 2)` and read the clause on the use agreement with
|
|
26
|
+
`get_section` when the corpus holds SIA 260; otherwise say so once and keep the plan.
|
|
27
|
+
|
|
28
|
+
## How to write it
|
|
29
|
+
|
|
30
|
+
The document lives in Stratta: `draft_deliverable` with the dossier id and
|
|
31
|
+
`kind: "use_agreement"` returns the plan (the office template when one was validated)
|
|
32
|
+
and the decisions with their ids; then one `write_section` per section, each with its
|
|
33
|
+
sources (`{kind: "entry", ref: <entryId>}` for a decision, `{kind: "fact", ref: ...}`
|
|
34
|
+
for a site fact). A requirement the owner has not stated is a `write_section` with
|
|
35
|
+
`gap: true` and a body that names the point to agree. Tell the user the document is on
|
|
36
|
+
the dossier page under Livrables; do not paste it in the conversation.
|
|
37
|
+
|
|
38
|
+
## The plan
|
|
39
|
+
|
|
40
|
+
In the user's language, unless the office's own skill says otherwise:
|
|
41
|
+
|
|
42
|
+
1. **Objet**: the structure and the parties.
|
|
43
|
+
2. **Objectifs d'utilisation**: what the structure is for, its service life category,
|
|
44
|
+
the uses foreseen.
|
|
45
|
+
3. **Exigences d'utilisation**: the requirements the owner sets (loads, deformations,
|
|
46
|
+
vibrations, appearance, durability), each as one line.
|
|
47
|
+
4. **Environnement et conditions**: what the site imposes, in plain words, from the site
|
|
48
|
+
sheet when there is one (`get_site_context`): hazards, groundwater, contamination.
|
|
49
|
+
5. **Risques acceptes et mesures**: what the owner accepts and what is done about it.
|
|
50
|
+
6. **Points a convenir**: everything above that the dossier does not settle, as a list
|
|
51
|
+
the two parties go through together.
|
|
52
|
+
|
|
53
|
+
The text is plain prose; the sources go in the `sources` argument. A point to agree is
|
|
54
|
+
a gap, printed as such.
|
|
55
|
+
|
|
56
|
+
## Rules
|
|
57
|
+
|
|
58
|
+
- Plain language: the owner is not an engineer. Keep clause references for the project
|
|
59
|
+
basis; here, name the norm once in a footnote.
|
|
60
|
+
- No requirement invented to look complete. A short agreement with visible gaps is worth
|
|
61
|
+
more than a full one the owner did not agree to.
|
|
62
|
+
- Do not conclude on compliance; do not write a decision the user has not confirmed.
|
|
63
|
+
- The last section ends with the two signature lines (owner, engineer). Stratta prints
|
|
64
|
+
the closing sentence; the signature is the parties', on paper.
|
|
65
|
+
|
|
66
|
+
## After drafting
|
|
67
|
+
|
|
68
|
+
List the points to agree in one table and propose them as questions to open in the
|
|
69
|
+
dossier (`open_question`), only if the user says so.
|