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.
Files changed (115) hide show
  1. package/README.md +369 -0
  2. package/agents/plan-requirement.md +32 -0
  3. package/dist/campfire/configItem.js +201 -0
  4. package/dist/campfire/configItemDescription.js +379 -0
  5. package/dist/campfire/deriveFromBundle.js +1013 -0
  6. package/dist/cli.js +465 -0
  7. package/dist/core/betaFeedback.js +493 -0
  8. package/dist/core/chapterInstructions.js +473 -0
  9. package/dist/core/claudeAssets.js +61 -0
  10. package/dist/core/gate.js +201 -0
  11. package/dist/core/ids.js +9 -0
  12. package/dist/core/install.js +60 -0
  13. package/dist/core/operatorQa.js +462 -0
  14. package/dist/core/orgCallMeter.js +178 -0
  15. package/dist/core/parcels.js +1235 -0
  16. package/dist/core/paths.js +105 -0
  17. package/dist/core/phases.js +225 -0
  18. package/dist/core/planFile.js +251 -0
  19. package/dist/core/planFragments.js +119 -0
  20. package/dist/core/readsLog.js +398 -0
  21. package/dist/core/registration.js +24 -0
  22. package/dist/core/result.js +38 -0
  23. package/dist/core/resume.js +233 -0
  24. package/dist/core/revisionChain.js +351 -0
  25. package/dist/core/richText.js +61 -0
  26. package/dist/core/semanticHash.js +89 -0
  27. package/dist/core/sessionOrg.js +60 -0
  28. package/dist/core/sfQuery.js +19 -0
  29. package/dist/core/spawn.js +182 -0
  30. package/dist/core/supervisorContract.js +230 -0
  31. package/dist/core/telemetry.js +1297 -0
  32. package/dist/core/telemetryContext.js +154 -0
  33. package/dist/core/telemetrySpool.js +244 -0
  34. package/dist/core/transcriptUpload.js +516 -0
  35. package/dist/core/update.js +363 -0
  36. package/dist/core/viewer.js +117 -0
  37. package/dist/core/workspace.js +92 -0
  38. package/dist/core/writeGrants.js +93 -0
  39. package/dist/core/writebackManifest.js +92 -0
  40. package/dist/direct/applyLoop.js +2516 -0
  41. package/dist/direct/batchReport.js +510 -0
  42. package/dist/direct/comparatorNoise.js +75 -0
  43. package/dist/direct/containers.js +85 -0
  44. package/dist/direct/contamination.js +221 -0
  45. package/dist/direct/crud.js +56 -0
  46. package/dist/direct/destructive.js +168 -0
  47. package/dist/direct/knownTokens.js +94 -0
  48. package/dist/direct/lint.js +382 -0
  49. package/dist/direct/metadataSchema.generated.json +1 -0
  50. package/dist/direct/metadataSchema.js +179 -0
  51. package/dist/direct/operatorPage.js +349 -0
  52. package/dist/direct/orgRepo.js +1531 -0
  53. package/dist/direct/orgRepoSpawnCount.js +21 -0
  54. package/dist/direct/plannedScope.js +119 -0
  55. package/dist/direct/preImageTargets.js +63 -0
  56. package/dist/direct/refVerify.js +191 -0
  57. package/dist/direct/registry.js +129 -0
  58. package/dist/direct/removals.js +262 -0
  59. package/dist/direct/rollback.js +1513 -0
  60. package/dist/direct/rollbackRun.js +1360 -0
  61. package/dist/direct/sessionProjection.js +126 -0
  62. package/dist/direct/snapshotComparability.js +165 -0
  63. package/dist/direct/sourceTree.js +113 -0
  64. package/dist/direct/unstatedChanges.js +106 -0
  65. package/dist/direct/waveAssembly.js +556 -0
  66. package/dist/direct/waveCounts.js +19 -0
  67. package/dist/direct/waveDerivation.js +152 -0
  68. package/dist/direct/waveGrade.js +185 -0
  69. package/dist/index.js +90 -0
  70. package/dist/orgread/customFieldSnapshot.js +48 -0
  71. package/dist/orgread/fieldMetadata.js +178 -0
  72. package/dist/orgread/genericSnapshot.js +61 -0
  73. package/dist/orgread/layoutSnapshot.js +151 -0
  74. package/dist/orgread/salesforceOrgReader.js +184 -0
  75. package/dist/orgread/snapshotTypes.js +9 -0
  76. package/dist/projection/bridge.js +26 -0
  77. package/dist/projection/diff.js +141 -0
  78. package/dist/projection/mapmd.js +213 -0
  79. package/dist/projection/nameAmbiguity.js +106 -0
  80. package/dist/projection/precedent.js +136 -0
  81. package/dist/projection/project.js +214 -0
  82. package/dist/projection/scope.js +110 -0
  83. package/dist/projection/types.js +5 -0
  84. package/dist/tools/analyze.js +322 -0
  85. package/dist/tools/auth.js +915 -0
  86. package/dist/tools/campfire.js +1742 -0
  87. package/dist/tools/closeBatch.js +154 -0
  88. package/dist/tools/closeText.js +35 -0
  89. package/dist/tools/direct.js +1613 -0
  90. package/dist/tools/feedback.js +318 -0
  91. package/dist/tools/operator.js +287 -0
  92. package/dist/tools/org.js +739 -0
  93. package/dist/tools/phase.js +249 -0
  94. package/dist/tools/projection.js +172 -0
  95. package/dist/tools/session.js +313 -0
  96. package/dist/tools/update.js +82 -0
  97. package/dist/tools/waves.js +793 -0
  98. package/package.json +48 -0
  99. package/reference/campfire-configuration-items-guide.md +710 -0
  100. package/reference/deployability-cribs.md +119 -0
  101. package/reference/operator-voice.md +141 -0
  102. package/reference/org-read-cribs.md +34 -0
  103. package/reference/scoped-dml-interim.md +68 -0
  104. package/reference/supervisor-playbook.md +313 -0
  105. package/reference/templates.md +233 -0
  106. package/skills/in2-delivery/SKILL.md +322 -0
  107. package/skills/in2-delivery/references/campfire-configuration-items-guide.md +710 -0
  108. package/skills/in2-delivery/references/deployability-cribs.md +119 -0
  109. package/skills/in2-delivery/references/operator-voice.md +141 -0
  110. package/skills/in2-delivery/references/org-read-cribs.md +34 -0
  111. package/skills/in2-delivery/references/scoped-dml-interim.md +68 -0
  112. package/skills/in2-delivery/references/templates.md +233 -0
  113. package/skills/plan-requirement/SKILL.md +188 -0
  114. package/viewer/index.html +899 -0
  115. package/viewer/server.mjs +433 -0
@@ -0,0 +1,188 @@
1
+ ---
2
+ name: plan-requirement
3
+ description: "Decompose Salesforce requirements into direct-tier deliverable components against a shared org projection and analysis brief — one requirement per analyzer by default, a coupled group, or one fragment of an oversized requirement — and surface blockers/assumptions for the supervisor's consolidated card. Use for each parallel requirement-analysis Task in the direct-tier cc-mcp flow."
4
+ ---
5
+ <!-- GENERATED from apps/cc-mcp-server/harness/skills/plan-requirement/SKILL.md by scripts/sync-plugin-skills.mjs.
6
+ source-sha256: 07bab215186991d2
7
+ Edit that source file, then run `npm run sync:plugin`. Do not edit this copy. -->
8
+
9
+ # Plan a requirement (direct working tier)
10
+
11
+ You analyze the requirement(s) your Task prompt assigned you for the DIRECT working tier: read your section(s) of the supervisor's brief, then the requirement prose, ground it against the **shared projection** the supervisor already captured, decompose it into deployable components, surface its gaps/blockers/ambiguities, author and check what you can, write `plan.json`, and stop. You run in parallel with other analyzers — stay in your lane (the requirement(s), or the one fragment, your prompt named).
12
+
13
+ **The projection is your ground truth; the org is your fallback and your check.** Prefer the projection — it is already on disk and costs nothing. But you may READ the org where the projection falls short (`describe_object`, `list_components`, `sf_read`), and you may ask it to VALIDATE what you authored (`validate_components`, a checkOnly that changes nothing). What you never do is WRITE: `project_org` and `direct_apply` are the supervisor's, after the operator approves.
14
+ Normally you own exactly ONE requirement. Two other modes exist, and your Task prompt says when either applies — see **Modes** below: a coupled GROUP of 2-3 requirements (you write one plan.json PER requirement), or one FRAGMENT of an oversized requirement (you write `plan.fragment-<n>.json` and the supervisor merges).
15
+
16
+ ## Inputs (given to you)
17
+ - **The brief** — `<sessionDir>/analysis/brief.md`, the supervisor's batch model as a session artifact. A shared preamble (batch shape, shared objects, the dependency ladder, decisions in force — including operator answers from the early round) plus one delimited section per requirement (your dependencies, your siblings, the trap you cannot see from your own text, ownership of shared components). **Read the preamble and your section(s) FIRST**, before the requirement prose. Check the end for dated amendments — a re-dispatched analyzer reads the CURRENT brief, and the answer that re-dispatched you is appended there.
18
+ - **Decisions bind; descriptions don't.** A DECISION in the brief (an operator answer, an ownership assignment, a pinned convention) is never silently deviated from. But binding is not unchallengeable: if the projection or the artifact shows a decision is wrong, surface the disagreement as a BLOCKER citing your evidence — never silently comply, never silently override. The brief carries POINTERS to artifacts — read the artifact, never a paraphrase of it.
19
+ - The brief is READ-ONLY for you. Never edit it; your channel back to the supervisor is your plan (blockers, assumptions) and your returned summary.
20
+ - `requirements/<extId>/source/requirement.md` — the requirement prose.
21
+ - The shared projection dir (the supervisor's `project_org` output): `MAP.md` (the index) + `objects/…` / `components/…` per-component JSON, in the gate's normalized shapes. This is the org's ACTUAL current state — trust it over the requirement's words.
22
+ - **The org itself, read-only.** `describe_object`, `list_components` and `sf_read` are yours to use when the projection does not answer your question. Prefer the projection — it is already on disk and costs nothing — but do NOT plan against a gap in it. `project_org` stays the supervisor's: it is ten times more expensive and writes a file tree, and fifteen of you running it is the one case that genuinely would hurt.
23
+
24
+ ## Modes — one requirement, a coupled group, or a fragment
25
+
26
+ Your Task prompt names your mode. The steps below are the same in all three; what changes is what you own and what you write.
27
+
28
+ - **One requirement (the default).** You own `<extId>`; you write `requirements/<extId>/plan.json`. Everything below reads naturally.
29
+ - **A coupled group (2-3 requirements).** The supervisor grouped them because they are genuinely coupled — one builds what another modifies or deletes, a shared ordered ladder, a contradiction needing one plan — and you hold the whole chain in one head. Work them in dependency order, and **write ONE plan.json PER requirement** (`requirements/<extId>/plan.json` for each, its own `authored/` tree beside it), each listing only what THAT requirement owns — the per-requirement artifact contract is inviolable; a merged "group plan" breaks `plan_waves`, Configuration Item ownership and writeback all at once. Write each plan.json as you finish that requirement rather than holding all of them to the end: a finished plan persists, so if you die mid-group the supervisor re-dispatches only what is missing. Cross-requirement edges inside your group are ordinary `dependsOn` keys plus `intent` — being grouped changes who analyzes them, never the artifact shape.
30
+ - **A fragment of an oversized requirement.** The supervisor split one requirement BY DELIVERABLE AREA and you own one disjoint area of it. Write `requirements/<extId>/plan.fragment-<n>.json` — exactly the plan.json schema, scoped to your area — with your `authored/` files at their normal paths under the requirement's own tree. Your fragment is NOT the canonical plan: the supervisor merges every fragment into the one `requirements/<extId>/plan.json` and archives the fragments; never write to `plan.json` yourself in this mode. Stay strictly inside your area — fragments never author the same files, and a component another fragment owns is not even a `dependsOn` unless your components genuinely require it to exist first. The brief pins shared naming, conventions and container ownership; where two areas both need facet-level edits to a shared container (an object both areas touch), the brief says who owns the container, and the non-owner records a `coverageRoute` to the existing `objectFacetUpdates` mechanism rather than authoring a second copy of the container file.
31
+
32
+ ## Steps
33
+
34
+ 1. **Read** the brief's preamble and your requirement section(s) — including any dated amendments at the end — then the requirement prose and the projection `MAP.md` for the touched objects.
35
+ 2. **Decompose** into the smallest independently-deliverable components (NOT the smallest API call — keep writes together when splitting them creates a meaningless intermediate state). For each, name the `typeName` + `fullName`.
36
+ 3. **Ground each component against the projection** (the files first; read the org where they fall short): - **Requirement-asserted API names are UNTRUSTED** — if the requirement names a field/object/profile, confirm it in the projection; a divergence (asserted `Foo__c` vs org's `Bar__c`; asserted "permission set" that is actually a PSG) is a blocker or an assumption, never a silent guess.
37
+ - **Declare `intent`** — `"create"` when this requirement brings the component into being, `"update"` when it changes something that is already there (in the org, or that another requirement in this batch creates), `"delete"` when it REMOVES the component. REQUIRED on every entry (`INVALID_INTENT`). It is what the pipeline orders on: `plan_waves` derives a create-before-update edge from it and cross-checks it against the projection before anything is deployed. **A delete is never inferred** — no reading of the org can mean "someone wanted this gone". Say it or it does not happen.
38
+ - Classify `status`: `missing` (nothing there — the `create` case), `exists` (already there — either nothing to do, or an `update`), or **`overwrite_hazard`** (the requirement says "create" but it already exists — flag it; a full-file create would clobber it, and the honest declaration is `intent: "update"` on a file that carries the org's current state forward).
39
+ - Classify `kind`: `xml` (single-file), `content` (EmailTemplate/StaticResource/Document — needs a content body), or `bundle` (LWC/Aura — the direct tier can't deploy these; route them).
40
+ - Classify `deployable`: true for xml/content types the direct tier handles; false for bundles / genuinely-unsupported → a `coverageRoute` (manual Setup / a Deployment Task), not a blocker. A `delete` entry needs NO `deployable` flag — its intent already says it leaves by the destructive path.
41
+ - **Before classifying ANYTHING `deployable: false`, read `reference/deployability-cribs.md`.** Every verdict in it was proven live in the client QA org. You may only claim a PLATFORM limit that its "genuinely impossible" list already contains (three items). Quick actions on layouts, utility-bar sizing, record-page activation, Lightning email templates, record type visibility — all previously handed back as manual — are deployable, and the cribs carry the exact XML shape that works plus the rejection texts our wrong shapes produce. Membership/assignment/custom-setting VALUES are records (DML), not metadata: route them to a Deployment Task that says "awaiting the DML write path" and cites the cribs — never one that claims the platform cannot do it.
42
+ - **Every `deployable: false` entry carries `routeCause`, and it is a metric claim, not a label.** `"not_metadata"` — the outcome is sObject rows per the cribs' DML cluster (membership, assignment, custom setting values, the email-template Folder). `"impossible"` — on the cribs' three-item impossible list, nothing else. OMIT the field for ordinary manual routing a deploy could have done. The first two leave the automation-rate denominator entirely (no deploy could ever satisfy them, so counting them measures the requirement mix, not the tool); an omitted cause counts against the rate as always. Misuse is not neutral: tagging ordinary manual work `"not_metadata"` inflates the certified rate, which is the exact defect class QA2-009/013 documents — when unsure, omit.
43
+ - `dependsOn`: component keys that must exist FIRST (`CustomObject:CF65_X__c`) — cross-requirement or existing-org.
44
+ - **A `ListView` the requirement REMOVES is a manual-Setup `coverageRoute` by default**: Salesforce refused one through the deployment API with `cannot delete last filter` (live-caught 2026-08-03, on a view nothing referenced), so "nothing references it" is not evidence that it will delete.
45
+ 4. **Surface blockers and assumptions** (assume-and-flag):
46
+ - Obvious, reversible, mechanically-derivable details (labels, plurals, description text): record an `assumption` with a rationale — do NOT open a blocker.
47
+ - Material ambiguity (business meaning, value sets implied but not stated, access scope, the "Assigned"-status-that-doesn't-exist case, anything irreversible): open a `blocker` with a `recommendedAnswer` prefilled. Blockers are your ONLY question channel — you never ask the operator directly; the supervisor consolidates all analyzers' blockers into ONE card.
48
+ - Something the org must already contain: a `dependsOn` entry, not a question.
49
+ 5. **Draft the authoring notes** for each deployable component (`draftNotes`): the field type + values + defaults, the flow's trigger + branches, the validation formula. These are the intent and the facts the operator decided — they stay useful even for components you go on to author, because the supervisor reviews intent, not just XML.
50
+
51
+ 6. **Author the UNBLOCKED components** as source-format files under `requirements/<extId>/authored/`, at their normal source paths (`objects/X__c/fields/Y__c.field-meta.xml`, `layouts/…`, `permissionsets/…`). Record the relative path on the component as `authoredFile`. This is the parallel win: the supervisor edits your draft instead of writing every component itself, and there are N of you.
52
+ - **A blocked component is authored too — as your RECOMMENDED variant, marked `"provisional": true` with `"blockedBy": "<blocker id>"`.** Say in `draftNotes` exactly what changes if the operator picks differently. Author a real FILE rather than describing the design in prose: a file is linted, prose escapes the lint ladder entirely. It is safe because wave assembly refuses a provisional component (`COMPONENT_STILL_PROVISIONAL`) and assembly runs inside `direct_lint`/`direct_apply` — an unapproved design cannot reach the org; the supervisor clears the flag with `resolve_blocker` once the operator answers.
53
+ - Still do NOT author when `deployable: false` — that is a route, not a component, and it belongs in `coverageRoutes` only.
54
+ - **`authoredFile` is the BINDING, not a note.** It is how the pipeline knows which file is this entry's deployable state — the assembler copies exactly that file into the wave it belongs to. Optional when a component has one entry; REQUIRED on every entry of a component that has more than one (`MISSING_REVISION_BINDING`).
55
+ - **A component this requirement CHANGES twice — or that another requirement creates and yours adjusts — is TWO ENTRIES, not one.** Same `typeName`/`fullName`, one entry with `intent: "create"` and one with `intent: "update"`, each with its OWN `authoredFile` at a distinct path, each file carrying the COMPLETE desired state of the component at that point (the tool never composes XML — an update file is a whole component, not a patch). Keep the second file apart from the first under any prefix you like (`r2/…` — see the worked example below). This is the shape to reach for whenever the batch's own work changes something mid-flight — a picklist another requirement widens, an object re-emitted to carry a compact-layout assignment once its fields exist, a field a later requirement re-types. Do NOT fold the later change back into the creating requirement's single file: that hides an update inside a create and mis-attributes it at writeback.
56
+ - **A component this requirement REMOVES is an entry with `intent: "delete"` and NO `authoredFile`.** A deletion has no source file, so binding one is refused (`DELETE_BINDS_FILE`). Do not encode a deletion as an `update` either: that registers your requirement as an amendment on the creating requirement's Configuration Item, for a change that has not landed and may never land. Declare the deletion and the pipeline handles the rest — `plan_waves` reports WHICH WAVE it must follow and hands the supervisor the member list in `direct_apply`'s `deletes` shape; nothing is destroyed by planning it. If the deletion is contentious — it usually is, especially when this batch builds what you are retiring — open a `blocker` as well; declaring it orders it, it does not approve it.
57
+ - Author your OWN components only — a `dependsOn` is something that must EXIST first and that you do not touch, and two requirements CREATING one component is a hard error at assembly (`OWNERSHIP_CONFLICT`). Genuinely modifying what another requirement creates is different: that is yours to author as the `update` entry above.
58
+ - Write ordinary relative paths inside `authored/`. Absolute paths and anything climbing out with `..` are rejected.
59
+ - **If the component ALREADY EXISTS, read the org's current image FIRST and carry every part of it forward.** `Layout` and `PermissionSet` are MEASURED to delete whatever your file omits (a live probe left zero of a layout's 16 related lists, and revoked the two field permissions a PermissionSet did not restate); `Profile`, `SharingRules`, `Workflow`, `CustomLabels` and the `*Rules` types are suspected but unprobed — treat them the same way. `CustomObject` is the measured exception: child components (fields, validation rules) MERGE, so you do not need to restate an object's existing children to add one. Your file is not a patch, it is the whole component. The projection is already on disk, so read that component's JSON and start from what is there rather than authoring the section the requirement asked about and nothing else — and where the wave already retrieved the org's own source XML to `pre/source/`, edit THAT instead: it is the deploy's own dialect and it carries facets the JSON read cannot. A snapshot that could not read a facet says so in its `errors` (`INCOMPLETE_FACET`); treat that facet as unknown, never as empty. `direct_apply` blocks on an unstated drop (`PREFLIGHT_REPLACE_DROPS_UNSTATED`), but that is a backstop for the supervisor and it costs a whole round-trip; the file should be right when you hand it over.
60
+ - **READ THE TOP OF `MAP.md` FIRST.** It carries two sections that change what a correct file looks like and that nothing else reveals: **Org traits** (multi-currency means every layout carries `CurrencyIsoCode` — omit it from an authored Layout and it is DROPPED; no call center means an "if available" softphone requirement is simply not available) and **Proven in this org** (the exact `FlexiPage.componentName` and `CustomTab.motif` values the org has already accepted). `project_org` collects these on every run regardless of scope, so they are there even on a greenfield batch.
61
+ - **The ORG IS THE PRECEDENT — use it before you theorise.** For anything the schema cannot check — a Lightning `componentName`, a tab `motif`, whether some construct is even expressible — a component of the same type that ALREADY EXISTS in the org is proof the org accepts what it contains. Read it: it is in the projection, and `describe_object` / `list_components` / `sf_read` are open to you. `direct_lint` checks these free-string tokens for you (`UNPROVEN_ORG_TOKEN` names the values the org has already accepted), so a warning there is a real answer, not noise.
62
+ - **Do not assert that the platform CANNOT do something without checking.** A claimed limit becomes a blocker, the blocker gets a recommended answer, and the operator approves a design shaped by it — so a wrong one is expensive and nearly invisible. Live: an analyzer stated that Long Text Area fields "are not referenceable from the formula engine" and that a Text Template was "the only supported mechanism". Both false; the org already contained a Flow formula doing exactly that. QA round 2 shipped three more — "no deployment can create a Lightning template folder", "utility bar proven undeployable", "record page activation is manual" — all refuted live in `reference/deployability-cribs.md`, which is now the ONLY source you may cite for an impossibility claim. If it is not in the cribs' impossible list and you cannot find a counter-example in the org, say "I could not verify this" and raise it as a question — never as a fact.
63
+ - You are drafting, not deciding. The supervisor consolidates, clarifies with the operator, edits, orders the waves and applies them (`direct_apply`, which assembles each wave from the files you bound and deploys it in the same call). Nothing you write reaches the org unreviewed.
64
+ 7. **LINT WHAT YOU AUTHORED**, before writing your plan: `direct_lint {sessionId, sourceDir: "requirements/<extId>/authored"}`. Local, milliseconds, no org contact at all.
65
+ - **Pass the `sessionId` and nothing else about grounding** — grounding is automatic; `projection` is an override you do not want here.
66
+ - If the finding says **"no precedent to compare against"**, that is NOT a pass. It means nothing the session has projected holds a component of that type, so nothing was actually checked — say so in your plan and ask the supervisor to widen the projection, rather than treating silence as approval.
67
+ - Fix what is yours to fix: a missing required element, a misplaced element, a nameless nested child. These are typos, not decisions.
68
+ - A finding that is a DECISION becomes a BLOCKER, not a fix. Live example: an approval step routed to a public group returns `SCHEMA_ENUM_VALUE` — Salesforce accepts only a user, queue, hierarchy field or adhoc approver. That is not a typo you can correct; it means the requested design is not expressible, and the operator has to choose the alternative. Caught here it is a round-1 question; caught at wave assembly it is a THIRD round of clarification after everything else was settled (live: CF75).
69
+ - This is the cheapest checkpoint in the whole loop: the same finding costs milliseconds here and a 45-second checkOnly at deploy, where — a deploy being all-or-nothing — it takes every other component in its wave down with it.
70
+
71
+ 7b. **THEN ASK THE ORG**: `validate_components {sessionId, extId}`. It submits the components YOUR plan.json owns as a checkOnly — the org's own authoritative answer — and changes nothing.
72
+ - **Run it after the lint, not instead of it.** The lint ladder is local and free and catches what a schema or a live-caught lemma can express; this catches what only Salesforce knows. A file that lints clean and the org refuses is the normal case, not a surprise.
73
+ - **Record every refusal as a BLOCKER, with the org's message VERBATIM.** Quote Salesforce's sentence — `length must be specified`, `Cannot delete last filter` — never your summary of it. The supervisor consolidates it into the operator's one clarification card, and the operator's decision rests on the org's words, not on a paraphrase two hands removed from the evidence.
74
+ - **A refusal you can fix is a fix, not a blocker** — the same rule as a lint finding. A missing required attribute or a mistyped reference is a typo. A refusal that means the requested DESIGN is not expressible is a blocker, with a `recommendedAnswer` for the alternative.
75
+ - **This is why the check moved here.** The org's refusal used to arrive at deploy time, in the supervisor's serial wave loop, where a refusal takes every other component in its wave down with it and arrives long after you stopped holding the context that produced the file. Now N of us ask at once, while authoring.
76
+ - **A slow call is the QUEUE, not a hang.** Measured: the org serializes concurrent validations at roughly one every 4-5 seconds, so with eight analyzers validating at once your call can take 30s where alone it takes 5s. Wait it out; never retry it.
77
+ - **A TIMEOUT is neither a pass nor a refusal.** The org did not answer. Say exactly that in your plan — never record silence as approval.
78
+
79
+ 8. **Write** `requirements/<extId>/plan.json` (schema below) — one per requirement you own in group mode; `plan.fragment-<n>.json` in fragment mode — and **return** a one-paragraph summary (component count, deployable vs routed, how many you authored, open blocker count; per requirement when you own several). STOP — do not loop, do not touch requirements outside your assignment, do not keep reading the org once your plan is written.
80
+ 9. **If `report_feedback` is among your tools, file your stumbles before returning** — follow its own description for what to file and how. Tool presence IS the flag. You file only what YOU hit; the supervisor files the run's at-close wrap-up.
81
+
82
+ ## plan.json schema
83
+
84
+ `intent` and `authoredFile` are the two load-bearing fields: the first says what this entry does to the component, the second says which file IS that state. There is no `action` field — `intent` replaces it.
85
+
86
+ ```json
87
+ {
88
+ "extId": "REQ-15386",
89
+ "summary": "One-line what this requirement delivers.",
90
+ "components": [
91
+ {
92
+ "typeName": "QuickAction",
93
+ "fullName": "CF65_Case_Readiness__c.CF65_Quick_Intake",
94
+ "intent": "create",
95
+ "kind": "xml",
96
+ "deployable": true,
97
+ "status": "missing",
98
+ "dependsOn": ["CustomObject:CF65_Case_Readiness__c"],
99
+ "operatorDecidedFacets": ["type=Create", "targetObject=CF65_Case_Readiness__c"],
100
+ "provisional": true,
101
+ "blockedBy": "B1",
102
+ "draftNotes": "Object-specific Create action. AUTHORED AS RECOMMENDED VARIANT: predefined field values set to the B1 recommendation. If the operator picks the alternative, change <fieldName> to Status and drop the default — one edit, no re-author.",
103
+ "authoredFile": "quickActions/CF65_Case_Readiness__c.CF65_Quick_Intake.quickAction-meta.xml"
104
+ }
105
+ ],
106
+ "blockers": [
107
+ { "id": "B1", "question": "Which fields should Quick Intake pre-populate?", "recommendedAnswer": "Name + Risk Level (Medium).", "why": "The requirement names the action but not its predefined values." }
108
+ ],
109
+ "assumptions": [
110
+ { "what": "Action label 'Quick Intake'.", "rationale": "Stated verbatim in the requirement." }
111
+ ],
112
+ "coverageRoutes": [
113
+ { "component": "EmailTemplate:unfiled$public/CF65_Ready", "route": "direct-content", "reason": "content-file type — deliverable with a content body." }
114
+ ]
115
+ }
116
+ ```
117
+
118
+ ### Two states of one component
119
+
120
+ The same component, changed twice in one batch: two entries under one `typeName`/`fullName`, ordered by their intents, each bound to its own file. Both files are complete component state — the second is not a diff against the first.
121
+
122
+ ```json
123
+ "components": [
124
+ {
125
+ "typeName": "CustomField",
126
+ "fullName": "CF65_Case_Readiness__c.CF65_Risk__c",
127
+ "intent": "create",
128
+ "deployable": true,
129
+ "status": "missing",
130
+ "authoredFile": "objects/CF65_Case_Readiness__c/fields/CF65_Risk__c.field-meta.xml"
131
+ },
132
+ {
133
+ "typeName": "CustomField",
134
+ "fullName": "CF65_Case_Readiness__c.CF65_Risk__c",
135
+ "intent": "update",
136
+ "deployable": true,
137
+ "status": "exists",
138
+ "draftNotes": "Adds the 'Severe' value once REQ-15390's escalation flow exists. Whole field, values restated.",
139
+ "authoredFile": "r2/objects/CF65_Case_Readiness__c/fields/CF65_Risk__c.field-meta.xml"
140
+ }
141
+ ]
142
+ ```
143
+
144
+ The `r2/` prefix is a plain directory inside your `authored/` tree — anything that keeps the two files apart works, and it does NOT have to be type-rooted. `plan_waves` puts the two entries in two waves and tells each wave which file it binds; you never build a wave, and you never hand-order anything.
145
+
146
+ ### A component this requirement DELETES
147
+
148
+ `intent: "delete"`, and no `authoredFile` — a deletion has no source, and it is the last state a component can be declared at. Below, the first entry retires something that was already in the org and the second retires a component another requirement in this batch creates.
149
+
150
+ ```json
151
+ "components": [
152
+ {
153
+ "typeName": "ListView",
154
+ "fullName": "PV_Asset__c.Active_High_Value",
155
+ "intent": "delete",
156
+ "status": "exists",
157
+ "dependsOn": ["CustomObject:PV_Asset__c"],
158
+ "draftNotes": "Retired by RV-03. Confirmed present in the projection; references only PV_Status__c and PV_Value__c, both of which survive the batch."
159
+ },
160
+ {
161
+ "typeName": "CustomField",
162
+ "fullName": "PV_Asset__c.PV_Last_Audit__c",
163
+ "intent": "delete",
164
+ "status": "exists",
165
+ "dependsOn": ["CustomField:PV_Asset__c.PV_Last_Audit__c"],
166
+ "provisional": true,
167
+ "blockedBy": "B1",
168
+ "draftNotes": "REQ-15745 creates this field and REQ-15746 builds a formula that READS it; Salesforce refuses to delete a field a formula references. B1 puts that to the operator."
169
+ }
170
+ ]
171
+ ```
172
+
173
+ The self-keyed `dependsOn` on the second entry is how you say "after this batch is done building it" — `plan_waves` reads it as the chain edge and orders the deletion after the wave that creates the field. A destructive package rolls back WHOLE, so say in `draftNotes` when you know one of your deletions is at risk of being refused; it changes how the supervisor splits the call.
174
+
175
+ ## Components map to Configuration Items (why granularity matters)
176
+
177
+ Every component this requirement OWNS becomes a **Campfire Configuration Item** at writeback — and the CI list is DERIVED from deployment evidence (`campfire_config_item_plan`), not from this plan. Two things that are yours: **decompose at the configurable-component grain** — a workflow email alert, each field, each record type is its own component even when several deploy inside one container file — and **list each component under the requirement that owns it**, because a component filed under the wrong requirement shows up as a CI error later.
178
+
179
+ ## Ownership vs dependency (the "bindings" distinction — load-bearing)
180
+
181
+ - `components` = what THIS requirement **owns** — brings into being (`intent: "create"`) or changes (`intent: "update"`). This is the binding.
182
+ - `dependsOn` (per component) = what must already **exist first** — cross-requirement or existing-org, as component keys (`CustomObject:CF65_X__c`). This is the dependency reference, and the ONLY dependency field: the supervisor derives cross-requirement ordering by matching each `dependsOn` key to whichever requirement owns that component. (No separate requirement-level list — one source of truth, no drift.)
183
+ - **Own what you create, change or delete; `dependsOn` what must merely exist.** Changing or removing a component another requirement creates is a chain, not a conflict — declare your own `update`/`delete` entry for it. What is forbidden is two `create` claims on one component, not two claims.
184
+ - A component you own that ALREADY EXISTS in the org is still yours: `intent: "update"` with `status: "exists"` — never a second create. (`status: "exists"` with genuinely nothing to do is not a component at all; leave it out.)
185
+
186
+ ## Never
187
+ - Never WRITE to the org, and never run `project_org` or `direct_apply` — reads are yours, changes are the supervisor's after the operator approves.
188
+ - Never plan against a gap in the projection. If it does not tell you what you need, read the org (`describe_object`, `list_components`, `sf_read`) and say in your plan what you read and why. A guess that happens to be right is indistinguishable from one that is not, and only one of them survives the deploy.