@detergent-software/conductor 1.0.0-dev.9 → 1.0.1-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +305 -0
- package/README.md +277 -24
- package/build/brief-cli.js +68 -0
- package/build/brief-cli.js.map +1 -0
- package/build/brief.js +211 -0
- package/build/brief.js.map +1 -0
- package/build/broker-cli.js +126 -0
- package/build/broker-cli.js.map +1 -0
- package/build/broker.js +154 -0
- package/build/broker.js.map +1 -0
- package/build/cli.js +442 -132
- package/build/cli.js.map +1 -1
- package/build/conditions.js +15 -8
- package/build/conditions.js.map +1 -1
- package/build/config.js +26 -3
- package/build/config.js.map +1 -1
- package/build/console.js +225 -0
- package/build/console.js.map +1 -0
- package/build/daemon.js +136 -5
- package/build/daemon.js.map +1 -1
- package/build/events.js +2 -1
- package/build/events.js.map +1 -1
- package/build/help.js +448 -0
- package/build/help.js.map +1 -0
- package/build/history.js +637 -0
- package/build/history.js.map +1 -0
- package/build/inbox.js +117 -18
- package/build/inbox.js.map +1 -1
- package/build/manager.js +118 -43
- package/build/manager.js.map +1 -1
- package/build/notes.js +27 -43
- package/build/notes.js.map +1 -1
- package/build/notify.js +32 -3
- package/build/notify.js.map +1 -1
- package/build/overrides.js +83 -0
- package/build/overrides.js.map +1 -0
- package/build/paths.js +10 -1
- package/build/paths.js.map +1 -1
- package/build/profile.js +68 -2
- package/build/profile.js.map +1 -1
- package/build/queue.js +183 -0
- package/build/queue.js.map +1 -0
- package/build/registry.js +17 -10
- package/build/registry.js.map +1 -1
- package/build/rule-actions.js +444 -0
- package/build/rule-actions.js.map +1 -0
- package/build/rule-input.js +17 -0
- package/build/rule-input.js.map +1 -0
- package/build/rules-service.js +402 -0
- package/build/rules-service.js.map +1 -0
- package/build/rules.js +850 -0
- package/build/rules.js.map +1 -0
- package/build/scheduler.js +293 -0
- package/build/scheduler.js.map +1 -0
- package/build/serve.js +51 -0
- package/build/serve.js.map +1 -0
- package/build/server.js +244 -7
- package/build/server.js.map +1 -1
- package/build/spend.js +42 -0
- package/build/spend.js.map +1 -1
- package/build/store.js +266 -12
- package/build/store.js.map +1 -1
- package/build/trackers.js +15 -0
- package/build/trackers.js.map +1 -0
- package/build/upgrade.js +16 -14
- package/build/upgrade.js.map +1 -1
- package/build/wait.js +3 -9
- package/build/wait.js.map +1 -1
- package/build/watchers/ado-api.js +55 -0
- package/build/watchers/ado-api.js.map +1 -0
- package/build/watchers/ado.js +60 -52
- package/build/watchers/ado.js.map +1 -1
- package/build/watchers/boards-brief.js +63 -0
- package/build/watchers/boards-brief.js.map +1 -0
- package/build/watchers/boards-queue.js +120 -0
- package/build/watchers/boards-queue.js.map +1 -0
- package/build/watchers/boards-writes.js +83 -0
- package/build/watchers/boards-writes.js.map +1 -0
- package/build/watchers/boards.js +271 -0
- package/build/watchers/boards.js.map +1 -0
- package/build/watchers/conflicts.js +132 -0
- package/build/watchers/conflicts.js.map +1 -0
- package/build/watchers/github.js +5 -2
- package/build/watchers/github.js.map +1 -1
- package/build/watchers/index.js +21 -7
- package/build/watchers/index.js.map +1 -1
- package/build/watchers/linear-api.js +55 -0
- package/build/watchers/linear-api.js.map +1 -0
- package/build/watchers/linear-labels.js +43 -0
- package/build/watchers/linear-labels.js.map +1 -0
- package/build/watchers/linear-queue.js +96 -0
- package/build/watchers/linear-queue.js.map +1 -0
- package/build/watchers/linear.js +18 -16
- package/build/watchers/linear.js.map +1 -1
- package/build/watchers/source.js +3 -3
- package/build/watchers/source.js.map +1 -1
- package/build/why.js +78 -0
- package/build/why.js.map +1 -0
- package/mod/.claude-plugin/plugin.json +1 -1
- package/mod/README.md +2 -2
- package/mod/hooks/model.ts +135 -8
- package/mod/hooks/register.tsx +219 -19
- package/mod/types/index.d.ts +6 -0
- package/package.json +1 -1
package/build/queue.js
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const pickSchema = z.object({
|
|
3
|
+
area: z.string().nullable(),
|
|
4
|
+
id: z.string(),
|
|
5
|
+
project: z.string(),
|
|
6
|
+
title: z.string().nullable(),
|
|
7
|
+
trackerProject: z.string().nullable(),
|
|
8
|
+
});
|
|
9
|
+
export const waitingSchema = z.object({
|
|
10
|
+
id: z.string(),
|
|
11
|
+
// It will start once a slot, an Area or a blocker frees up (or the hold ends); false when it
|
|
12
|
+
// never will on its own (labelled human, blocked by an item nobody works on).
|
|
13
|
+
pending: z.boolean(),
|
|
14
|
+
project: z.string(),
|
|
15
|
+
reason: z.string(),
|
|
16
|
+
trackerProject: z.string().nullable(),
|
|
17
|
+
});
|
|
18
|
+
export const queuePlanSchema = z.object({
|
|
19
|
+
// Nothing to start, nothing that will become startable, nothing conducted to watch.
|
|
20
|
+
drained: z.boolean(),
|
|
21
|
+
picks: z.array(pickSchema),
|
|
22
|
+
// Conducted tracker projects with no open item: everything is done on the base branch.
|
|
23
|
+
readyToRelease: z.array(z.object({ project: z.string(), trackerProject: z.string() })),
|
|
24
|
+
slots: z.object({
|
|
25
|
+
free: z.number(),
|
|
26
|
+
parked: z.number(),
|
|
27
|
+
projects: z.array(z.object({ free: z.number(), name: z.string(), parked: z.number(), running: z.number(), size: z.number() })),
|
|
28
|
+
running: z.number(),
|
|
29
|
+
size: z.number(),
|
|
30
|
+
}),
|
|
31
|
+
waiting: z.array(waitingSchema),
|
|
32
|
+
});
|
|
33
|
+
const READY = new Set(['backlog', 'unstarted']); // Backlog and Todo
|
|
34
|
+
// The Area an item holds: the one its tracker read gave it (a Boards Area Path), else its label in
|
|
35
|
+
// the Area group.
|
|
36
|
+
export function areaOf(item, areaLabels) {
|
|
37
|
+
if (item?.area)
|
|
38
|
+
return item.area;
|
|
39
|
+
const areas = new Set(areaLabels);
|
|
40
|
+
return item?.labels.find((l) => areas.has(l)) ?? null;
|
|
41
|
+
}
|
|
42
|
+
// The Area group is single-select, so an item that spans sub-Areas carries their parent: `skills`
|
|
43
|
+
// covers `skills/conduct-atk` and `skills/work-issue`, which don't cover each other.
|
|
44
|
+
export function areasOverlap(a, b) {
|
|
45
|
+
if (!a || !b)
|
|
46
|
+
return false;
|
|
47
|
+
return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);
|
|
48
|
+
}
|
|
49
|
+
// The tracker projects whose items are queued, in order.
|
|
50
|
+
export function conductedProjects(projects) {
|
|
51
|
+
return projects
|
|
52
|
+
.filter((p) => p.priority !== null && p.priority >= 1 && p.priority <= 4)
|
|
53
|
+
.sort((a, b) => (a.priority ?? 5) - (b.priority ?? 5) || (a.sortOrder ?? 0) - (b.sortOrder ?? 0));
|
|
54
|
+
}
|
|
55
|
+
// The items to start now, in order, and why the others wait. An Area is held, per project, by
|
|
56
|
+
// every item in flight and every item the tracker says is started, and by the Areas it covers or
|
|
57
|
+
// is covered by. Slots count running workers: a parked worker keeps its Area but not its slot.
|
|
58
|
+
export function planQueue({ held, inFlight, projects, slots }) {
|
|
59
|
+
const states = new Map();
|
|
60
|
+
const candidates = [];
|
|
61
|
+
for (const queue of projects) {
|
|
62
|
+
const { snapshot } = queue;
|
|
63
|
+
const tracked = conductedProjects(snapshot.projects);
|
|
64
|
+
const rank = new Map(tracked.map((p, i) => [p.name, i]));
|
|
65
|
+
const open = new Map(snapshot.issues.map((i) => [i.id, i]));
|
|
66
|
+
const closed = new Set(snapshot.closed);
|
|
67
|
+
const own = inFlight.filter((w) => w.project === queue.name);
|
|
68
|
+
// A worker whose item closed holds no Area, but keeps its slot until it has retired: a retire
|
|
69
|
+
// can be refused (unfinished work) while its session still runs.
|
|
70
|
+
const mine = new Map(own.filter((w) => !closed.has(w.item)).map((w) => [w.item, w]));
|
|
71
|
+
const parked = own.filter((w) => w.status === 'parked').length;
|
|
72
|
+
const running = own.length - parked;
|
|
73
|
+
const holders = new Map();
|
|
74
|
+
const state = {
|
|
75
|
+
free: Math.max(0, queue.slots - running),
|
|
76
|
+
holders,
|
|
77
|
+
inFlight: mine,
|
|
78
|
+
open,
|
|
79
|
+
parked,
|
|
80
|
+
picked: 0,
|
|
81
|
+
queue,
|
|
82
|
+
queued: new Set(),
|
|
83
|
+
rank,
|
|
84
|
+
running,
|
|
85
|
+
};
|
|
86
|
+
const hold = (area, id) => {
|
|
87
|
+
if (area && !holders.has(area))
|
|
88
|
+
holders.set(area, id);
|
|
89
|
+
};
|
|
90
|
+
for (const w of mine.values())
|
|
91
|
+
hold(areaOf(open.get(w.item), snapshot.areaLabels), w.item);
|
|
92
|
+
for (const i of open.values())
|
|
93
|
+
if (i.stateType === 'started')
|
|
94
|
+
hold(areaOf(i, snapshot.areaLabels), i.id);
|
|
95
|
+
for (const i of open.values()) {
|
|
96
|
+
if (i.trackerProject !== null && rank.has(i.trackerProject) && READY.has(i.stateType ?? '')) {
|
|
97
|
+
candidates.push({ issue: i, state });
|
|
98
|
+
if (!i.labels.includes(queue.humanLabel))
|
|
99
|
+
state.queued.add(i.id);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
states.set(queue.name, state);
|
|
103
|
+
}
|
|
104
|
+
const trackerPriority = (c) => c.state.queue.snapshot.projects.find((p) => p.name === c.issue.trackerProject)?.priority ?? 5;
|
|
105
|
+
candidates.sort((a, b) => trackerPriority(a) - trackerPriority(b) ||
|
|
106
|
+
b.state.queue.weight - a.state.queue.weight ||
|
|
107
|
+
(a.state.rank.get(a.issue.trackerProject ?? '') ?? 0) - (b.state.rank.get(b.issue.trackerProject ?? '') ?? 0) ||
|
|
108
|
+
issuePriority(a.issue) - issuePriority(b.issue) ||
|
|
109
|
+
// A tracker's own order means something only within its project.
|
|
110
|
+
(a.state === b.state ? (a.issue.rank ?? 0) - (b.issue.rank ?? 0) : 0) ||
|
|
111
|
+
Date.parse(a.issue.createdAt ?? '0') - Date.parse(b.issue.createdAt ?? '0') ||
|
|
112
|
+
keyNumber(a.issue.id) - keyNumber(b.issue.id));
|
|
113
|
+
// Every worker counts against the global slots, those of a project whose read failed too.
|
|
114
|
+
const totalParked = inFlight.filter((w) => w.status === 'parked').length;
|
|
115
|
+
const totalRunning = inFlight.length - totalParked;
|
|
116
|
+
const globalFree = Math.max(0, slots - totalRunning);
|
|
117
|
+
const picks = [];
|
|
118
|
+
const waiting = [];
|
|
119
|
+
for (const { issue, state } of candidates) {
|
|
120
|
+
const { areaLabels } = state.queue.snapshot;
|
|
121
|
+
const area = areaOf(issue, areaLabels);
|
|
122
|
+
const blockers = issue.blockedBy.filter((b) => state.open.has(b));
|
|
123
|
+
const heldBy = state.holders.has(area ?? '')
|
|
124
|
+
? [area, state.holders.get(area ?? '')]
|
|
125
|
+
: [...state.holders].find(([h]) => areasOverlap(h, area));
|
|
126
|
+
// A blocker that will clear on its own: in flight, started, or in this queue.
|
|
127
|
+
const active = (b) => state.inFlight.has(b) || state.open.get(b)?.stateType === 'started' || state.queued.has(b);
|
|
128
|
+
let wait = null;
|
|
129
|
+
if (state.inFlight.has(issue.id))
|
|
130
|
+
wait = { pending: false, reason: 'in flight' };
|
|
131
|
+
else if (issue.labels.includes(state.queue.humanLabel))
|
|
132
|
+
wait = { pending: false, reason: `labelled ${state.queue.humanLabel}` };
|
|
133
|
+
else if (blockers.length > 0) {
|
|
134
|
+
const stuck = blockers.filter((b) => !active(b));
|
|
135
|
+
wait =
|
|
136
|
+
stuck.length > 0
|
|
137
|
+
? { pending: false, reason: `blocked by ${blockers.join(', ')} (${stuck.join(', ')} not being worked)` }
|
|
138
|
+
: { pending: true, reason: `blocked by ${blockers.join(', ')}` };
|
|
139
|
+
}
|
|
140
|
+
else if (heldBy) {
|
|
141
|
+
const [heldArea, holder] = heldBy;
|
|
142
|
+
wait = { pending: true, reason: `Area ${area ?? ''} held by ${holder ?? '?'}${heldArea === area ? '' : ` (${heldArea ?? ''})`}` };
|
|
143
|
+
}
|
|
144
|
+
else if (held !== null)
|
|
145
|
+
wait = { pending: true, reason: held };
|
|
146
|
+
else if (state.queue.paused !== null)
|
|
147
|
+
wait = { pending: true, reason: state.queue.paused };
|
|
148
|
+
else if (state.picked >= state.free)
|
|
149
|
+
wait = { pending: true, reason: 'no free slot' };
|
|
150
|
+
else if (picks.length >= globalFree)
|
|
151
|
+
wait = { pending: true, reason: `no free slot (all ${slots} in use across projects)` };
|
|
152
|
+
if (wait) {
|
|
153
|
+
waiting.push({ id: issue.id, project: state.queue.name, trackerProject: issue.trackerProject, ...wait });
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
picks.push({ area, id: issue.id, project: state.queue.name, title: issue.title, trackerProject: issue.trackerProject });
|
|
157
|
+
state.picked++;
|
|
158
|
+
if (area && !state.holders.has(area))
|
|
159
|
+
state.holders.set(area, issue.id);
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
drained: picks.length === 0 && !waiting.some((w) => w.pending) && inFlight.length === 0,
|
|
163
|
+
picks,
|
|
164
|
+
readyToRelease: [...states.values()].flatMap((s) => conductedProjects(s.queue.snapshot.projects)
|
|
165
|
+
.filter((p) => !s.queue.snapshot.issues.some((i) => i.trackerProject === p.name))
|
|
166
|
+
.map((p) => ({ project: s.queue.name, trackerProject: p.name }))),
|
|
167
|
+
slots: {
|
|
168
|
+
free: globalFree,
|
|
169
|
+
parked: totalParked,
|
|
170
|
+
projects: [...states.values()].map((s) => ({ free: s.free, name: s.queue.name, parked: s.parked, running: s.running, size: s.queue.slots })),
|
|
171
|
+
running: totalRunning,
|
|
172
|
+
size: slots,
|
|
173
|
+
},
|
|
174
|
+
waiting,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function issuePriority(issue) {
|
|
178
|
+
return issue.priority !== null && issue.priority >= 1 && issue.priority <= 4 ? issue.priority : 5;
|
|
179
|
+
}
|
|
180
|
+
function keyNumber(key) {
|
|
181
|
+
return Number(key.split('-')[1]);
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"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"}
|
package/build/registry.js
CHANGED
|
@@ -2,12 +2,9 @@ import { existsSync, realpathSync } from 'node:fs';
|
|
|
2
2
|
import { basename, dirname, join, resolve } from 'node:path';
|
|
3
3
|
import { ConductorError } from "./errors.js";
|
|
4
4
|
import { PROFILE_FILE, readProfile } from "./profile.js";
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
// `conduct project add .` works from any directory of any checkout. With no profile on the way up,
|
|
9
|
-
// the given directory is the answer, and reading its profile says what is missing.
|
|
10
|
-
export function projectRoot(path) {
|
|
5
|
+
// The checkout a path is in (a worktree's own directory, or the main checkout) and the project's
|
|
6
|
+
// main checkout, found as projectRoot says.
|
|
7
|
+
export function checkoutOf(path) {
|
|
11
8
|
let start;
|
|
12
9
|
try {
|
|
13
10
|
start = realpathSync.native(resolve(path));
|
|
@@ -18,16 +15,26 @@ export function projectRoot(path) {
|
|
|
18
15
|
for (let dir = start;; dir = dirname(dir)) {
|
|
19
16
|
const parent = dirname(dir);
|
|
20
17
|
if (basename(parent) === 'worktrees' && basename(dirname(parent)) === '.claude')
|
|
21
|
-
return dirname(dirname(parent));
|
|
18
|
+
return { checkout: dir, root: dirname(dirname(parent)) };
|
|
22
19
|
if (existsSync(join(dir, PROFILE_FILE)))
|
|
23
|
-
return dir;
|
|
20
|
+
return { checkout: dir, root: dir };
|
|
24
21
|
if (parent === dir)
|
|
25
|
-
return start;
|
|
22
|
+
return { checkout: start, root: start };
|
|
26
23
|
}
|
|
27
24
|
}
|
|
28
|
-
|
|
25
|
+
// A project is registered by its main checkout. From the given path this walks up, the way git
|
|
26
|
+
// finds .git, to the first directory that holds .claude/conductor.json. A worktree at
|
|
27
|
+
// <root>/.claude/worktrees/<name> belongs to <root>, the way scripts/dev-ports.mjs resolves it, so
|
|
28
|
+
// `conduct project add .` works from any directory of any checkout. With no profile on the way up,
|
|
29
|
+
// the given directory is the answer, and reading its profile says what is missing.
|
|
30
|
+
export function projectRoot(path) {
|
|
31
|
+
return checkoutOf(path).root;
|
|
32
|
+
}
|
|
33
|
+
// `check` refuses a profile before it is stored: the daemon checks its rules against config.json.
|
|
34
|
+
export function registerProject(store, path, check = () => { }) {
|
|
29
35
|
const root = projectRoot(path);
|
|
30
36
|
const { path: profilePath, profile } = readProfile(root);
|
|
37
|
+
check(profile, profilePath);
|
|
31
38
|
return store.upsertProject({ profile, profilePath, root });
|
|
32
39
|
}
|
|
33
40
|
//# sourceMappingURL=registry.js.map
|
package/build/registry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAI7D,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAI7D,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAgB,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEvE,iGAAiG;AACjG,4CAA4C;AAC5C,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,IAAI,KAAa,CAAC;IAClB,IAAI,CAAC;QACH,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,cAAc,CAAC,GAAG,IAAI,iBAAiB,CAAC,CAAC;IACrD,CAAC;IACD,KAAK,IAAI,GAAG,GAAG,KAAK,GAAI,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,QAAQ,CAAC,MAAM,CAAC,KAAK,WAAW,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,SAAS;YAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QAC1I,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;YAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;QAC7E,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAC9D,CAAC;AACH,CAAC;AAED,+FAA+F;AAC/F,sFAAsF;AACtF,mGAAmG;AACnG,mGAAmG;AACnG,mFAAmF;AACnF,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;AAC/B,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,eAAe,CAC7B,KAAY,EACZ,IAAY,EACZ,QAAkD,GAAG,EAAE,GAAE,CAAC;IAE1D,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACzD,KAAK,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAC5B,OAAO,KAAK,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7D,CAAC"}
|