@intentius/chant 0.109.0 → 0.111.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/dist/cli/main.d.ts.map +1 -1
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/discovery/param-deps.d.ts +30 -2
- package/dist/discovery/param-deps.d.ts.map +1 -1
- package/dist/fold/subset.d.ts +9 -2
- package/dist/fold/subset.d.ts.map +1 -1
- package/dist/fold-provenance.d.ts +14 -2
- package/dist/fold-provenance.d.ts.map +1 -1
- package/dist/import/ir-utils.d.ts.map +1 -1
- package/dist/import/parser.d.ts +8 -0
- package/dist/import/parser.d.ts.map +1 -1
- package/dist/op/activities/factory.d.ts.map +1 -1
- package/dist/provenance.d.ts +11 -0
- package/dist/provenance.d.ts.map +1 -1
- package/dist/serializer-walker.d.ts.map +1 -1
- package/dist/stack-output.d.ts +5 -0
- package/dist/stack-output.d.ts.map +1 -1
- package/dist/workspace/box-cli.d.ts +3 -2
- package/dist/workspace/box-cli.d.ts.map +1 -1
- package/dist/workspace/box-factory-write.d.ts +71 -0
- package/dist/workspace/box-factory-write.d.ts.map +1 -0
- package/dist/workspace/box-intent.d.ts +6 -0
- package/dist/workspace/box-intent.d.ts.map +1 -1
- package/dist/workspace/declaration-write-cli.d.ts +11 -0
- package/dist/workspace/declaration-write-cli.d.ts.map +1 -0
- package/dist/workspace/declaration-write.d.ts +78 -0
- package/dist/workspace/declaration-write.d.ts.map +1 -0
- package/dist/workspace/declaration.d.ts +8 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/json-edit.d.ts +11 -0
- package/dist/workspace/json-edit.d.ts.map +1 -1
- package/dist/workspace/ls.d.ts +8 -0
- package/dist/workspace/ls.d.ts.map +1 -1
- package/dist/workspace/reason-codes.d.ts +4 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/status.d.ts.map +1 -1
- package/dist/workspace/write-scope.d.ts +10 -0
- package/dist/workspace/write-scope.d.ts.map +1 -1
- package/dist/yaml.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cli/commands/import.test.ts +5 -4
- package/src/cli/main.test.ts +2 -0
- package/src/cli/main.ts +18 -0
- package/src/discovery/fold-composite.test.ts +22 -0
- package/src/discovery/fold-host-composite.test.ts +23 -0
- package/src/discovery/fold-import.ts +73 -21
- package/src/discovery/fold-project-provenance.test.ts +52 -0
- package/src/discovery/param-deps.test.ts +43 -2
- package/src/discovery/param-deps.ts +101 -2
- package/src/fold/subset.ts +9 -2
- package/src/fold-provenance.test.ts +11 -0
- package/src/fold-provenance.ts +22 -2
- package/src/import/ir-utils.ts +6 -1
- package/src/import/parser.ts +8 -0
- package/src/op/activities/factory.ts +3 -1
- package/src/op/factory.e2e.test.ts +3 -1
- package/src/provenance.ts +13 -1
- package/src/serializer-walker.test.ts +10 -0
- package/src/serializer-walker.ts +17 -1
- package/src/stack-output.ts +6 -1
- package/src/workspace/box-cli.ts +35 -4
- package/src/workspace/box-factory-write.schema.json +342 -0
- package/src/workspace/box-factory-write.test.ts +108 -0
- package/src/workspace/box-factory-write.ts +226 -0
- package/src/workspace/box-intent.test.ts +14 -4
- package/src/workspace/box-intent.ts +9 -1
- package/src/workspace/declaration-extensions.test.ts +79 -0
- package/src/workspace/declaration-write-cli.ts +82 -0
- package/src/workspace/declaration-write.test.ts +155 -0
- package/src/workspace/declaration-write.ts +275 -0
- package/src/workspace/declaration.ts +19 -1
- package/src/workspace/json-edit.ts +71 -0
- package/src/workspace/ls-contract.test.ts +53 -0
- package/src/workspace/ls.schema.json +11 -0
- package/src/workspace/ls.ts +18 -0
- package/src/workspace/member-write.schema.json +193 -0
- package/src/workspace/reason-codes.test.ts +4 -0
- package/src/workspace/reason-codes.ts +6 -0
- package/src/workspace/status.schema.json +10 -1
- package/src/workspace/status.ts +25 -6
- package/src/workspace/write-scope.ts +17 -0
- package/src/yaml.test.ts +6 -0
- package/src/yaml.ts +4 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://intentius.io/chant/schemas/workspace/member-write/v1/member-write.schema.json",
|
|
4
|
+
"title": "chant workspace member add|remove and host set output",
|
|
5
|
+
"description": "What `chant workspace member add <name> --from <file|->`, `member remove <name>` and `host set <name> --from <file|->` print (#3596): the entry before and after the write and the file it changed, or the reason it wrote nothing. Each write changes one entry of members or hosts in the declaration, in place, keeping the file's formatting and comments, and never commits. Readers ignore fields they do not know; a field is only ever added within a version. The error codes are a closed list, each in the one closed list of `reason-codes.ts`. Contract version 1 of this document is written by chant 0.110.0 and newer.",
|
|
6
|
+
"oneOf": [
|
|
7
|
+
{
|
|
8
|
+
"$ref": "#/$defs/result"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"$ref": "#/$defs/failure"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"$defs": {
|
|
15
|
+
"result": {
|
|
16
|
+
"description": "The entry was written, or would be with --dry-run, or the declaration already held it (changed false). Exit code 0.",
|
|
17
|
+
"type": "object",
|
|
18
|
+
"required": [
|
|
19
|
+
"$schema",
|
|
20
|
+
"contract",
|
|
21
|
+
"chant",
|
|
22
|
+
"action",
|
|
23
|
+
"name",
|
|
24
|
+
"declaration",
|
|
25
|
+
"paths",
|
|
26
|
+
"changed",
|
|
27
|
+
"dryRun",
|
|
28
|
+
"previous",
|
|
29
|
+
"entry"
|
|
30
|
+
],
|
|
31
|
+
"properties": {
|
|
32
|
+
"$schema": {
|
|
33
|
+
"const": "https://intentius.io/chant/schemas/workspace/member-write/v1/member-write.schema.json"
|
|
34
|
+
},
|
|
35
|
+
"contract": {
|
|
36
|
+
"const": 1
|
|
37
|
+
},
|
|
38
|
+
"chant": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"description": "The chant that wrote it."
|
|
41
|
+
},
|
|
42
|
+
"action": {
|
|
43
|
+
"enum": [
|
|
44
|
+
"member add",
|
|
45
|
+
"member remove",
|
|
46
|
+
"host set"
|
|
47
|
+
]
|
|
48
|
+
},
|
|
49
|
+
"name": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"description": "The member's or host's name."
|
|
52
|
+
},
|
|
53
|
+
"declaration": {
|
|
54
|
+
"type": "object",
|
|
55
|
+
"required": [
|
|
56
|
+
"path",
|
|
57
|
+
"sha256"
|
|
58
|
+
],
|
|
59
|
+
"properties": {
|
|
60
|
+
"path": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"description": "The declaration file, relative to the repository root (the working directory outside git), with / separators."
|
|
63
|
+
},
|
|
64
|
+
"sha256": {
|
|
65
|
+
"type": "string",
|
|
66
|
+
"pattern": "^[0-9a-f]{64}$",
|
|
67
|
+
"description": "The sha256 of the declaration's bytes after the write, or as they would be with --dry-run."
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"paths": {
|
|
72
|
+
"type": "array",
|
|
73
|
+
"items": {
|
|
74
|
+
"type": "string"
|
|
75
|
+
},
|
|
76
|
+
"description": "The declaration, relative to the repository root, when the write changed it or would with --dry-run; empty when it already held what was given."
|
|
77
|
+
},
|
|
78
|
+
"changed": {
|
|
79
|
+
"type": "boolean",
|
|
80
|
+
"description": "Whether the declaration changed: paths is not empty."
|
|
81
|
+
},
|
|
82
|
+
"dryRun": {
|
|
83
|
+
"type": "boolean",
|
|
84
|
+
"description": "True when --dry-run was given: nothing was written, and the document says what would have been."
|
|
85
|
+
},
|
|
86
|
+
"previous": {
|
|
87
|
+
"oneOf": [
|
|
88
|
+
{
|
|
89
|
+
"type": "null"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"type": "object"
|
|
93
|
+
}
|
|
94
|
+
],
|
|
95
|
+
"description": "The entry before the write, as the declaration held it, x- keys included; null when member add or host set adds a new one."
|
|
96
|
+
},
|
|
97
|
+
"entry": {
|
|
98
|
+
"oneOf": [
|
|
99
|
+
{
|
|
100
|
+
"type": "null"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"type": "object",
|
|
104
|
+
"required": [
|
|
105
|
+
"name"
|
|
106
|
+
],
|
|
107
|
+
"properties": {
|
|
108
|
+
"name": {
|
|
109
|
+
"type": "string"
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
],
|
|
114
|
+
"description": "The entry after the write, as the declaration holds it, with name first; null after member remove."
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"failure": {
|
|
119
|
+
"type": "object",
|
|
120
|
+
"description": "Nothing was written. Exit code 1.",
|
|
121
|
+
"required": [
|
|
122
|
+
"$schema",
|
|
123
|
+
"contract",
|
|
124
|
+
"chant",
|
|
125
|
+
"action",
|
|
126
|
+
"name",
|
|
127
|
+
"error"
|
|
128
|
+
],
|
|
129
|
+
"properties": {
|
|
130
|
+
"$schema": {
|
|
131
|
+
"const": "https://intentius.io/chant/schemas/workspace/member-write/v1/member-write.schema.json"
|
|
132
|
+
},
|
|
133
|
+
"contract": {
|
|
134
|
+
"const": 1
|
|
135
|
+
},
|
|
136
|
+
"chant": {
|
|
137
|
+
"type": "string"
|
|
138
|
+
},
|
|
139
|
+
"action": {
|
|
140
|
+
"enum": [
|
|
141
|
+
"member add",
|
|
142
|
+
"member remove",
|
|
143
|
+
"host set"
|
|
144
|
+
]
|
|
145
|
+
},
|
|
146
|
+
"name": {
|
|
147
|
+
"type": [
|
|
148
|
+
"string",
|
|
149
|
+
"null"
|
|
150
|
+
]
|
|
151
|
+
},
|
|
152
|
+
"error": {
|
|
153
|
+
"type": "object",
|
|
154
|
+
"required": [
|
|
155
|
+
"code",
|
|
156
|
+
"message"
|
|
157
|
+
],
|
|
158
|
+
"properties": {
|
|
159
|
+
"code": {
|
|
160
|
+
"enum": [
|
|
161
|
+
"declaration-missing",
|
|
162
|
+
"declaration-ambiguous",
|
|
163
|
+
"declaration-unparseable",
|
|
164
|
+
"declaration-invalid",
|
|
165
|
+
"placement-invalid",
|
|
166
|
+
"reader-too-old",
|
|
167
|
+
"root-chant-required",
|
|
168
|
+
"not-a-git-repository",
|
|
169
|
+
"revision-unknown",
|
|
170
|
+
"write-usage-invalid",
|
|
171
|
+
"write-input-invalid",
|
|
172
|
+
"member-exists",
|
|
173
|
+
"member-unknown",
|
|
174
|
+
"box-isolation-collision",
|
|
175
|
+
"box-isolation-literal",
|
|
176
|
+
"write-scope-member",
|
|
177
|
+
"write-scope-protected",
|
|
178
|
+
"write-scope-class-unknown",
|
|
179
|
+
"agent-unknown",
|
|
180
|
+
"principal-unidentified",
|
|
181
|
+
"write-lock-timeout",
|
|
182
|
+
"write-lock-not-held"
|
|
183
|
+
]
|
|
184
|
+
},
|
|
185
|
+
"message": {
|
|
186
|
+
"type": "string"
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
@@ -40,7 +40,9 @@ import { PATCH_ERROR_CODES } from "./patch";
|
|
|
40
40
|
import { AGENT_ERROR_CODES } from "./agent-cli";
|
|
41
41
|
import { SCOPE_FINDING_CODES, WRITE_SCOPE_CODES } from "./write-scope";
|
|
42
42
|
import { PLANTABLE_REASON_CODES } from "./box-factory";
|
|
43
|
+
import { BOX_FACTORY_ERROR_CODES } from "./box-factory-write";
|
|
43
44
|
import { BOX_LISTING_ERROR_CODES } from "./box-listing";
|
|
45
|
+
import { DECLARATION_WRITE_ERROR_CODES } from "./declaration-write";
|
|
44
46
|
import { BOX_PUBLISH_ERROR_CODES } from "./box-publish";
|
|
45
47
|
import { WRITE_LOCK_ERROR_CODES } from "./write-lock-cli";
|
|
46
48
|
import { WIP_ERROR_CODES, WIP_WRITE_ERROR_CODES } from "./wip";
|
|
@@ -108,6 +110,8 @@ const PER_COMMAND: Record<string, readonly string[]> = {
|
|
|
108
110
|
SCOPE_FINDING_CODES,
|
|
109
111
|
PLANTABLE_REASON_CODES,
|
|
110
112
|
BOX_LISTING_ERROR_CODES,
|
|
113
|
+
DECLARATION_WRITE_ERROR_CODES,
|
|
114
|
+
BOX_FACTORY_ERROR_CODES,
|
|
111
115
|
BOX_PUBLISH_ERROR_CODES,
|
|
112
116
|
WRITE_LOCK_ERROR_CODES,
|
|
113
117
|
WIP_ERROR_CODES,
|
|
@@ -260,6 +260,12 @@ export const REASONS = {
|
|
|
260
260
|
"listing-member-unknown": "box listing set names a member the declaration does not declare.",
|
|
261
261
|
"listing-box-missing": "box listing set names a member whose entry declares no box block, so it has no listing.",
|
|
262
262
|
"listing-cover-invalid": "The cover can't be read, is not a PNG, JPEG or WebP picture, is larger than 5 MiB, has a path outside the workspace, or has an extension other than its picture format's.",
|
|
263
|
+
// A declaration's members and hosts written through chant (member add|remove, host set, #3596): why the write was refused. Nothing is written.
|
|
264
|
+
"member-exists": "member add names a member the declaration already has, with an entry other than the one given.",
|
|
265
|
+
"member-unknown": "member remove names a member the declaration does not declare.",
|
|
266
|
+
// A box's factory written through chant (box factory set, #3600): why the write was refused. Nothing is written.
|
|
267
|
+
"factory-member-unknown": "box factory set names a member the declaration does not declare.",
|
|
268
|
+
"factory-box-missing": "box factory set names a member whose entry declares no box block, so it has no factory.",
|
|
263
269
|
// A box's work published through chant (box publish, #3165, ws-088): why the call printed no result.
|
|
264
270
|
"publish-member-unknown": "box publish names a member the declaration does not declare.",
|
|
265
271
|
"publish-none": "box publish names a member whose box block names no publisher, or which declares no box block.",
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
"$defs": {
|
|
8
8
|
"boxShip": {
|
|
9
9
|
"type": "object",
|
|
10
|
+
"patternProperties": { "^x-": { "description": "Added in contract 1 by #3595. An x- key the declaration holds on this object, with its value as written." } },
|
|
10
11
|
"additionalProperties": false,
|
|
11
12
|
"required": ["op", "gate", "env", "bookkeeping", "serving", "pending"],
|
|
12
13
|
"properties": {
|
|
@@ -170,6 +171,7 @@
|
|
|
170
171
|
},
|
|
171
172
|
"member": {
|
|
172
173
|
"type": "object",
|
|
174
|
+
"patternProperties": { "^x-": { "description": "Added in contract 1 by #3595. An x- key the declaration holds on this object, with its value as written." } },
|
|
173
175
|
"required": ["name", "dir", "kind", "fields", "environments", "compare", "readable", "gateLedger", "gates", "box", "stewards", "stewardReasons"],
|
|
174
176
|
"properties": {
|
|
175
177
|
"name": { "type": "string" },
|
|
@@ -543,7 +545,11 @@
|
|
|
543
545
|
"choice": { "description": "The record's choice as written, such as { option, reason }, or null while the record is proposed." },
|
|
544
546
|
"answer": { "type": ["string", "null"], "description": "The chosen option's label, from options[]'s entry whose id is choice.option, or null while no option is chosen (#2855). Added by chant 0.94.0." },
|
|
545
547
|
"decided_by": { "type": ["string", "null"], "description": "Who decided it, or null while it is proposed." },
|
|
546
|
-
"decided_on": { "type": ["string", "null"], "description": "The day it was decided, or null while it is proposed." }
|
|
548
|
+
"decided_on": { "type": ["string", "null"], "description": "The day it was decided, or null while it is proposed." },
|
|
549
|
+
"approved": {
|
|
550
|
+
"type": "boolean",
|
|
551
|
+
"description": "Added in contract 1 by #3609. Whether the record's state counts as approved: the decision kind's approval rank for that state is above 0, the rule the factory's pick holds dispatch with. With chant's decision kind, decided, ratified and superseded are approved, and proposed and withdrawn are not. False when no decision record has the id, and for a kind that declares no approval ranks."
|
|
552
|
+
}
|
|
547
553
|
}
|
|
548
554
|
},
|
|
549
555
|
"replication": {
|
|
@@ -583,6 +589,7 @@
|
|
|
583
589
|
},
|
|
584
590
|
"box": {
|
|
585
591
|
"type": "object",
|
|
592
|
+
"patternProperties": { "^x-": { "description": "Added in contract 1 by #3595. An x- key the declaration holds on this object, with its value as written." } },
|
|
586
593
|
"required": ["capabilities", "isolation", "intent", "services"],
|
|
587
594
|
"properties": {
|
|
588
595
|
"factory": {
|
|
@@ -681,6 +688,7 @@
|
|
|
681
688
|
},
|
|
682
689
|
"factory": {
|
|
683
690
|
"type": "object",
|
|
691
|
+
"patternProperties": { "^x-": { "description": "Added in contract 1 by #3595. An x- key the declaration holds on this object, with its value as written." } },
|
|
684
692
|
"required": ["builds", "check", "checks", "builders", "tiers", "builderFor", "publish"],
|
|
685
693
|
"properties": {
|
|
686
694
|
"builds": { "type": "array", "minItems": 1, "items": { "type": "string" }, "description": "The members the factory builds, in declaration order. A work item a person asks for constrains member:<the first>." },
|
|
@@ -723,6 +731,7 @@
|
|
|
723
731
|
},
|
|
724
732
|
"listing": {
|
|
725
733
|
"type": "object",
|
|
734
|
+
"patternProperties": { "^x-": { "description": "Added in contract 1 by #3595. An x- key the declaration holds on this object, with its value as written." } },
|
|
726
735
|
"required": ["published", "title", "line", "cover"],
|
|
727
736
|
"properties": {
|
|
728
737
|
"published": { "type": "boolean", "description": "Whether the box is listed; true unless declared otherwise." },
|
package/src/workspace/status.ts
CHANGED
|
@@ -48,7 +48,7 @@ import { resolveBoxes, type ResolvedIsolation } from "./box-isolation";
|
|
|
48
48
|
import { resolveBoxIntents, unresolvedIntent, type BoxIntent } from "./box-intent";
|
|
49
49
|
import { loadKindRegistry, resolveMemberFields, type MemberFields } from "./kinds";
|
|
50
50
|
import { factoryView, listingView, plantability, treeBytes, type FactoryView, type ListingView, type Plantable } from "./box-factory";
|
|
51
|
-
import { declaredRecordKinds, readDeclaration, readerVersion, WorkspaceReadError, type Declaration, type ErrorLocation, type Member } from "./declaration";
|
|
51
|
+
import { declaredRecordKinds, extensionsAt, readDeclaration, readerVersion, WorkspaceReadError, type Declaration, type ErrorLocation, type Member } from "./declaration";
|
|
52
52
|
import type { ReasonCode } from "./reason-codes";
|
|
53
53
|
import { gateAdmissionFrom } from "./identity";
|
|
54
54
|
import { scopeSource } from "./write-scope";
|
|
@@ -320,6 +320,18 @@ export interface StatusQuery {
|
|
|
320
320
|
readStewards?: typeof readMemberStewards;
|
|
321
321
|
}
|
|
322
322
|
|
|
323
|
+
/** A factory view with the declaration's x- keys on it and on its check, publish and tiers (#3595). */
|
|
324
|
+
function factoryWithX(view: FactoryView | null, pointer: string, x: (pointer: string) => Record<string, unknown>): FactoryView | null {
|
|
325
|
+
if (view === null) return null;
|
|
326
|
+
return {
|
|
327
|
+
...view,
|
|
328
|
+
check: view.check === null ? null : { ...view.check, ...x(`${pointer}/check`) },
|
|
329
|
+
tiers: view.tiers.map((t, i) => ({ ...t, ...x(`${pointer}/tiers/${i}`) })),
|
|
330
|
+
publish: view.publish === null ? null : { ...view.publish, ...x(`${pointer}/publish`) },
|
|
331
|
+
...x(pointer),
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
|
|
323
335
|
class StatusError extends Error {
|
|
324
336
|
constructor(
|
|
325
337
|
readonly code: StatusErrorCode,
|
|
@@ -500,6 +512,10 @@ export async function workspaceStatus(query: StatusQuery): Promise<StatusDocumen
|
|
|
500
512
|
const own = await hasMemberLedger(m, found.dir);
|
|
501
513
|
const gates = await readMemberGates(own ? `${MEMBERS_DIR}/${m.name}/${GATES_DIR}` : GATES_DIR, own ? "members" : "flat", commit, envs, found.dir, now, query.readGates, rules);
|
|
502
514
|
const stewards = await (query.readStewards ?? readMemberStewards)(resolve(found.dir, m.dir), query.env, now, m.kind, m.box);
|
|
515
|
+
// The declaration's x- keys go back on the objects that hold them (#3595).
|
|
516
|
+
const x = (pointer: string) => extensionsAt(declaration, pointer);
|
|
517
|
+
const bp = m.box?.pointer ?? "";
|
|
518
|
+
const withX = <T extends object>(view: T | null, pointer: string): T | null => (view === null ? null : { ...view, ...x(pointer) });
|
|
503
519
|
members.push({
|
|
504
520
|
name: m.name,
|
|
505
521
|
dir: m.dir,
|
|
@@ -514,7 +530,7 @@ export async function workspaceStatus(query: StatusQuery): Promise<StatusDocumen
|
|
|
514
530
|
m.box === null
|
|
515
531
|
? null
|
|
516
532
|
: {
|
|
517
|
-
capabilities: m.box.capabilities.map((c) => ({ name: c.name, broker: c.broker, scope: [...c.scope] })),
|
|
533
|
+
capabilities: m.box.capabilities.map((c) => ({ name: c.name, broker: c.broker, scope: [...c.scope], ...x(c.pointer) })),
|
|
518
534
|
isolation: isolation.get(m.name) ?? null,
|
|
519
535
|
intent: intents.get(m.name) ?? null,
|
|
520
536
|
services: m.box.services.map((s) => ({
|
|
@@ -525,15 +541,18 @@ export async function workspaceStatus(query: StatusQuery): Promise<StatusDocumen
|
|
|
525
541
|
duration: s.duration,
|
|
526
542
|
health: s.health,
|
|
527
543
|
optional: s.optional,
|
|
544
|
+
...x(s.pointer),
|
|
528
545
|
})),
|
|
529
|
-
factory: factoryView(m.box.factory, declaration.members),
|
|
530
|
-
listing: listingView(m.box.listing, coverBytes),
|
|
546
|
+
factory: factoryWithX(factoryView(m.box.factory, declaration.members), `${bp}/factory`, x),
|
|
547
|
+
listing: withX(listingView(m.box.listing, coverBytes), `${bp}/listing`),
|
|
531
548
|
publisher: m.box.publisher,
|
|
532
|
-
ship: await shipView(m, found.dir, read),
|
|
533
|
-
replicate: m.box.replicate === null ? null : (({ box: _box, ...rest }) => rest)(policyView(m.name, m.box.replicate)),
|
|
549
|
+
ship: withX(await shipView(m, found.dir, read), `${bp}/ship`),
|
|
550
|
+
replicate: withX(m.box.replicate === null ? null : (({ box: _box, ...rest }) => rest)(policyView(m.name, m.box.replicate)), `${bp}/replicate`),
|
|
551
|
+
...x(bp),
|
|
534
552
|
},
|
|
535
553
|
stewards: stewards.stewards,
|
|
536
554
|
stewardReasons: stewards.reasons,
|
|
555
|
+
...x(m.pointer),
|
|
537
556
|
});
|
|
538
557
|
}
|
|
539
558
|
// Several members read from one flat ledger see the same records; say so.
|
|
@@ -403,6 +403,23 @@ export function scopedKind(source: ScopeSource, kindName: string, kindFile: stri
|
|
|
403
403
|
return { name: kindName, declaredName: null, member: dir.startsWith("..") ? null : memberHolding(dir === "" ? "." : dir, decl.members), declared: false };
|
|
404
404
|
}
|
|
405
405
|
|
|
406
|
+
/**
|
|
407
|
+
* The agent sessions as `chant workspace agent` and the write paths read
|
|
408
|
+
* them (#3615): the declaration at base, else the working tree's. Null when
|
|
409
|
+
* neither has a declaration. Lighter than {@link scopeSource}: no trust
|
|
410
|
+
* policy and no principal classes.
|
|
411
|
+
*/
|
|
412
|
+
export function declaredSessions(cwd: string): { agents: AgentDeclaration[]; from: "base" | "working-tree" } | null {
|
|
413
|
+
const top = gitRoot(cwd);
|
|
414
|
+
const base = top ? resolveBase(top) : null;
|
|
415
|
+
if (base?.commit) {
|
|
416
|
+
const atBase = readAt(cwd, base.commit);
|
|
417
|
+
if (atBase) return { agents: atBase.declaration.agents, from: "base" };
|
|
418
|
+
}
|
|
419
|
+
const here = readAt(cwd);
|
|
420
|
+
return here ? { agents: here.declaration.agents, from: "working-tree" } : null;
|
|
421
|
+
}
|
|
422
|
+
|
|
406
423
|
/**
|
|
407
424
|
* Refuse a record write outside the writer's scope (#2548): throws a
|
|
408
425
|
* {@link WriteScopeError}. `agent` is the session the write names
|
package/src/yaml.test.ts
CHANGED
|
@@ -26,6 +26,12 @@ describe("emitYAML", () => {
|
|
|
26
26
|
expect(emitYAML([undefined, 1], 0)).toBe("\n- null\n- 1");
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
+
test("an empty mapping in a list is an item, not nothing", () => {
|
|
30
|
+
expect(emitYAML([{}], 0)).toBe("\n- {}");
|
|
31
|
+
expect(emitYAML({ egress: [{}] }, 0)).toBe("\negress:\n - {}");
|
|
32
|
+
expect(emitYAML([{ a: undefined }, { b: 1 }], 0)).toBe("\n- {}\n- b: 1");
|
|
33
|
+
});
|
|
34
|
+
|
|
29
35
|
test("booleans", () => {
|
|
30
36
|
expect(emitYAML(true, 0)).toBe("true");
|
|
31
37
|
expect(emitYAML(false, 0)).toBe("false");
|
package/src/yaml.ts
CHANGED
|
@@ -127,6 +127,10 @@ export function emitYAML(value: unknown, indent: number): string {
|
|
|
127
127
|
lines.push(`${prefix} ${key}: ${emitted}`);
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
|
+
} else {
|
|
131
|
+
// An empty mapping is still an item: `egress: [{}]` allows all
|
|
132
|
+
// egress, and dropping it leaves an empty list.
|
|
133
|
+
lines.push(`${prefix}- {}`);
|
|
130
134
|
}
|
|
131
135
|
} else {
|
|
132
136
|
lines.push(`${prefix}- ${emitYAML(item, indent + 1).trimStart()}`);
|