in2-agent-server 0.20260821.185429
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 +369 -0
- package/agents/plan-requirement.md +32 -0
- package/dist/campfire/configItem.js +201 -0
- package/dist/campfire/configItemDescription.js +379 -0
- package/dist/campfire/deriveFromBundle.js +1013 -0
- package/dist/cli.js +465 -0
- package/dist/core/betaFeedback.js +493 -0
- package/dist/core/chapterInstructions.js +473 -0
- package/dist/core/claudeAssets.js +61 -0
- package/dist/core/gate.js +201 -0
- package/dist/core/ids.js +9 -0
- package/dist/core/install.js +60 -0
- package/dist/core/operatorQa.js +462 -0
- package/dist/core/orgCallMeter.js +178 -0
- package/dist/core/parcels.js +1235 -0
- package/dist/core/paths.js +105 -0
- package/dist/core/phases.js +225 -0
- package/dist/core/planFile.js +251 -0
- package/dist/core/planFragments.js +119 -0
- package/dist/core/readsLog.js +398 -0
- package/dist/core/registration.js +24 -0
- package/dist/core/result.js +38 -0
- package/dist/core/resume.js +233 -0
- package/dist/core/revisionChain.js +351 -0
- package/dist/core/richText.js +61 -0
- package/dist/core/semanticHash.js +89 -0
- package/dist/core/sessionOrg.js +60 -0
- package/dist/core/sfQuery.js +19 -0
- package/dist/core/spawn.js +182 -0
- package/dist/core/supervisorContract.js +230 -0
- package/dist/core/telemetry.js +1297 -0
- package/dist/core/telemetryContext.js +154 -0
- package/dist/core/telemetrySpool.js +244 -0
- package/dist/core/transcriptUpload.js +516 -0
- package/dist/core/update.js +363 -0
- package/dist/core/viewer.js +117 -0
- package/dist/core/workspace.js +92 -0
- package/dist/core/writeGrants.js +93 -0
- package/dist/core/writebackManifest.js +92 -0
- package/dist/direct/applyLoop.js +2516 -0
- package/dist/direct/batchReport.js +510 -0
- package/dist/direct/comparatorNoise.js +75 -0
- package/dist/direct/containers.js +85 -0
- package/dist/direct/contamination.js +221 -0
- package/dist/direct/crud.js +56 -0
- package/dist/direct/destructive.js +168 -0
- package/dist/direct/knownTokens.js +94 -0
- package/dist/direct/lint.js +382 -0
- package/dist/direct/metadataSchema.generated.json +1 -0
- package/dist/direct/metadataSchema.js +179 -0
- package/dist/direct/operatorPage.js +349 -0
- package/dist/direct/orgRepo.js +1531 -0
- package/dist/direct/orgRepoSpawnCount.js +21 -0
- package/dist/direct/plannedScope.js +119 -0
- package/dist/direct/preImageTargets.js +63 -0
- package/dist/direct/refVerify.js +191 -0
- package/dist/direct/registry.js +129 -0
- package/dist/direct/removals.js +262 -0
- package/dist/direct/rollback.js +1513 -0
- package/dist/direct/rollbackRun.js +1360 -0
- package/dist/direct/sessionProjection.js +126 -0
- package/dist/direct/snapshotComparability.js +165 -0
- package/dist/direct/sourceTree.js +113 -0
- package/dist/direct/unstatedChanges.js +106 -0
- package/dist/direct/waveAssembly.js +556 -0
- package/dist/direct/waveCounts.js +19 -0
- package/dist/direct/waveDerivation.js +152 -0
- package/dist/direct/waveGrade.js +185 -0
- package/dist/index.js +90 -0
- package/dist/orgread/customFieldSnapshot.js +48 -0
- package/dist/orgread/fieldMetadata.js +178 -0
- package/dist/orgread/genericSnapshot.js +61 -0
- package/dist/orgread/layoutSnapshot.js +151 -0
- package/dist/orgread/salesforceOrgReader.js +184 -0
- package/dist/orgread/snapshotTypes.js +9 -0
- package/dist/projection/bridge.js +26 -0
- package/dist/projection/diff.js +141 -0
- package/dist/projection/mapmd.js +213 -0
- package/dist/projection/nameAmbiguity.js +106 -0
- package/dist/projection/precedent.js +136 -0
- package/dist/projection/project.js +214 -0
- package/dist/projection/scope.js +110 -0
- package/dist/projection/types.js +5 -0
- package/dist/tools/analyze.js +322 -0
- package/dist/tools/auth.js +915 -0
- package/dist/tools/campfire.js +1742 -0
- package/dist/tools/closeBatch.js +154 -0
- package/dist/tools/closeText.js +35 -0
- package/dist/tools/direct.js +1613 -0
- package/dist/tools/feedback.js +318 -0
- package/dist/tools/operator.js +287 -0
- package/dist/tools/org.js +739 -0
- package/dist/tools/phase.js +249 -0
- package/dist/tools/projection.js +172 -0
- package/dist/tools/session.js +313 -0
- package/dist/tools/update.js +82 -0
- package/dist/tools/waves.js +793 -0
- package/package.json +48 -0
- package/reference/campfire-configuration-items-guide.md +710 -0
- package/reference/deployability-cribs.md +119 -0
- package/reference/operator-voice.md +141 -0
- package/reference/org-read-cribs.md +34 -0
- package/reference/scoped-dml-interim.md +68 -0
- package/reference/supervisor-playbook.md +313 -0
- package/reference/templates.md +233 -0
- package/skills/in2-delivery/SKILL.md +322 -0
- package/skills/in2-delivery/references/campfire-configuration-items-guide.md +710 -0
- package/skills/in2-delivery/references/deployability-cribs.md +119 -0
- package/skills/in2-delivery/references/operator-voice.md +141 -0
- package/skills/in2-delivery/references/org-read-cribs.md +34 -0
- package/skills/in2-delivery/references/scoped-dml-interim.md +68 -0
- package/skills/in2-delivery/references/templates.md +233 -0
- package/skills/plan-requirement/SKILL.md +188 -0
- package/viewer/index.html +899 -0
- package/viewer/server.mjs +433 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { fail, internalError, ok } from "../core/result.js";
|
|
3
|
+
import { WorkspaceError } from "../core/workspace.js";
|
|
4
|
+
import { SessionOrgError, resolveSessionOrg } from "../core/sessionOrg.js";
|
|
5
|
+
import { closeBatchTelemetry } from "../core/telemetryContext.js";
|
|
6
|
+
import { batchReportArtifacts, composeBatchReport, renderBatchReport, writeBatchReportArtifacts } from "../direct/batchReport.js";
|
|
7
|
+
import { renderOperatorPage } from "../direct/operatorPage.js";
|
|
8
|
+
import { installPendingUpdate } from "../core/update.js";
|
|
9
|
+
import { loadRequirementsIndex, loadSession } from "./session.js";
|
|
10
|
+
import { composeCloseText } from "./closeText.js";
|
|
11
|
+
/**
|
|
12
|
+
* THE EXPLICIT END OF A BATCH.
|
|
13
|
+
*
|
|
14
|
+
* Before this tool existed, a batch had no end — five subsystems in `core/telemetry.ts` each
|
|
15
|
+
* guessed at one with `process.once("beforeExit", …)`, and the guess was wrong in production:
|
|
16
|
+
* 7 batches, 0 terminal; 0 transcripts uploaded; no session ever produced a contamination report.
|
|
17
|
+
*
|
|
18
|
+
* Measured cause (see `registerBatchCloser` in core/telemetryContext.ts): the MCP client closes
|
|
19
|
+
* stdin, waits 2000 ms, then SIGTERMs. `beforeExit` fires only if the event loop drains inside that
|
|
20
|
+
* window — one still-ref'd handle and it never fires at all — and no signal handler gets more time.
|
|
21
|
+
* Every step that mattered was network work that could not finish in two seconds.
|
|
22
|
+
*
|
|
23
|
+
* So finalization happens HERE instead, in a tool call, while the server is alive and unhurried,
|
|
24
|
+
* and the artifacts are RETURNED rather than only written — a report the supervisor cannot read is
|
|
25
|
+
* a report that does not reach the operator.
|
|
26
|
+
*/
|
|
27
|
+
export function registerCloseBatchTools(server) {
|
|
28
|
+
server.registerTool("close_batch", {
|
|
29
|
+
description: "END THE BATCH. Call this ONCE, as the LAST tool call of a delivery run, after the final wave and any Campfire writeback — including when the run ended badly (waves rejected, blocked, or abandoned). " +
|
|
30
|
+
"It is the only thing that gives a batch an end: it states the batch's terminal result to the ledger, assembles and writes the closing evidence, and ships everything that was waiting on the end of the run (provenance parcels, the session transcript, any unflushed events). " +
|
|
31
|
+
"Nothing else does this. A run that is never closed reads as ABANDONED on the IN2 dashboard no matter how well it went, and its evidence never leaves the machine. " +
|
|
32
|
+
"RETURNS the technical spine for the operator's end-results page: the COMPUTED summary counts (`scope`: how many configurations were planned, how many the org read-back proved, how many still need a person, and the automation rate) plus per-wave verdicts and rollback coverage, batch-level findings, the delivery log with its drift explanations, and the contamination report. " +
|
|
33
|
+
"USE `scope` VERBATIM for the page's summary panel — do NOT re-count configurations from the evidence bundles. Those numbers are derived once, at Configuration Item grain, from what the approved plans asked for; a hand-derived second count is how a run reported 205 components as 94 configurations. A null `scope` means this batch never recorded what it was asked for: say the rate is unavailable rather than printing a zero. " +
|
|
34
|
+
"RETURNS `operatorPage`: the operator's results page, ALREADY RENDERED. Paste it verbatim as the top of your reply and write only what belongs below it — the manual steps, rollback, notes and the technical section. Do NOT recompose it, reorder it, or re-count anything in it; it is derived from the same numbers `scope` reports, and a hand-written second version is how the page came to differ on every run. " +
|
|
35
|
+
"Local-only evidence: the report names components, and component identity never enters the ledger. Safe to call more than once — the batch closes at most once per server process and later calls return the same result. " +
|
|
36
|
+
"This is the ONLY correct way to end a run; do not rely on the session simply stopping.",
|
|
37
|
+
inputSchema: {
|
|
38
|
+
sessionId: z
|
|
39
|
+
.string()
|
|
40
|
+
.describe("The session whose batch to close. The org is derived from the session, exactly as it is for every other org-touching tool — there is no org to name and none to get wrong.")
|
|
41
|
+
}
|
|
42
|
+
}, async ({ sessionId }) => {
|
|
43
|
+
try {
|
|
44
|
+
const session = await loadSession(sessionId);
|
|
45
|
+
const { alias, orgId } = await resolveSessionOrg(session, "target", { verify: false });
|
|
46
|
+
if (!orgId) {
|
|
47
|
+
return fail("ORG_NOT_BOUND", `Session ${sessionId} is bound to alias ${JSON.stringify(alias)} but recorded no Org ID, and both the mirror and the read-set are org-keyed. Re-bind the session (activate_session, or create_session { targetOrgAlias, targetOrgId }).`);
|
|
48
|
+
}
|
|
49
|
+
// Order matters, and it is the opposite of what it looks like.
|
|
50
|
+
//
|
|
51
|
+
// The report is composed and written FIRST, from this tool's own arguments, so the operator
|
|
52
|
+
// gets it even if shipping fails entirely — a local artifact is worth more than a network
|
|
53
|
+
// round-trip. The telemetry closer then runs the same report writer again behind its own
|
|
54
|
+
// once-guard, which is a no-op re-render rather than a second computation of anything sent.
|
|
55
|
+
const report = await composeBatchReport({
|
|
56
|
+
sessionId,
|
|
57
|
+
orgId,
|
|
58
|
+
...(alias ? { orgAlias: alias } : {})
|
|
59
|
+
});
|
|
60
|
+
const rendered = renderBatchReport(report);
|
|
61
|
+
const written = await writeBatchReportArtifacts(report, rendered);
|
|
62
|
+
// FAIL-OPEN, like every other piece of closing bookkeeping. A missing requirements index
|
|
63
|
+
// costs the page its titles, never the close its result — `close_batch` must still close
|
|
64
|
+
// when everything else has gone wrong, and that guard is not negotiable.
|
|
65
|
+
//
|
|
66
|
+
// BUT NOT SILENTLY. A bare `catch { operatorPage = "" }` turned any renderer throw into an
|
|
67
|
+
// empty page with no note anywhere: the operator saw a close with no summary and no reason
|
|
68
|
+
// for its absence, and a later reader had nothing to find. The failure is now carried out
|
|
69
|
+
// as a closing note, which reaches both the returned text and the payload, without ever
|
|
70
|
+
// reaching the return value's success.
|
|
71
|
+
let operatorPage = "";
|
|
72
|
+
let pageFailure = null;
|
|
73
|
+
try {
|
|
74
|
+
operatorPage = renderOperatorPage(report, await loadRequirementsIndex(sessionId));
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
operatorPage = "";
|
|
78
|
+
pageFailure =
|
|
79
|
+
`the operator's results page could NOT be rendered (${error instanceof Error ? error.message : String(error)}) — ` +
|
|
80
|
+
`the batch still closed and every count below is intact. State the result and the \`scope\` counts in plain language; do not reconstruct the page by hand.`;
|
|
81
|
+
}
|
|
82
|
+
// Ship. Awaited, unlike every exit hook this replaces, so what follows is a statement about
|
|
83
|
+
// what happened rather than a hope about what might.
|
|
84
|
+
const outcome = await closeBatchTelemetry();
|
|
85
|
+
// The update activation deferred. AFTER the evidence has shipped, deliberately: this is
|
|
86
|
+
// the last tool call of the run, nothing will lazily import another module, and an
|
|
87
|
+
// `npm install -g` that replaces dist under this process can no longer skew anything. The
|
|
88
|
+
// next session starts on the new version with no one asked to do anything — the reason
|
|
89
|
+
// activation stopped asking (QA rounds 1-2: every "update available" notice was ignored).
|
|
90
|
+
// Fail-open like everything else here: a failed install is a note, never a failed close.
|
|
91
|
+
const updateInstalled = await installPendingUpdate().catch(() => undefined);
|
|
92
|
+
const updateNote = !updateInstalled
|
|
93
|
+
? []
|
|
94
|
+
: updateInstalled.ok && updateInstalled.updated
|
|
95
|
+
? [
|
|
96
|
+
`server updated to ${updateInstalled.toVersion} (this run was on ${updateInstalled.fromVersion}) — the NEXT conversation runs the new version; this one is done either way.`
|
|
97
|
+
]
|
|
98
|
+
: updateInstalled.ok
|
|
99
|
+
? []
|
|
100
|
+
: [`a pending server update could not be installed (${updateInstalled.error ?? "unknown error"}) — the next activation will retry.`];
|
|
101
|
+
const artifacts = batchReportArtifacts(sessionId);
|
|
102
|
+
const shipping = [
|
|
103
|
+
...(outcome
|
|
104
|
+
? outcome.notes
|
|
105
|
+
: ["telemetry is disabled on this install (CC_MCP_TELEMETRY=0) — nothing was sent, and nothing was expected to be"]),
|
|
106
|
+
...updateNote,
|
|
107
|
+
// FIRST-CLASS, not appended as an afterthought: this is the note that explains an empty
|
|
108
|
+
// `operatorPage`, and it must survive into the payload as well as the text.
|
|
109
|
+
...(pageFailure ? [pageFailure] : [])
|
|
110
|
+
];
|
|
111
|
+
const text = composeCloseText({
|
|
112
|
+
operatorPage,
|
|
113
|
+
rendered,
|
|
114
|
+
artifactPath: artifacts.markdown,
|
|
115
|
+
written: written !== null,
|
|
116
|
+
shipping
|
|
117
|
+
});
|
|
118
|
+
// The mirror (ok()'s `text`) carries the operator page a SECOND time here — once inside
|
|
119
|
+
// the paste fence, once under `operatorPage`. Deliberate, reviewed 2026-08-21: this fires
|
|
120
|
+
// once per run, and the fence-with-page-inside is the deliverable whose verbatim relay
|
|
121
|
+
// exists because hand re-derivation miscounted a results page twice (QA rounds 1 and 2).
|
|
122
|
+
// Slimming the mirrored text to a pointer would reopen exactly that. direct_history made
|
|
123
|
+
// the opposite call (text overridden to a pointer) because its duplicate is an uncapped
|
|
124
|
+
// git patch on a tool called many times a run.
|
|
125
|
+
return ok(text, {
|
|
126
|
+
sessionId,
|
|
127
|
+
orgId,
|
|
128
|
+
result: report.result,
|
|
129
|
+
// THE FOUR COUNTS, COMPUTED. The page's summary panel is composed from these rather than
|
|
130
|
+
// hand-derived from evidence bundles at the end of a long run — which is how QA round 1
|
|
131
|
+
// item 24 happened (205 components reported as 94 configurations) and QA round 2 repeated
|
|
132
|
+
// it. `null` means this batch never recorded what it was asked for: state no rate, never
|
|
133
|
+
// a zero one.
|
|
134
|
+
scope: report.scope,
|
|
135
|
+
// The finished page, for a client that would rather render than parse.
|
|
136
|
+
operatorPage,
|
|
137
|
+
deliveredWaves: report.deliveredWaves,
|
|
138
|
+
problemWaves: report.problemWaves,
|
|
139
|
+
practiceRuns: report.practiceRuns,
|
|
140
|
+
findings: report.findings,
|
|
141
|
+
artifacts: written ? artifacts : null,
|
|
142
|
+
closed: outcome?.finalized ?? false,
|
|
143
|
+
shipping
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
if (error instanceof SessionOrgError)
|
|
148
|
+
return fail(error.code, error.message);
|
|
149
|
+
if (error instanceof WorkspaceError)
|
|
150
|
+
return fail(error.code, error.message);
|
|
151
|
+
return internalError(error);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// HOW A CLOSE READS, ASSEMBLED.
|
|
2
|
+
//
|
|
3
|
+
// Extracted from the `close_batch` handler so the branch that matters — whether the operator's
|
|
4
|
+
// finished page leads the result or is absent entirely — is reachable from a test without a
|
|
5
|
+
// session, an org, or a workspace on disk.
|
|
6
|
+
export function composeCloseText(input) {
|
|
7
|
+
return [
|
|
8
|
+
// THE OPERATOR'S PAGE, FINISHED. It leads because the supervisor reads this result top down,
|
|
9
|
+
// and the technical spine below it used to be the first thing found — which is how the page
|
|
10
|
+
// came to be re-derived by hand on every run.
|
|
11
|
+
...(input.operatorPage
|
|
12
|
+
? [
|
|
13
|
+
`=== PASTE THE BLOCK BELOW VERBATIM AS THE OPERATOR'S RESULTS PAGE ===`,
|
|
14
|
+
``,
|
|
15
|
+
input.operatorPage,
|
|
16
|
+
``,
|
|
17
|
+
`=== END OF BLOCK. Everything below is yours, not the operator's: write the "Still to do" items, rollback, notes and the technical section beneath the pasted block. ===`,
|
|
18
|
+
``,
|
|
19
|
+
`---`,
|
|
20
|
+
``
|
|
21
|
+
]
|
|
22
|
+
: []),
|
|
23
|
+
input.rendered,
|
|
24
|
+
``,
|
|
25
|
+
`---`,
|
|
26
|
+
``,
|
|
27
|
+
`## Batch close`,
|
|
28
|
+
``,
|
|
29
|
+
input.written
|
|
30
|
+
? `Evidence written to ${input.artifactPath} (and batch-report.json beside it).`
|
|
31
|
+
: `Evidence could NOT be written to ${input.artifactPath} — the report above is the only copy.`,
|
|
32
|
+
``,
|
|
33
|
+
...input.shipping.map((note) => `- ${note}`)
|
|
34
|
+
].join("\n");
|
|
35
|
+
}
|