From 99b670508633d75795200622f289d64edfcfc046 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 7 Nov 2026 14:19:08 +0000 Subject: [PATCH 1/2] Plans up to date before the agility-rooms track; plan 004 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Plan 001: A6 describes what shipped (npmjs, Linux + Windows CI, trusted publishing behind the npm environment); Track D drops the satisfied A1/A2 prerequisites, uses the 2026-11-07 survey counts, names A7 and the IHttpClient seam; R1 points at the new brief. - Plans 002 and 003: marked done, with the PRs; dependency sections describe the published-package pin, not a git commit. - Plan 004: the brief for the agility-rooms session — survey summary, what the SDK offers, the rest-1 writes/Copy decision to make first, R1 and D1–D4, rules, done when. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_016NSWj9gL1oCubj5e2anVkb --- plans/001-sdk-adoption-campaign.md | 33 +++--- plans/002-adopt-sdk-gh-v1.md | 21 ++-- plans/003-adopt-sdk-k6i-agility-slack-bot.md | 19 +-- plans/004-adopt-sdk-agility-rooms.md | 117 +++++++++++++++++++ 4 files changed, 162 insertions(+), 28 deletions(-) create mode 100644 plans/004-adopt-sdk-agility-rooms.md diff --git a/plans/001-sdk-adoption-campaign.md b/plans/001-sdk-adoption-campaign.md index f82cbe6..34ae036 100644 --- a/plans/001-sdk-adoption-campaign.md +++ b/plans/001-sdk-adoption-campaign.md @@ -224,10 +224,11 @@ moves. snapshot, reverseOf — a receipt as data; writing it to disk stays in gh-v1). gh-v1's tests for these move with them, rewritten against recorded responses. -- **A6 CI and packaging** — GitHub Actions running `npm run verify` on PRs; - publish prereleases (`0.x`, `next` tag) to GitHub Packages under the - `@versionone` scope (or npmjs — decision below). Until then consumers pin a - git SHA or a tarball from `npm pack`. +- **A6 CI and packaging** — done: CI runs `npm run verify` on Linux (Node + 20/22/24) and Windows (Node 24); `@versionone/agility-sdk` is on npmjs + (`1.0.0-alpha.0`, `alpha` dist-tag); `publish.yml` publishes later + versions from a `v*` tag through npm trusted publishing, gated by the + GitHub environment `npm` (an approval). Consumers install from npmjs. - **A7 Attachments and embedded images** — gap 5's `attachment`/ `EmbeddedImage`, as part of the asset-update abstraction, not a side channel. Two consumers to serve: gh-v1's `gh v1 attach` (list, get, add, @@ -361,13 +362,17 @@ Strangler, starting below the call sites so nothing user-visible moves: delegates to rooms' current axios instance (keeps the SSO refresh interceptor and snackbar). Point `bulkApiService.tsx` at `client.assets.*`. Rows arrive translated, so `getApiResults`' `IsReadOnly` - patch goes. This is the whole first PR. Needs A2 for parity of the - command-failure snackbar. + patch goes. This is the whole first PR. (A2 is done: + `CommandFailureError` carries what the snackbar needs.) - **D2 Domain by domain.** Start with `src/domains/ai` (it already has - adapters and architecture tests), then retire string-boolean decodes per - feature (48 today). Jest + Playwright gate each PR. + adapters, architecture tests, and the injected `IHttpClient` / + `FakeHttpClient` seam), then retire string-boolean decodes per feature + (46 at the 2026-11-07 survey). Attachments and embedded images move to + `client.attachments` / `client.embeddedImages` (A7). Jest + Playwright + gate each PR. - **D3 Native transport.** Swap the axios-backed Transport for - `createFetchTransport` with `credentials` + `onUnauthorized` (needs A1). + `createFetchTransport` with `credentials` + `onUnauthorized` (A1 is + done). - **D4 Schema convergence.** Evaluate replacing parts of `src/metaAssetStore/` field knowledge with the SDK `schema` service. @@ -419,11 +424,11 @@ ESM" here means finishing the edges: captured from the local dev instance (spec 000 §2a: fakes send what the server sends — api/asset spells `"True"`, not `true`). -**agility-rooms** (slow; no handoff yet) +**agility-rooms** (slow; brief: `plans/004-adopt-sdk-agility-rooms.md`) -- **R1** Narrow the axios surface: route the 67 axios importers through - `utils/bulkApiService.tsx` and a small set of helpers, so D1 swaps one - module. Start when Track A2 lands; write the handoff then. +- **R1** Narrow the axios surface: route the axios importers (88 production + files at the 2026-11-07 survey) through `utils/bulkApiService.tsx` and a + small set of helpers, so D1 swaps one module. ## Operating model for the campaign @@ -487,4 +492,4 @@ ESM" here means finishing the edges: - [x] C2 gh-v1 rows translated through the schema; `isTrue`/`oidOf` gone — versionone/gh-v1#36 - [x] C3 gh-v1 resolve and batch on `client.resolve`/`client.batch` — versionone/gh-v1#37 (with the SDK fixes from #43) - [x] C4 gh-v1 `gh v1 attach` on `client.attachments`, `blob` removed — versionone/gh-v1#38 (re-vendored at `d51fb16`; small files now upload inline); `raw` stays CLI-local -- [ ] D1–D4 agility-rooms +- [ ] D1–D4 agility-rooms — brief: `plans/004-adopt-sdk-agility-rooms.md` (first: decide rooms' rest-1 writes and Copy) diff --git a/plans/002-adopt-sdk-gh-v1.md b/plans/002-adopt-sdk-gh-v1.md index f1d0b70..83f9112 100644 --- a/plans/002-adopt-sdk-gh-v1.md +++ b/plans/002-adopt-sdk-gh-v1.md @@ -1,9 +1,13 @@ # Plan 002: gh-v1 adopts `@versionone/agility-sdk` (Track C) -Brief for a session on `versionone/gh-v1`. Start once the SDK PR that adds -this file has merged into `proposed_type_script_api_version`. Source plan: +Brief for a session on `versionone/gh-v1`. Source plan: `plans/001-sdk-adoption-campaign.md`, Track C. +**Status (2026-11-07): done.** C1–C4 merged (versionone/gh-v1#33, #35–#38); +gh-v1 then moved to the renamed, published package (#39, #40). gh-v1 +reaches Agility only through the vendored SDK, apart from the `gh v1 api` +passthrough. The rest of this brief is the record of how. + ## Goal gh-v1 talks to Agility only through `@versionone/agility-sdk`. CLI behaviour and @@ -33,15 +37,18 @@ runtime dependency, but its code ships inside the repo: - `vendor/versionone-sdk/` holds the SDK's ESM build (`index.js`, which imports nothing) and types (`index.d.ts`), plus `SOURCE.json` naming - the commit they came from. `lib/api.js` imports from there. -- `package.json` lists `@versionone/agility-sdk` under `devDependencies`, pinned - to a full commit, so the lockfile records exactly what was vendored. + the version they came from and each file's SHA-256. `lib/api.js` + imports from there. +- `package.json` lists `@versionone/agility-sdk` under `devDependencies`, + pinned to an exact published version (`1.0.0-alpha.0` today; before the + first publish it was a git commit), so the lockfile records exactly what + was vendored. - To move the pin: change it in `package.json`, then `npm install && npm run vendor:sdk`, and commit the copy. `test/vendor.test.js` fails if the copy, `SOURCE.json` and the pin disagree. -- Publishing the SDK to a registry (plan 001, *Decisions needed*) changes - only where the pin points; the copy stays. +- The SDK is on npmjs (plan 001, A6); that changed only where the pin + points. The copy stays, because gh never runs npm. ## Steps, one PR each, on branch `sdk-adoption` diff --git a/plans/003-adopt-sdk-k6i-agility-slack-bot.md b/plans/003-adopt-sdk-k6i-agility-slack-bot.md index 32a9db3..9544508 100644 --- a/plans/003-adopt-sdk-k6i-agility-slack-bot.md +++ b/plans/003-adopt-sdk-k6i-agility-slack-bot.md @@ -1,9 +1,14 @@ # Plan 003: k6i-agility-slack-bot adopts `@versionone/agility-sdk` (Track B) -Brief for a session on `digital-ai/k6i-agility-slack-bot`. Start once the -SDK PR that adds this file has merged into `proposed_type_script_api_version`. -Source plan: `plans/001-sdk-adoption-campaign.md`, Track B. Work on -`bolt-migration` (branch `sdk-adoption` from it), never `main`. +Brief for a session on `digital-ai/k6i-agility-slack-bot`. Source plan: +`plans/001-sdk-adoption-campaign.md`, Track B. Work on `bolt-migration`, +never `main`. + +**Status (2026-11-07): done.** S1–S4 (digital-ai/k6i-agility-slack-bot#21–#24) +and B1–B4 (#29, #30, #32, #34) merged; the bot installs +`@versionone/agility-sdk@1.0.0-alpha.0` from npmjs (#41). Its SDK requests +(group rows, a shared TypeCache, a registry release, number roots, Template) +are all answered. The rest of this brief is the record of how. ## Goal @@ -26,9 +31,9 @@ hand-decoding and rest-1 write path go. ## Dependency -No registry package yet. Pin a commit: -`"@versionone/agility-sdk": "github:versionone/VersionOne.SDK.JavaScript#"`. -The SDK's `prepare` script builds `dist` on install. The bot is ESM, so +`"@versionone/agility-sdk": "1.0.0-alpha.0"` from npmjs, an exact pin +(until the first publish it was a git commit, which needed `git` in the +image and wrote a `git+ssh` URL into the lockfile). The bot is ESM, so `import { AgilityApiClient } from "@versionone/agility-sdk"`. ## Steps, one PR each diff --git a/plans/004-adopt-sdk-agility-rooms.md b/plans/004-adopt-sdk-agility-rooms.md new file mode 100644 index 0000000..c65ee33 --- /dev/null +++ b/plans/004-adopt-sdk-agility-rooms.md @@ -0,0 +1,117 @@ +# Plan 004: agility-rooms adopts `@versionone/agility-sdk` (Track D) + +Brief for a session on `digital-ai/agility-rooms`, a React/Vite SPA that +runs inside Agility (same-origin, cookie auth). Source plan: +`plans/001-sdk-adoption-campaign.md`, Track D. gh-v1 (plan 002) and the +slack bot (plan 003) have finished their adoptions; this is the last +consumer, and the slowest: a strangler that starts below the call sites so +nothing user-visible moves. + +## Goal + +Rooms talks to the Agility data endpoints (api/asset, query.v1, rest-1, +meta.v1, loc-2, attachments, embedded images) only through +`@versionone/agility-sdk`. Rows arrive translated, so its hand-decoding +goes. UI behaviour stays the same. Rooms' own routes (`api/*` reports, +tags, watch, rooms2config, LLM; `*.mvc` pages) are out of scope unless the +SDK already covers them. + +## Where things stand (surveyed 2026-11-07 at `main` `0874590`, read-only) + +Full survey: plan 001, *What the consumers do today*, the agility-rooms +re-survey paragraph. In short: + +- **HTTP.** `src/utils/axios.tsx` builds the default instance (`baseURL` + the app root, `X-Requested-With`, cookie auth; on 401/403 an SSO popup + via `Account.mvc/Login`, then axios-auth-refresh replays). A response + interceptor turns api/asset `commandFailures` into a localized snackbar + and throws — but only when the URL is exactly `/api/asset`; 9 calls + written `api/asset` bypass it. `getAxiosInstance(...)` variants, a bare + `meta` instance and a plain `axios.create` in `src/navigation/routes.tsx` + skip some interceptors. 88 production files import axios. +- **Endpoints.** api/asset (111 call sites in 57 files), query.v1 (16), + rest-1 reads (4) **and writes** (5 `Data/{T}/{id}` attribute posts, 2 + `?op=Copy`, plus `New/{T}?ctx=` templates), meta.v1, loc-2, `loc.v1`, + `config.v1`, attachments (`MultiValueRelations/Attachments.tsx`: inline + Base64 create, `attachment.img` download), embedded images + (`useImageUpload.ts` → `EmbeddedImage.mvc/Upload`). +- **Reads.** Positional `results[n]` with index constants + (`metaAssetStore/constants.ts`); some board and `ID=$Oids` reads are + unbounded (the SDK refuses an unpaged query). +- **Decoding.** 46 `"True"`/`"False"` comparisons; `NULL_OID` used 118 + times; `massageApiAssetResponseObject` unwraps single relations. meta.v1 + is loaded by `store/metaDefinition/useMetaDefinitionStore.ts`. +- **Tests.** Jest (222 files, module mocks, no MSW); the AI domain's + injected `IHttpClient` / `FakeHttpClient` is the cleanest seam. + Playwright (79 specs) runs against a live server. + +## What the SDK offers rooms (1.0.0-alpha.0) + +- `AgilityApiClient` with a pluggable `Transport` (D1 wraps rooms' axios), + or `createFetchTransport` with `credentials: "same-origin"` and + `onUnauthorized` (resend an idempotent request after re-auth; a write is + never resent), `signal` / `client.withSignal` for cancellation. +- `client.assets.query/queries/send` (rows translated through the schema; + a failed query throws; `CommandFailureError` carries each failure by + index for the snackbar), `client.queryV1`, `client.data` (rest-1 reads), + `client.localize`, `client.schema` / `TypeCache`, `client.resolve`, + `client.batch` (guarded sends, receipts, undo). +- `client.attachments` (list/page/info/get/add/put/remove/url; inline + Base64 up to 1 MB as rooms does, two-step above) and + `client.embeddedImages` (upload/url/normalize). +- Browser-safe: no `node:` imports, no Buffer. Install + `npm install @versionone/agility-sdk@1.0.0-alpha.0` (an exact pin; it is + an alpha). + +## First: a decision for Jim + +Rooms writes through rest-1 (attribute posts with `act`, `?op=Copy`) and +reads `New/{T}` templates, which plan 001 assumed no consumer needed. +Before D1, find out (live, on v1sdktesting) whether api/asset covers each: +an update for the attribute posts (likely), an `execute: "Copy"` or similar +for Copy, and whether `New/{T}` has an api/asset equivalent. Report what you +find to the SDK session and Jim, with a recommendation: move them to +api/asset, or have the SDK grow a narrow rest-1 write path. + +## Steps, one PR each against `main`, from its own branch + +1. **R1 Narrow the axios surface.** Route the axios importers through + `utils/bulkApiService.tsx` and a small set of helpers, so D1 swaps one + module. Fix the `api/asset` vs `/api/asset` interceptor gap on the way. +2. **D1 SDK under the existing axios.** A `Transport` that delegates to + rooms' axios instance (keeps the SSO refresh and the snackbar); point + `bulkApiService.tsx` at `client.assets.*`. Rows arrive translated, so + `getApiResults`' `IsReadOnly` patch goes. +3. **D2 Domain by domain.** Start with `src/domains/ai`, then retire the + string-boolean and `NULL_OID` decodes per feature; attachments onto + `client.attachments`, embedded images onto `client.embeddedImages`; + positional `results[n]` onto named or `queries` results; page every read. +4. **D3 Native transport.** Replace the axios-backed Transport with + `createFetchTransport({ credentials: "same-origin", onUnauthorized })`, + the SSO popup as the hook. +5. **D4 Schema convergence.** Evaluate replacing parts of + `src/metaAssetStore/` and `useMetaDefinitionStore` with the SDK's + `schema` / `TypeCache`. + +## Rules + +- Jest and the existing Playwright gates pass on every PR. No behaviour or + UI change unless a step says so. +- Live Agility calls go only to `https://www14.v1host.com/v1sdktesting` + (`V1_URL`, token in `V1_ACCESS_TOKEN`; Node's fetch needs + `NODE_USE_ENV_PROXY=1`). Writes are allowed there and nowhere else: name + assets `sdk-integration …` and delete them by exact OID. Every query is + small and explicitly paged. Point Playwright at nothing else. +- An EmbeddedImage cannot be deleted; upload one only when a test needs it. +- If the SDK lacks something, don't work around it in rooms: tell the SDK + session (`session_016NSWj9gL1oCubj5e2anVkb`, `send_message`) with what + you need and why. Don't request reviewers; Jim picks. + +## Done when + +- Rooms reaches the data endpoints only through the SDK; no file outside + the transport adapter imports axios for them. +- No `"True"`/`"False"` comparisons or `NULL_OID` checks on SDK rows remain. +- Attachments and embedded images go through the SDK. +- Plan 001's checklist line `D1–D4 agility-rooms` is ticked, with PR links + (tell the SDK session as each merges). From a7d48ded8f308158b275a6752e5994686f08b631 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 7 Nov 2026 14:19:19 +0000 Subject: [PATCH 2/2] Plan 003: mark the 2026-11-06 snapshot line as historical Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_016NSWj9gL1oCubj5e2anVkb --- plans/003-adopt-sdk-k6i-agility-slack-bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plans/003-adopt-sdk-k6i-agility-slack-bot.md b/plans/003-adopt-sdk-k6i-agility-slack-bot.md index 9544508..94a2196 100644 --- a/plans/003-adopt-sdk-k6i-agility-slack-bot.md +++ b/plans/003-adopt-sdk-k6i-agility-slack-bot.md @@ -25,7 +25,7 @@ hand-decoding and rest-1 write path go. `findAssets` (rest-1 `find`/`findin`, `page` up to 200), `fetchLocalizations` (loc-2), and `queryFor*` helpers built on `lib/queries.js`. `test/v1-service.test.js` stubs global `fetch`. -- **S1–S4 are not done yet**: `jsconfig.json` still says `commonJS`/`es6`; +- **S1–S4 were not done yet** (then; all merged since): `jsconfig.json` still says `commonJS`/`es6`; query bodies have no explicit page; `axios`, `botkit*`, `botbuilder-*` are still dependencies and `lib/v1api.js` still exists. These come first.