halfcycle 0.4.9 → 0.4.11
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/.claude-plugin/plugin.json +1 -1
- package/bin/bin.bundle.mjs +152 -137
- package/dist/bin.js +0 -0
- package/dist/build-record/render-v2.d.ts +5 -0
- package/dist/build-record/render-v2.d.ts.map +1 -1
- package/dist/cli-contract.d.ts.map +1 -1
- package/dist/cli.js +290 -122
- package/dist/cli.js.map +3 -3
- package/dist/close-phase.d.ts +10 -2
- package/dist/close-phase.d.ts.map +1 -1
- package/dist/draw/index.d.ts +4 -1
- package/dist/draw/index.d.ts.map +1 -1
- package/dist/index.js +137 -62
- package/dist/index.js.map +2 -2
- package/dist/plan.d.ts +21 -10
- package/dist/plan.d.ts.map +1 -1
- package/dist/review.d.ts +6 -3
- package/dist/review.d.ts.map +1 -1
- package/package.json +11 -11
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "halfcycle",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.11",
|
|
4
4
|
"description": "Halfcycle Method bundle — resolution-stub slash commands, remote method-delivery registration, and governance-hook wiring for a Halfcycle engagement repo. It ships NO worker role files: a project's roles are authored from that project's own recorded decisions at orchestration kickoff (FX-2, W3-F-27).",
|
|
5
5
|
"commands": [
|
|
6
6
|
{
|
package/bin/bin.bundle.mjs
CHANGED
|
@@ -16149,14 +16149,13 @@ var SCOPE_STATE_NAMES = [
|
|
|
16149
16149
|
"waiting",
|
|
16150
16150
|
"sent-back",
|
|
16151
16151
|
"approved",
|
|
16152
|
-
"partly-stale"
|
|
16153
|
-
"withdrawn"
|
|
16152
|
+
"partly-stale"
|
|
16154
16153
|
];
|
|
16155
16154
|
var scopeStateNameSchema = external_exports.enum(SCOPE_STATE_NAMES);
|
|
16156
16155
|
var plannedScopeStateSchema = scopeStateNameSchema.exclude(["not-planned"]);
|
|
16157
16156
|
var SCOPE_PART_STATUSES = ["approved", "waiting"];
|
|
16158
16157
|
var scopePartStatusSchema = external_exports.enum(SCOPE_PART_STATUSES);
|
|
16159
|
-
var SCOPE_ACTS = ["approve", "send-back"
|
|
16158
|
+
var SCOPE_ACTS = ["approve", "send-back"];
|
|
16160
16159
|
var scopeActSchema = external_exports.enum(SCOPE_ACTS);
|
|
16161
16160
|
var SCOPE_GIVEN_IN = ["console", "chat"];
|
|
16162
16161
|
var scopeGivenInSchema = external_exports.enum(SCOPE_GIVEN_IN);
|
|
@@ -16227,14 +16226,9 @@ var scopeSendBackRequestSchema = external_exports.object({
|
|
|
16227
16226
|
parts: external_exports.array(scopeDecisionPartSchema).max(PHASE_PLAN_CHANGES_MAX),
|
|
16228
16227
|
note: scopeNoteWireSchema.optional()
|
|
16229
16228
|
}).strict();
|
|
16230
|
-
var scopeWithdrawRequestSchema = external_exports.object({
|
|
16231
|
-
act: external_exports.literal("withdraw"),
|
|
16232
|
-
planVersion: planVersionSchema
|
|
16233
|
-
}).strict();
|
|
16234
16229
|
var scopeDecisionRequestSchema = external_exports.discriminatedUnion("act", [
|
|
16235
16230
|
scopeApproveRequestSchema,
|
|
16236
|
-
scopeSendBackRequestSchema
|
|
16237
|
-
scopeWithdrawRequestSchema
|
|
16231
|
+
scopeSendBackRequestSchema
|
|
16238
16232
|
]);
|
|
16239
16233
|
var scopeDecisionRecordedSchema = external_exports.object({
|
|
16240
16234
|
outcome: external_exports.literal("recorded"),
|
|
@@ -16267,7 +16261,6 @@ var scopeDecisionResultSchema = external_exports.discriminatedUnion("outcome", [
|
|
|
16267
16261
|
reasonOutcome("not-owner"),
|
|
16268
16262
|
reasonOutcome("no-owner"),
|
|
16269
16263
|
reasonOutcome("plan-changed"),
|
|
16270
|
-
reasonOutcome("nothing-to-withdraw"),
|
|
16271
16264
|
reasonOutcome("build-started")
|
|
16272
16265
|
]);
|
|
16273
16266
|
var scopeReadPartSchema = external_exports.object({
|
|
@@ -16880,107 +16873,6 @@ var TYPED_APPROVAL_OFF_SENTENCE = "Approving by typing is switched off for now."
|
|
|
16880
16873
|
var TYPED_REVIEW_OFF_SENTENCE = "Reviewing by typing is switched off for now.";
|
|
16881
16874
|
var CLIENT_UPDATE_SENTENCE = `To approve by typing in a session, Halfcycle needs updating: run \`${HALFCYCLE_COMMAND}\` in this project's folder, then reopen your session and ask again.`;
|
|
16882
16875
|
|
|
16883
|
-
// ../events/dist/scope-notices.js
|
|
16884
|
-
var scopePartNameSchema = external_exports.string().min(1).max(SYSTEM_PART_NAME_MAX);
|
|
16885
|
-
var scopeNoteEntrySchema = external_exports.object({
|
|
16886
|
-
part: scopePartNameSchema.optional(),
|
|
16887
|
-
note: external_exports.string().min(1).max(SCOPE_NOTE_MAX)
|
|
16888
|
-
}).strict();
|
|
16889
|
-
var scopeSentBackSchema = external_exports.object({
|
|
16890
|
-
phase: scopePhaseSchema,
|
|
16891
|
-
number: external_exports.number().int().min(1),
|
|
16892
|
-
notes: external_exports.array(scopeNoteEntrySchema).min(1).max(PHASE_PLAN_CHANGES_MAX + 1)
|
|
16893
|
-
}).strict().superRefine((entry, ctx) => {
|
|
16894
|
-
entry.notes.forEach((n, i) => {
|
|
16895
|
-
if (n.part === void 0 && i !== entry.notes.length - 1) {
|
|
16896
|
-
ctx.addIssue({
|
|
16897
|
-
code: external_exports.ZodIssueCode.custom,
|
|
16898
|
-
path: ["notes", i],
|
|
16899
|
-
message: "the note on the whole phase comes after every note on a part"
|
|
16900
|
-
});
|
|
16901
|
-
}
|
|
16902
|
-
});
|
|
16903
|
-
});
|
|
16904
|
-
var scopeWaitingSchema = external_exports.object({
|
|
16905
|
-
phase: scopePhaseSchema,
|
|
16906
|
-
number: external_exports.number().int().min(1),
|
|
16907
|
-
changedParts: external_exports.array(scopePartNameSchema).max(PHASE_PLAN_CHANGES_MAX)
|
|
16908
|
-
}).strict();
|
|
16909
|
-
var scopeNoticesSchema = external_exports.object({
|
|
16910
|
-
sentBack: external_exports.array(scopeSentBackSchema),
|
|
16911
|
-
waiting: external_exports.array(scopeWaitingSchema),
|
|
16912
|
-
typedApprovalOffered: external_exports.boolean()
|
|
16913
|
-
}).strict().refine((v) => v.sentBack.length > 0 || v.waiting.length > 0, {
|
|
16914
|
-
message: "carried only when a phase was sent back or waits for the owner"
|
|
16915
|
-
});
|
|
16916
|
-
function quotedParts(parts) {
|
|
16917
|
-
return parts.map((p) => `"${p}"`).join(", ");
|
|
16918
|
-
}
|
|
16919
|
-
function approvalSentence(phase, offerTyping) {
|
|
16920
|
-
if (offerTyping === "off")
|
|
16921
|
-
return TYPED_APPROVAL_OFF_SENTENCE;
|
|
16922
|
-
if (offerTyping === "update")
|
|
16923
|
-
return CLIENT_UPDATE_SENTENCE;
|
|
16924
|
-
return `In their own Claude Code session, they ask to see the plan, check each part, and then type: approve ${phase}`;
|
|
16925
|
-
}
|
|
16926
|
-
function sentBackNotice(entry) {
|
|
16927
|
-
return [
|
|
16928
|
-
`Before anything else: the project's owner sent the scope of phase ${entry.number}, "${entry.phase}", back with these notes.`,
|
|
16929
|
-
...entry.notes.map((n) => n.part === void 0 ? `- ${n.note}` : `- "${n.part}": ${n.note}`),
|
|
16930
|
-
`Change the plan to answer every note, then send it again: say "plan the next phase" to start. It then waits for the owner's approval again.`
|
|
16931
|
-
].join("\n");
|
|
16932
|
-
}
|
|
16933
|
-
function waitingNotice(entry, offerTyping) {
|
|
16934
|
-
return [
|
|
16935
|
-
...entry.changedParts.length > 0 ? [`These parts changed since the owner last decided on this phase, and wait for their approval: ${quotedParts(entry.changedParts)}.`] : [],
|
|
16936
|
-
`The scope of phase ${entry.number}, "${entry.phase}", is waiting for the project's owner to approve it.`,
|
|
16937
|
-
approvalSentence(entry.phase, offerTyping)
|
|
16938
|
-
].join(" ");
|
|
16939
|
-
}
|
|
16940
|
-
function scopeNoticeText(scope, options) {
|
|
16941
|
-
const omit2 = options.omitActivePhase === true ? options.activePhase : void 0;
|
|
16942
|
-
return {
|
|
16943
|
-
sentBack: scope.sentBack.map(sentBackNotice),
|
|
16944
|
-
waiting: scope.waiting.filter((w) => omit2 === void 0 || w.phase !== omit2).map((w) => waitingNotice(w, options.offerTyping))
|
|
16945
|
-
};
|
|
16946
|
-
}
|
|
16947
|
-
|
|
16948
|
-
// ../events/dist/review-notices.js
|
|
16949
|
-
var reviewNoticeQuestionSchema = external_exports.object({
|
|
16950
|
-
phase: scopePhaseSchema,
|
|
16951
|
-
number: reviewPhaseNumberSchema,
|
|
16952
|
-
part: systemPartIdSchema,
|
|
16953
|
-
partName: systemPartSchema.shape.name,
|
|
16954
|
-
question: reviewNoteSchema
|
|
16955
|
-
}).strict();
|
|
16956
|
-
var reviewNoticeSentBackSchema = external_exports.object({
|
|
16957
|
-
phase: scopePhaseSchema,
|
|
16958
|
-
number: reviewPhaseNumberSchema,
|
|
16959
|
-
part: systemPartIdSchema,
|
|
16960
|
-
partName: systemPartSchema.shape.name,
|
|
16961
|
-
note: reviewNoteSchema
|
|
16962
|
-
}).strict();
|
|
16963
|
-
var reviewNoticesSchema = external_exports.object({
|
|
16964
|
-
questions: external_exports.array(reviewNoticeQuestionSchema).max(REVIEW_PARTS_MAX),
|
|
16965
|
-
sentBack: external_exports.array(reviewNoticeSentBackSchema).max(REVIEW_PARTS_MAX)
|
|
16966
|
-
}).strict().refine((v) => v.questions.length > 0 || v.sentBack.length > 0, {
|
|
16967
|
-
message: "carried only when a question waits or a part was sent back"
|
|
16968
|
-
});
|
|
16969
|
-
function phaseCalled(phase, number4) {
|
|
16970
|
-
return number4 === null ? `phase "${phase}"` : `phase ${number4}, "${phase}"`;
|
|
16971
|
-
}
|
|
16972
|
-
function questionNotice(entry) {
|
|
16973
|
-
const answer = `${HALFCYCLE_COMMAND} review ${quoteForShell(entry.phase)} --answer ${quoteForShell(entry.part)} "<your answer>"`;
|
|
16974
|
-
return `Before anything else: the project's owner asked about "${entry.partName}" in the review of ${phaseCalled(entry.phase, entry.number)}: ${entry.question} Answer it with ${answer}.`;
|
|
16975
|
-
}
|
|
16976
|
-
function sentBackNotice2(entry) {
|
|
16977
|
-
const where = entry.number === null ? `in phase "${entry.phase}"` : `in phase ${entry.number}, "${entry.phase}",`;
|
|
16978
|
-
return `Before anything else: the project's owner sent "${entry.partName}" ${where} back to building: ${entry.note} Add or reopen the tasks that build it. When they are finished, run the close step again.`;
|
|
16979
|
-
}
|
|
16980
|
-
function reviewNoticeText(review) {
|
|
16981
|
-
return [...review.questions.map(questionNotice), ...review.sentBack.map(sentBackNotice2)];
|
|
16982
|
-
}
|
|
16983
|
-
|
|
16984
16876
|
// ../events/dist/device-auth.js
|
|
16985
16877
|
var utcIso86012 = external_exports.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/, "must be a UTC ISO-8601 timestamp ending in Z");
|
|
16986
16878
|
var DEVICE_AUTH_STATUS = {
|
|
@@ -17080,11 +16972,126 @@ var DASHBOARD_URL = "https://app.halfcycle.ai";
|
|
|
17080
16972
|
function projectPageUrl(engagementId) {
|
|
17081
16973
|
return isEngagementId(engagementId) ? `${DASHBOARD_URL}/${encodeURIComponent(engagementId)}` : void 0;
|
|
17082
16974
|
}
|
|
16975
|
+
function systemViewUrl(engagementId, phase) {
|
|
16976
|
+
const page = projectPageUrl(engagementId);
|
|
16977
|
+
if (page === void 0)
|
|
16978
|
+
return void 0;
|
|
16979
|
+
return `${page}/console/system-view?${new URLSearchParams({ phase }).toString()}`;
|
|
16980
|
+
}
|
|
17083
16981
|
function requestAccessSentence(engagementId) {
|
|
17084
16982
|
const page = projectPageUrl(engagementId) ?? "this project's page on Halfcycle";
|
|
17085
16983
|
return `To ask for access, open ${page} signed in as this account and choose "Request access". Then let the project's owner know, so they can approve it.`;
|
|
17086
16984
|
}
|
|
17087
16985
|
|
|
16986
|
+
// ../events/dist/scope-notices.js
|
|
16987
|
+
var scopePartNameSchema = external_exports.string().min(1).max(SYSTEM_PART_NAME_MAX);
|
|
16988
|
+
var scopeNoteEntrySchema = external_exports.object({
|
|
16989
|
+
part: scopePartNameSchema.optional(),
|
|
16990
|
+
note: external_exports.string().min(1).max(SCOPE_NOTE_MAX)
|
|
16991
|
+
}).strict();
|
|
16992
|
+
var scopeSentBackSchema = external_exports.object({
|
|
16993
|
+
phase: scopePhaseSchema,
|
|
16994
|
+
number: external_exports.number().int().min(1),
|
|
16995
|
+
notes: external_exports.array(scopeNoteEntrySchema).min(1).max(PHASE_PLAN_CHANGES_MAX + 1)
|
|
16996
|
+
}).strict().superRefine((entry, ctx) => {
|
|
16997
|
+
entry.notes.forEach((n, i) => {
|
|
16998
|
+
if (n.part === void 0 && i !== entry.notes.length - 1) {
|
|
16999
|
+
ctx.addIssue({
|
|
17000
|
+
code: external_exports.ZodIssueCode.custom,
|
|
17001
|
+
path: ["notes", i],
|
|
17002
|
+
message: "the note on the whole phase comes after every note on a part"
|
|
17003
|
+
});
|
|
17004
|
+
}
|
|
17005
|
+
});
|
|
17006
|
+
});
|
|
17007
|
+
var scopeWaitingSchema = external_exports.object({
|
|
17008
|
+
phase: scopePhaseSchema,
|
|
17009
|
+
number: external_exports.number().int().min(1),
|
|
17010
|
+
changedParts: external_exports.array(scopePartNameSchema).max(PHASE_PLAN_CHANGES_MAX)
|
|
17011
|
+
}).strict();
|
|
17012
|
+
var scopeNoticesSchema = external_exports.object({
|
|
17013
|
+
sentBack: external_exports.array(scopeSentBackSchema),
|
|
17014
|
+
waiting: external_exports.array(scopeWaitingSchema),
|
|
17015
|
+
typedApprovalOffered: external_exports.boolean()
|
|
17016
|
+
}).strict().refine((v) => v.sentBack.length > 0 || v.waiting.length > 0, {
|
|
17017
|
+
message: "carried only when a phase was sent back or waits for the owner"
|
|
17018
|
+
});
|
|
17019
|
+
function quotedParts(parts) {
|
|
17020
|
+
return parts.map((p) => `"${p}"`).join(", ");
|
|
17021
|
+
}
|
|
17022
|
+
function approvalSentence(phase, offerTyping) {
|
|
17023
|
+
if (offerTyping === "off")
|
|
17024
|
+
return TYPED_APPROVAL_OFF_SENTENCE;
|
|
17025
|
+
if (offerTyping === "update")
|
|
17026
|
+
return CLIENT_UPDATE_SENTENCE;
|
|
17027
|
+
return `In their own Claude Code session, they ask to see the plan, check each part, and then type: approve ${phase}`;
|
|
17028
|
+
}
|
|
17029
|
+
function phaseWords(phase) {
|
|
17030
|
+
return `phase "${phase}"`;
|
|
17031
|
+
}
|
|
17032
|
+
function sentBackNotice(entry) {
|
|
17033
|
+
return [
|
|
17034
|
+
`Before anything else: the project's owner sent the scope of ${phaseWords(entry.phase)} back with these notes.`,
|
|
17035
|
+
...entry.notes.map((n) => n.part === void 0 ? `- ${n.note}` : `- "${n.part}": ${n.note}`),
|
|
17036
|
+
`Change the plan to answer every note, then send it again: say "plan the next phase" to start. It then waits for the owner's approval again.`
|
|
17037
|
+
].join("\n");
|
|
17038
|
+
}
|
|
17039
|
+
function systemViewSentence(offerTyping, address) {
|
|
17040
|
+
if (address === void 0)
|
|
17041
|
+
return [];
|
|
17042
|
+
return [offerTyping === "yes" ? `Or they approve it in the System view: ${address}` : `They approve it in the System view: ${address}`];
|
|
17043
|
+
}
|
|
17044
|
+
function waitingNotice(entry, offerTyping, engagementId) {
|
|
17045
|
+
return [
|
|
17046
|
+
...entry.changedParts.length > 0 ? [`These parts changed since the owner last decided on this phase, and wait for their approval: ${quotedParts(entry.changedParts)}.`] : [],
|
|
17047
|
+
`The scope of ${phaseWords(entry.phase)} is waiting for the project's owner to approve it.`,
|
|
17048
|
+
approvalSentence(entry.phase, offerTyping),
|
|
17049
|
+
...systemViewSentence(offerTyping, systemViewUrl(engagementId, entry.phase))
|
|
17050
|
+
].join(" ");
|
|
17051
|
+
}
|
|
17052
|
+
function scopeNoticeText(scope, options) {
|
|
17053
|
+
const omit2 = options.omitActivePhase === true ? options.activePhase : void 0;
|
|
17054
|
+
return {
|
|
17055
|
+
sentBack: scope.sentBack.map(sentBackNotice),
|
|
17056
|
+
waiting: scope.waiting.filter((w) => omit2 === void 0 || w.phase !== omit2).map((w) => waitingNotice(w, options.offerTyping, options.engagementId))
|
|
17057
|
+
};
|
|
17058
|
+
}
|
|
17059
|
+
|
|
17060
|
+
// ../events/dist/review-notices.js
|
|
17061
|
+
var reviewNoticeQuestionSchema = external_exports.object({
|
|
17062
|
+
phase: scopePhaseSchema,
|
|
17063
|
+
number: reviewPhaseNumberSchema,
|
|
17064
|
+
part: systemPartIdSchema,
|
|
17065
|
+
partName: systemPartSchema.shape.name,
|
|
17066
|
+
question: reviewNoteSchema
|
|
17067
|
+
}).strict();
|
|
17068
|
+
var reviewNoticeSentBackSchema = external_exports.object({
|
|
17069
|
+
phase: scopePhaseSchema,
|
|
17070
|
+
number: reviewPhaseNumberSchema,
|
|
17071
|
+
part: systemPartIdSchema,
|
|
17072
|
+
partName: systemPartSchema.shape.name,
|
|
17073
|
+
note: reviewNoteSchema
|
|
17074
|
+
}).strict();
|
|
17075
|
+
var reviewNoticesSchema = external_exports.object({
|
|
17076
|
+
questions: external_exports.array(reviewNoticeQuestionSchema).max(REVIEW_PARTS_MAX),
|
|
17077
|
+
sentBack: external_exports.array(reviewNoticeSentBackSchema).max(REVIEW_PARTS_MAX)
|
|
17078
|
+
}).strict().refine((v) => v.questions.length > 0 || v.sentBack.length > 0, {
|
|
17079
|
+
message: "carried only when a question waits or a part was sent back"
|
|
17080
|
+
});
|
|
17081
|
+
function phaseCalled(phase) {
|
|
17082
|
+
return `phase "${phase}"`;
|
|
17083
|
+
}
|
|
17084
|
+
function questionNotice(entry) {
|
|
17085
|
+
const answer = `${HALFCYCLE_COMMAND} review ${quoteForShell(entry.phase)} --answer ${quoteForShell(entry.part)} "<your answer>"`;
|
|
17086
|
+
return `Before anything else: the project's owner asked about "${entry.partName}" in the review of ${phaseCalled(entry.phase)}: ${entry.question} Answer it with ${answer}.`;
|
|
17087
|
+
}
|
|
17088
|
+
function sentBackNotice2(entry) {
|
|
17089
|
+
return `Before anything else: the project's owner sent "${entry.partName}" in ${phaseCalled(entry.phase)} back to building: ${entry.note} Rebuild it: add or reopen the tasks that build it. For each task that rebuilds it, add a task that reviews the rebuild, held by a different agent from the one that built it. When each review has passed, report the build with the time each task finished, then run the close step again.`;
|
|
17090
|
+
}
|
|
17091
|
+
function reviewNoticeText(review) {
|
|
17092
|
+
return [...review.questions.map(questionNotice), ...review.sentBack.map(sentBackNotice2)];
|
|
17093
|
+
}
|
|
17094
|
+
|
|
17088
17095
|
// ../events/dist/credential-wire.js
|
|
17089
17096
|
var engagementCredentialResponseSchema = external_exports.object({
|
|
17090
17097
|
engagementId: external_exports.string(),
|
|
@@ -17137,7 +17144,7 @@ var chatScopeRequestSchema = external_exports.discriminatedUnion("act", [
|
|
|
17137
17144
|
chatScopeApproveRequestSchema,
|
|
17138
17145
|
chatScopeSendBackRequestSchema
|
|
17139
17146
|
]);
|
|
17140
|
-
var CHAT_SCOPE_ACTS =
|
|
17147
|
+
var CHAT_SCOPE_ACTS = SCOPE_ACTS;
|
|
17141
17148
|
var chatScopeRecordedSchema = external_exports.object({
|
|
17142
17149
|
outcome: external_exports.literal("recorded"),
|
|
17143
17150
|
act: external_exports.enum(CHAT_SCOPE_ACTS),
|
|
@@ -20413,7 +20420,7 @@ async function observeChanges(sessionId, reply, deps = {}) {
|
|
|
20413
20420
|
var R1_START_NOT_HERE = "Halfcycle cannot count what this phase has changed on this computer yet, because the commit the phase started from is not here. Get the project's latest history, and it counts again at the end of the next reply.";
|
|
20414
20421
|
var R2_START_NOT_ON_BRANCH = "Halfcycle cannot count what this phase has changed on this branch, because the branch does not contain the commit the phase started from. Switch to the branch the phase is built on, and it counts again at the end of the next reply.";
|
|
20415
20422
|
function r3NoStartRecorded(phase) {
|
|
20416
|
-
return `Halfcycle cannot count what phase ${phase} changes, because no starting commit was recorded when it opened. To count from where the project is now, run: ${HALFCYCLE_COMMAND} open-phase ${quoteForShell(phase)} --actor "you" --evidence "<what shows this phase is ready to start>"`;
|
|
20423
|
+
return `Halfcycle cannot count what phase "${phase}" changes, because no starting commit was recorded when it opened. To count from where the project is now, run: ${HALFCYCLE_COMMAND} open-phase ${quoteForShell(phase)} --actor "you" --evidence "<what shows this phase is ready to start>"`;
|
|
20417
20424
|
}
|
|
20418
20425
|
function r4OutsideThePlan(parts) {
|
|
20419
20426
|
const first = parts.length === 1 ? "Halfcycle saw changes to a part this phase's plan does not include:" : "Halfcycle saw changes to parts this phase's plan does not include:";
|
|
@@ -20672,7 +20679,7 @@ function showCommand(phase) {
|
|
|
20672
20679
|
return `\`${HALFCYCLE_COMMAND} plan ${quoteForShell(phase)} --show\``;
|
|
20673
20680
|
}
|
|
20674
20681
|
function recordedLine(act, phase, planVersion) {
|
|
20675
|
-
return act === "approve" ? line(`Approved ${phase}, plan version ${planVersion}, in your session.`) : line(`Sent ${phase} back with your note, plan version ${planVersion}, in your session. The note is given first to the next session that asks what to do.`);
|
|
20682
|
+
return act === "approve" ? line(`Approved "${phase}", plan version ${planVersion}, in your session.`) : line(`Sent "${phase}" back with your note, plan version ${planVersion}, in your session. The note is given first to the next session that asks what to do.`);
|
|
20676
20683
|
}
|
|
20677
20684
|
function notAttendedLine(act) {
|
|
20678
20685
|
return line(`${nothingDone(act)}: approving or sending back by typing counts only when a person types it into an open session.`);
|
|
@@ -20687,7 +20694,7 @@ function showFirstLine(act) {
|
|
|
20687
20694
|
return line(`${nothingDone(act)}: that phase has not been listed here. List its parts first with \`${HALFCYCLE_COMMAND} plan <phase> --show\`, then type the line again.`);
|
|
20688
20695
|
}
|
|
20689
20696
|
function tooOldLine(act, phase) {
|
|
20690
|
-
return line(`${nothingDone(act)}: ${phase} was listed an hour or more ago. List it again with ${showCommand(phase)}, then type the line again within the hour.`);
|
|
20697
|
+
return line(`${nothingDone(act)}: "${phase}" was listed an hour or more ago. List it again with ${showCommand(phase)}, then type the line again within the hour.`);
|
|
20691
20698
|
}
|
|
20692
20699
|
function noteNeededLine() {
|
|
20693
20700
|
return line("Nothing was sent back: a send-back needs a note after the colon saying what should change.");
|
|
@@ -20714,11 +20721,11 @@ function lineForAnswer(act, phase, answer) {
|
|
|
20714
20721
|
case "show-first":
|
|
20715
20722
|
return showFirstLine(act);
|
|
20716
20723
|
case "plan-changed":
|
|
20717
|
-
return line(`${nothingDone(act)}: the plan for ${phase} changed after it was listed here. List it again with ${showCommand(phase)}, check the parts, then type the line again.`);
|
|
20724
|
+
return line(`${nothingDone(act)}: the plan for "${phase}" changed after it was listed here. List it again with ${showCommand(phase)}, check the parts, then type the line again.`);
|
|
20718
20725
|
case "already-approved":
|
|
20719
|
-
return answer.replanNeeded ? line(
|
|
20726
|
+
return answer.replanNeeded ? line(`"${phase}" is already approved, so nothing changed. Some parts wait because the description of the system changed since the plan was written: write the plan for "${phase}" again, run ${showCommand(phase)}, then approve the new version.`) : line(`"${phase}" is already approved, so nothing changed.`);
|
|
20720
20727
|
case "build-started":
|
|
20721
|
-
return line(`${nothingDone(act)}: tasks in ${phase} have started, so its scope can no longer be sent back. A built part goes back at the phase's review.`);
|
|
20728
|
+
return line(`${nothingDone(act)}: tasks in "${phase}" have started, so its scope can no longer be sent back. A built part goes back at the phase's review.`);
|
|
20722
20729
|
case "not-owner":
|
|
20723
20730
|
return notOwnerLine(act);
|
|
20724
20731
|
case "no-owner":
|
|
@@ -20786,17 +20793,20 @@ function reviewWordsLookSecretLine() {
|
|
|
20786
20793
|
function reviewShowFirstLine() {
|
|
20787
20794
|
return line(`${NOTHING_RECORDED}: that review has not been listed here. Say "review what was built" to list it, then type the line again.`);
|
|
20788
20795
|
}
|
|
20796
|
+
function namedPhase(phase) {
|
|
20797
|
+
return `"${phase}"`;
|
|
20798
|
+
}
|
|
20789
20799
|
function reviewPartNotListedLine(part, phase) {
|
|
20790
|
-
return line(`${NOTHING_RECORDED}: "${part}" is not a part of the review of ${phase} as it was listed here.`);
|
|
20800
|
+
return line(`${NOTHING_RECORDED}: "${part}" is not a part of the review of ${namedPhase(phase)} as it was listed here.`);
|
|
20791
20801
|
}
|
|
20792
20802
|
function reviewNothingToAcceptLine(phase) {
|
|
20793
|
-
return line(`${NOTHING_RECORDED}: no built part of ${phase} waits for your decision.`);
|
|
20803
|
+
return line(`${NOTHING_RECORDED}: no built part of ${namedPhase(phase)} waits for your decision.`);
|
|
20794
20804
|
}
|
|
20795
20805
|
function reviewListedTooLongAgoLine(phase) {
|
|
20796
|
-
return line(`${NOTHING_RECORDED}: ${phase} was listed an hour or more ago. ${LIST_AGAIN}, then type the line again within the hour.`);
|
|
20806
|
+
return line(`${NOTHING_RECORDED}: ${namedPhase(phase)} was listed an hour or more ago. ${LIST_AGAIN}, then type the line again within the hour.`);
|
|
20797
20807
|
}
|
|
20798
20808
|
function reviewChangedLine(phase) {
|
|
20799
|
-
return line(`${NOTHING_RECORDED}: the review of ${phase} changed after it was listed here. ${LIST_AGAIN}, then type the line again.`);
|
|
20809
|
+
return line(`${NOTHING_RECORDED}: the review of ${namedPhase(phase)} changed after it was listed here. ${LIST_AGAIN}, then type the line again.`);
|
|
20800
20810
|
}
|
|
20801
20811
|
function reviewAlreadyDecidedLine(name) {
|
|
20802
20812
|
return line(`${NOTHING_RECORDED}: "${name}" is already decided in this review.`);
|
|
@@ -20804,33 +20814,37 @@ function reviewAlreadyDecidedLine(name) {
|
|
|
20804
20814
|
function reviewAwaitingAnswerLine(name) {
|
|
20805
20815
|
return line(`${NOTHING_RECORDED}: "${name}" is waiting for the agent's answer to your question. Once it is in, say "review what was built" to list it again and decide the part.`);
|
|
20806
20816
|
}
|
|
20817
|
+
function reviewAnswerNotListedLine(name) {
|
|
20818
|
+
return line(`${NOTHING_RECORDED}: the review listed here does not show the agent's answer to your question on "${name}". Say "review what was built" to list it again: the answer shows there once it is in, and then you can decide the part.`);
|
|
20819
|
+
}
|
|
20807
20820
|
function reviewSentBackLine(name) {
|
|
20808
20821
|
return line(`${NOTHING_RECORDED}: "${name}" was sent back to building in this round, so it waits for the next round.`);
|
|
20809
20822
|
}
|
|
20810
20823
|
function reviewWalkChangedLine(phase, number4) {
|
|
20811
20824
|
const typed = typedPhaseReference(phase, number4);
|
|
20812
|
-
return line(`${NOTHING_RECORDED}: phase ${phase} cannot close, because its walk was recorded as clean and a defect is now recorded against it. Send the part with the defect back with send back ${typed}/<part>: <what is wrong>; when its tasks are finished, the close step opens the review again with the walk's defects.`);
|
|
20825
|
+
return line(`${NOTHING_RECORDED}: phase ${namedPhase(phase)} cannot close, because its walk was recorded as clean and a defect is now recorded against it. Send the part with the defect back with send back ${typed}/<part>: <what is wrong>; when its tasks are finished, the close step opens the review again with the walk's defects.`);
|
|
20813
20826
|
}
|
|
20814
20827
|
function reviewNoReviewLine(phase) {
|
|
20815
|
-
return line(`${NOTHING_RECORDED}: phase ${phase} has no review open.`);
|
|
20828
|
+
return line(`${NOTHING_RECORDED}: phase ${namedPhase(phase)} has no review open.`);
|
|
20816
20829
|
}
|
|
20817
20830
|
function reviewCloseRefusedLine(phase, steps) {
|
|
20818
20831
|
if (steps.length === 0) {
|
|
20819
|
-
return line(`${NOTHING_RECORDED}: phase ${phase} could not close just now. Type the line again in a minute.`);
|
|
20832
|
+
return line(`${NOTHING_RECORDED}: phase ${namedPhase(phase)} could not close just now. Type the line again in a minute.`);
|
|
20820
20833
|
}
|
|
20821
20834
|
const labels = steps.map(unfinishedStepLabel).join(", ");
|
|
20822
|
-
const head = steps.length === 1 ? `${NOTHING_RECORDED}: phase ${phase} cannot close while 1 of its steps is unfinished: ${labels}.` : `${NOTHING_RECORDED}: phase ${phase} cannot close while ${steps.length} of its steps are unfinished: ${labels}.`;
|
|
20835
|
+
const head = steps.length === 1 ? `${NOTHING_RECORDED}: phase ${namedPhase(phase)} cannot close while 1 of its steps is unfinished: ${labels}.` : `${NOTHING_RECORDED}: phase ${namedPhase(phase)} cannot close while ${steps.length} of its steps are unfinished: ${labels}.`;
|
|
20823
20836
|
return line([head, ...steps.map(unfinishedStepLine), "Then type the line again."].join(" "));
|
|
20824
20837
|
}
|
|
20825
20838
|
function reviewRefusedLine(act) {
|
|
20826
20839
|
return act === "accept" ? line(`${NOTHING_RECORDED}: Halfcycle did not accept the request. Update Halfcycle by running \`${HALFCYCLE_COMMAND}\` in this project's folder, then type the line again.`) : line(`${NOTHING_RECORDED}: the words were not accepted. Reword them in plain words and type the line again.`);
|
|
20827
20840
|
}
|
|
20828
20841
|
function stillWaitingOf(phase, waiting) {
|
|
20842
|
+
const named = namedPhase(phase);
|
|
20829
20843
|
if (waiting === 0)
|
|
20830
|
-
return `No part of ${
|
|
20844
|
+
return `No part of ${named} waits for your decision now.`;
|
|
20831
20845
|
if (waiting === 1)
|
|
20832
|
-
return `1 part of ${
|
|
20833
|
-
return `${waiting} parts of ${
|
|
20846
|
+
return `1 part of ${named} still waits for your decision.`;
|
|
20847
|
+
return `${waiting} parts of ${named} still wait for your decision.`;
|
|
20834
20848
|
}
|
|
20835
20849
|
function stillWaiting(waiting) {
|
|
20836
20850
|
if (waiting === 0)
|
|
@@ -20848,7 +20862,7 @@ function decidedWords(decided) {
|
|
|
20848
20862
|
case "send-back":
|
|
20849
20863
|
return "sent back to building";
|
|
20850
20864
|
case "carry":
|
|
20851
|
-
return decided.carriedTo === void 0 || decided.carriedTo === null ? "carried to the next phase planned" : `carried to phase
|
|
20865
|
+
return decided.carriedTo === void 0 || decided.carriedTo === null ? "carried to the next phase planned" : `carried to phase "${decided.carriedTo.phase}"`;
|
|
20852
20866
|
case "drop":
|
|
20853
20867
|
return "dropped";
|
|
20854
20868
|
default: {
|
|
@@ -20861,14 +20875,15 @@ function reviewRecordedLine(decided, phase, waiting) {
|
|
|
20861
20875
|
return line(`Recorded in your session: "${decided.name}" ${decidedWords(decided)}. ${stillWaitingOf(phase, waiting)}`);
|
|
20862
20876
|
}
|
|
20863
20877
|
function reviewBulkRecordedLine(accepted, phase, waiting) {
|
|
20864
|
-
const
|
|
20878
|
+
const named = namedPhase(phase);
|
|
20879
|
+
const first = accepted === 1 ? `Recorded in your session: 1 part of ${named} accepted.` : `Recorded in your session: ${accepted} parts of ${named} accepted.`;
|
|
20865
20880
|
return line(`${first} ${stillWaiting(waiting)}`);
|
|
20866
20881
|
}
|
|
20867
20882
|
function reviewClosedLine(phase) {
|
|
20868
|
-
return
|
|
20883
|
+
return `Recorded in your session. That was the last decision: phase ${namedPhase(phase)} is closed. Run its close step now, then tell the person what it says.`;
|
|
20869
20884
|
}
|
|
20870
20885
|
function reviewNoPartsClosedLine(phase) {
|
|
20871
|
-
return
|
|
20886
|
+
return `Recorded in your session. Phase ${namedPhase(phase)} had no parts to review, so it is closed. Run its close step now, then tell the person what it says.`;
|
|
20872
20887
|
}
|
|
20873
20888
|
function notDecidableLine(answer) {
|
|
20874
20889
|
const first = answer.parts[0];
|
|
@@ -21010,7 +21025,7 @@ async function checkAndSendReview(match, engagementId, credential, env, opts) {
|
|
|
21010
21025
|
return reviewWordsLookSecretLine();
|
|
21011
21026
|
}
|
|
21012
21027
|
if (part.awaitingAnswer)
|
|
21013
|
-
return
|
|
21028
|
+
return reviewAnswerNotListedLine(part.name);
|
|
21014
21029
|
if (part.sentBack)
|
|
21015
21030
|
return reviewSentBackLine(part.name);
|
|
21016
21031
|
if (!part.decidable)
|
|
@@ -21602,8 +21617,8 @@ async function fetchPositionNotices(url2, bearer, engagementId, fetchFn, deadlin
|
|
|
21602
21617
|
clearTimeout(timer);
|
|
21603
21618
|
}
|
|
21604
21619
|
}
|
|
21605
|
-
function scopeNoticeLines(scope) {
|
|
21606
|
-
const text = scopeNoticeText(scope, { offerTyping: scope.typedApprovalOffered ? "yes" : "off" });
|
|
21620
|
+
function scopeNoticeLines(scope, engagementId) {
|
|
21621
|
+
const text = scopeNoticeText(scope, { engagementId, offerTyping: scope.typedApprovalOffered ? "yes" : "off" });
|
|
21607
21622
|
return [...text.sentBack, ...text.waiting];
|
|
21608
21623
|
}
|
|
21609
21624
|
function defaultWriteErr2(text) {
|
|
@@ -21636,7 +21651,7 @@ async function runRefreshCredential(opts) {
|
|
|
21636
21651
|
if (positionDeadline > 0) {
|
|
21637
21652
|
const notices = await fetchPositionNotices(connection.url, connection.bearer, engagementId, opts.fetchFn ?? globalThis.fetch, positionDeadline);
|
|
21638
21653
|
if (notices?.scope !== void 0)
|
|
21639
|
-
parts.push(...scopeNoticeLines(notices.scope));
|
|
21654
|
+
parts.push(...scopeNoticeLines(notices.scope, engagementId));
|
|
21640
21655
|
if (notices?.review !== void 0)
|
|
21641
21656
|
parts.push(...reviewNoticeText(notices.review));
|
|
21642
21657
|
}
|
package/dist/bin.js
CHANGED
|
File without changes
|
|
@@ -71,6 +71,11 @@ export declare function printItemStartText(text: string): string;
|
|
|
71
71
|
*/
|
|
72
72
|
export declare function latestCloseHeadline(record: BuildRecord): string;
|
|
73
73
|
/**
|
|
74
|
+
* A v3 record whose review ran more than one round says so in its opening line and
|
|
75
|
+
* points down to "Earlier rounds of the review", and the close's walk line names the
|
|
76
|
+
* round that closed the phase (review R-FW10: a reader who stopped at the opening never
|
|
77
|
+
* learned an earlier round said something else).
|
|
78
|
+
*
|
|
74
79
|
* Render a parsed Build Record as markdown: v2's observed and attested halves, which
|
|
75
80
|
* a v3 record carries unchanged, and for a v3 record the owner's review after the
|
|
76
81
|
* latest close (RM1–RM3, feature `close-review-and-carry-drop`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-v2.d.ts","sourceRoot":"","sources":["../../src/build-record/render-v2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"render-v2.d.ts","sourceRoot":"","sources":["../../src/build-record/render-v2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,EAGL,KAAK,WAAW,EAKjB,MAAM,mBAAmB,CAAC;AA8J3B;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAepD;AAKD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASpD;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOvD;AAgMD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAO/D;AAmRD;;;;;;;;;;;;GAYG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAyEvE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-contract.d.ts","sourceRoot":"","sources":["../src/cli-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AAIH,iFAAiF;AACjF,eAAO,MAAM,SAAS,mIAAoI,CAAC;AAE3J,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjD,sDAAsD;AACtD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,2DAA2D;IAC3D,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,+EAA+E;IAC/E,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C,QAAQ,CAAC,WAAW,EAAE,SAAS,eAAe,EAAE,CAAC;CAClD;AAiFD,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAElE;AAED,iDAAiD;AACjD,MAAM,WAAW,SAAS;IACxB,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAmBD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAAE,CAyBxF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMtE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAMvE;AASD;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;CAErB,CAAC;
|
|
1
|
+
{"version":3,"file":"cli-contract.d.ts","sourceRoot":"","sources":["../src/cli-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AAIH,iFAAiF;AACjF,eAAO,MAAM,SAAS,mIAAoI,CAAC;AAE3J,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjD,sDAAsD;AACtD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,2DAA2D;IAC3D,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,+EAA+E;IAC/E,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C,QAAQ,CAAC,WAAW,EAAE,SAAS,eAAe,EAAE,CAAC;CAClD;AAiFD,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAElE;AAED,iDAAiD;AACjD,MAAM,WAAW,SAAS;IACxB,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAmBD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAAE,CAyBxF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMtE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAMvE;AASD;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;CAErB,CAAC;AAyBX;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAa1F"}
|