Skip to content

Design: Gospl / Strategiq OS — 12-Week MVP Operating Model

Design: Gospl / Strategiq OS — 12-Week MVP Operating Model

Section titled “Design: Gospl / Strategiq OS — 12-Week MVP Operating Model”

Generated by /office-hours on 2026-06-09 Branch: main Repo: strategiq-gospl (greenfield) Status: DRAFT Mode: Startup (intrapreneurship — validated internal product)

Gospl is a culture-aware operating system: a single source of truth for running an organisation, connecting people, clients, and organisation through one core relationship — actions tagged to outcomes. It is not a workspace and does not replace tools for booking holidays, planning campaigns, or running projects. It connects those actions to purpose, turning everyday activity into visible progress toward shared goals.

The vision is validated by the company’s own 5-year-old bespoke Laravel intranet, which V1 must replace. The build runs ~12 weeks with an outside delivery partner, using Claude Code as the build engine. Functionality arrives as written specs (overview, problem statement, goals/non-goals, user stories, functional requirements); a human-readable wiki is generated alongside the code.

Strongest evidence is behavioural and internal: the company has run on a bespoke intranet built for this purpose for 5 years. The product is not a hypothesis to test — it is a working system being rebuilt and extended. “V1 must replace the existing solution” is the demand bar: people open the current OS daily, and V1 has to clear that bar to be adopted.

A bespoke Laravel intranet, ~5 years old, running the people/clients/org workflows today. The Personal Page spec (June 2026) shows the texture of what’s being replaced: legacy carry-over fields, manual data entry (an admin copy-pastes Insights PDF sections by hand), truncated content, GDPR exposure from data duplicated with the HRIS (HomeRun). The new build keeps what works, drops legacy noise, and automates the manual paths.

Client 1 is the company itself. V1 is multi-tenant from day one (clients are external orgs that will see views), accepting the data-leakage risk that comes with it and mitigating it at the database layer (see Premise P4 / Constraints).

Scope decision (B — defined core spine): V1 = the actions→outcomes spine across people / clients / org, plus the highest-traffic pages of the current intranet. The long tail of legacy pages migrates after launch. This is still a single whole release (Premise P1) with a defined boundary — not a sectional rollout. Chosen over (A) full like-for-like replacement of the entire legacy surface, which is not reachable in 12 weeks given external-API dependencies.

  • ~12 weeks to MVP.
  • V1 connects all three areas (people, clients, org) and releases as one whole — no sectional release (governs release, not build order).
  • V1 must replace the existing solution to the standard of the defined core spine (B).
  • AI features are in scope from the start; storage choices must accommodate them.
  • GDPR / data minimisation: HomeRun is the single source of truth for personal/HR data. Gospl holds only what core functionality needs (name, team, reporting line, job title). No duplication of personal data.
  • External integrations (Mojo, Insights provider, HomeRun) are partly outside the team’s control; some are of unknown API readiness (e.g. Mojo — OQ-01 in the Personal Page spec).
  • P1 — Vertical slices, whole release. Build thin slices that cross people + clients + org; flip V1 live only when the whole stands. “No sections” governs release, not build order.

  • P2 — The pipeline (contract-first). Spec (team) → Claude drafts acceptance criteria (owner signs) → Claude authors the API contract (OpenAPI 3.1 by default) → contract handed to the external team for implementation, and in parallel drives Claude’s generated client types + a mock server → Claude builds the frontend against the mock → contract tests (owned by us) verify the external API matches the contract → tests tagged by FR ID → wiki page (incl. auto-rendered API docs) generated per piece of functionality. The US/FR/OQ ID is the join key across spec ↔ contract ↔ test ↔ wiki. “Did we meet the brief” = every Must-Have FR has a passing, ID-tagged test, including its contract test.

  • P2a — API ownership split. API implementation is the external team’s. Per piece of functionality we produce the API contract as the handoff artifact; they build to it. The contract is the single source for four jobs (write once, no hand-sync): handoff doc to the external team, our generated client types, the mock server (lets the frontend be built before their API exists — decouples our timeline from theirs), and the wiki API page. Contract drift is the primary integration risk — mitigated by us-owned contract tests (the contract is the spec their API must pass, run against their endpoints, tagged by FR ID) and a written, versioned change protocol (contract changes signed by both sides before either moves).

  • P3 — Specs in-repo, invariants centralised. /specs lives beside the code; principles.md holds global rules (GDPR, data minimisation, HomeRun source-of-truth, tenant isolation). Page specs inherit, never redefine.

  • P4 — Stack spine (owner’s final call 2026-06-10; this is the recommendation). TypeScript / React / Node API / Postgres + pgvector + Row-Level Security. One DB does three jobs: relational core for the actions→outcomes graph, pgvector for AI embeddings, RLS for tenant isolation enforced at the database layer. AI starts narrow — stateless LLM extraction (e.g. Insights PDF parsing) needs no vector store; the vector store earns its place later on cross-graph search/insights.

Approach A: Full like-for-like replacement

Section titled “Approach A: Full like-for-like replacement”

Rebuild the entire surface of the legacy Laravel intranet before V1 goes live.

  • Effort: XL. Risk: High.
  • Pros: clean cut-over, nothing left behind; no dual-running period.
  • Cons: not reachable in 10 weeks; leans hard on external APIs of unknown readiness; forces low-value legacy pages into the critical path. Rejected.
Section titled “Approach B: Defined core spine + high-traffic pages (RECOMMENDED, chosen)”

V1 = actions→outcomes spine across all three areas + the most-used pages. Long tail migrates post-launch. Single whole release with a defined boundary.

  • Effort: L. Risk: Medium.
  • Pros: ships in the window; spine-first means the linking object is right before pages pile on; external-API-dependent features can be sequenced/feature-flagged; honours “release as one whole.”
  • Cons: requires an explicit, defended boundary of what’s in V1 vs post-launch; a defined dual-running/migration period for the long tail.

Approach C: Spine-only thin demo, pages deferred

Section titled “Approach C: Spine-only thin demo, pages deferred”

Ship only the actions→outcomes engine with minimal UI; defer most real pages.

  • Effort: M. Risk: Medium.
  • Pros: fastest proof the core graph works.
  • Cons: would not “replace the existing solution” — fails the V1 bar. Rejected as V1, but its spine-first instinct is folded into B as the first slice.

B — defined core spine. It is the only option that satisfies “all three areas, one whole release, replaces the existing solution” inside 10 weeks. Build the actions→outcomes spine first as the first vertical slice, then layer the highest-traffic pages on top, each page spec referencing the spine spec’s IDs.

/specs
principles.md # global invariants — every spec inherits
_platform/ # GLOBAL API — cross-cutting services every feature consumes
identity-and-access.md # identity, roles, permissions, org-chart visibility (PR-06)
user-directory.md # canonical employee list (planned)
notifications.md # in-app + email channel (in-app inbox + dispatch + digests)
_spine/goals-outcomes.md # the actions→outcomes domain core; canonical entity IDs
people/personal-page.md # feature spec + Claude-drafted acceptance criteria
people/...
clients/...
org/...
/contracts # API contracts (OpenAPI 3.1); handoff artifact to the API team
_platform/identity.yaml # shared schemas (UserRef, Role) + identity/access/org reads
people/personal-page.yaml
...
/wiki # generated; mirrors /specs + auto-rendered API docs +
# "how it actually works"
/src

Per-spec lifecycle:

  1. Team writes the spec in the existing format (it works — keep it).
  2. Claude appends acceptance criteria to each FR (verifiable done-conditions) and marks each FR buildable now or blocked: OQ-0x. Owner signs the criteria.
  3. Claude authors the API contract (OpenAPI 3.1) for the functionality and hands it to the external team. Same file generates our client types + a mock server.
  4. Claude builds the frontend slice against the mock; every Must-Have FR gets a test tagged with its FR ID, plus a contract test the external API must pass.
  5. Claude generates a plain-English wiki page for the functionality — including the auto-rendered API docs from the contract — shareable with any non-technical stakeholder to understand how it works.
  6. Re-assessment is mechanical: green ID-tagged test (incl. contract test) = FR met; the spec, contract, test, and wiki stay joined by ID.

The spec→criteria→test→wiki harness (auto-acceptance-criteria, ID-tagged test convention, auto-wiki generation) is unproven and building it consumes part of the 12 weeks. Time-box it as an explicit week-0/1 milestone. Manual fallback if it underperforms: Claude hand-writes acceptance criteria and wiki pages per slice — the ID join key (spec↔test↔wiki) still holds; only the automation is dropped. The pipeline is a productivity bet, not a release-gate dependency.

  • Acceptance criteria — signed by the spec owner (Sarah for the People specs; the named owner on each spec’s header).
  • Design sign-off — per FR-23-style gate, the spec’s design reviewer.
  • Release gate (whole-V1 go-live) — Duncan (project owner).

Additions to the spec template (format otherwise unchanged)

Section titled “Additions to the spec template (format otherwise unchanged)”
  • Acceptance criteria per FR — Claude-generated, owner-approved (decided: Claude generates).
  • Data model stub — entities touched + new-vs-existing; page specs link to the spine’s entity IDs rather than redefining them.
  • Buildable / blocked flag per FR — so the buildable work is always visible.
  • Design link slot — Figma/screenshot reference, so review checks against the real design (cf. Personal Page FR-23: design sign-off gates dev).
  • Promote system-wide rules out of page specs — e.g. Personal Page FR-19/FR-22 (data minimisation, HomeRun source-of-truth) belong in principles.md, not in one page’s spec.
  • API contract per functionality — OpenAPI 3.1 file in /contracts, authored by Claude, handed to the external team. Endpoints/schemas reference the spine’s entity IDs. This is the formal interface between our frontend and their API.

Living Spine — Scrum → Spec Update Mechanism

Section titled “Living Spine — Scrum → Spec Update Mechanism”

The external API team is in the stack meeting and in every morning scrum. To keep the actions→outcomes spine and the specs current without a second set of notes:

  • One file per standup: docs/scrum/YYYY-MM-DD.md — raw notes pasted in, no format tax. Decisions, new actions, blockers, any agreed contract changes.
  • Each morning Claude reconciles that entry against the live specs/contracts/spine: proposes spec edits, opens contract-change-protocol entries (versioned, signed before either side moves), logs durable decisions, and flags any scrum action that contradicts a signed decision before it drifts.
  • Output is a short “spine delta” — what changed, what it touches, what needs a sign-off — scannable in 30 seconds.

This is the heartbeat that keeps spec ↔ contract ↔ test ↔ wiki joined as the project moves day to day.

Integration Protocol — Mock → Real Cutover

Section titled “Integration Protocol — Mock → Real Cutover”

Both teams work in parallel from contract sign-off: Gospl builds the frontend against the Prism mock; the external team implements the real endpoints to the same contract.

The switch unit is the endpoint (contract operation), not the UI component. Cut over at the API boundary; track readiness per operationId / x-gospl-frs, not per component.

Per-endpoint loop:

  1. Contract signed for the section’s endpoints → both teams start.
  2. Gospl builds components against the Prism mock; external team implements the endpoint.
  3. Endpoint ready → contract test it (Schemathesis/Dredd, or Prism proxy-validation). Green = the real API provably matches the contract.
  4. Flip that endpoint mock → real via config (no code change).
  5. Run E2E on the components that use it. Repeat per endpoint until the section is live.

Switch mechanism: run Prism as a proxy with fallback — route to the real API where the endpoint exists, fall back to the mock where it doesn’t. Frontend always talks to one URL; readiness is a config table behind it. No frontend churn as endpoints come online.

Readiness matrix (per section, tied to FR IDs) is the truth of what’s actually live:

EndpointModeGate
getUserProfilerealcontract test green
getUserMotivatorsmockblocked: OQ-01 (Mojo)
importInsightsPdfmockblocked: OQ-03 (PDF parse)

A section is “done” only when every endpoint is real and contract-test-green — never “looks fine on the mock.” Don’t let a long-lived half-mock state drift silently; the matrix + contract tests are the source of truth.

The wiki is generated from in-repo source on every merge — never hand-maintained.

  • Source stays in the main repo (/docs, /specs, /contracts, /wiki). This is non-negotiable: co-location + the ID join key (spec↔contract↔test↔wiki) only hold if everything versions together in one commit. Not a git submodule — submodules break atomicity (the wiki would lag code by a sync step) and reintroduce exactly the drift we’re killing. One PR changes code + spec + contract + wiki together.
  • Generator config also lives in the main repo (e.g. /wiki-site). Recommendation: a TS-house static generator — Docusaurus (+ redocusaurus) or Astro Starlight (+ starlight-openapi) — both render the OpenAPI contracts into browsable API docs, so the “dynamically include in the wiki” loop closes automatically from /contracts.
  • Published site is build output, not a repo. CI on merge to the release branch: build the static site → deploy to the host. The built HTML is ephemeral, rebuilt every commit.
  • Access control is mandatory. The wiki describes internal architecture, the data model, tenancy, and GDPR posture. It MUST sit behind auth (SSO / private hosting), never a public URL. Host choice (Vercel/Netlify/Cloudflare Pages private, or internal) TBD; the access requirement is not.

Coarse week-bands so work can be sequenced and slippage is visible. Provisional — firms up once the stack is confirmed (06-10) and the V1 boundary list is signed.

  • Week 0–1: stack sign-off, greenfield repo + CI bootstrap, auth/tenancy scaffolding (RLS from commit 1), the spec→criteria→test→wiki pipeline, and the signed V1 boundary list. Build of feature pages does not start until the boundary list is signed.
  • Week 2–4: first vertical slice — the actions→outcomes spine end-to-end across people → clients → org. This proves the core graph and the pipeline.
  • Week 5–9: the high-traffic pages from the boundary list, layered on the spine; external-API-dependent FRs behind feature flags.
  • Week 10: integration hardening, RLS leakage testing, whole-release gate prep.
  • Week 10+: buffer + de-scope lever. If under pressure, the named lever is to push more of the boundary list into the post-launch long tail (never to ship in sections or skip the whole-release gate).

Pre-Build Dependencies (must resolve before the slice they gate)

Section titled “Pre-Build Dependencies (must resolve before the slice they gate)”

These are not parallel open questions — they block specific build work.

  • Stack final sign-off (2026-06-10) — gates repo bootstrap. All stack-dependent items below are contingent on this. Is the external API team in this meeting — does the P4 recommendation bind them, or are they downstream of it?
  • Backend/DB ownership split — does the external team own the database + backend stack, or implement API handlers against a stack/schema we define? Changes where the tenancy defense lives: if they own the DB, RLS + no-cross-tenant-leakage becomes a contract requirement we hand them and verify via contract tests, not code we write; if we define the stack/schema, RLS design stays ours (P4). Resolve before week-0 scaffolding.
  • API style — REST/OpenAPI (default) vs GraphQL. Changes the contract format (OpenAPI doc vs SDL) and the mock/contract-test tooling.
  • V1 boundary list — the explicit set of in-V1 pages vs post-launch long tail. Hard week-0 gate; feature-page build does not start without it. This is the scope contract for B — without it, B drifts back toward A.
  • Permission model — roles (self / colleague / manager / admin / elevated). RLS policies cannot be designed before roles are fixed, so this gates the auth/tenancy scaffolding in week 0–1, not later.
  • Auth / identity / SSO — how users log in, how identity relates to HomeRun and to tenancy. Gates week-0 scaffolding. (Owner to decide approach.)
  • External-client-facing views in V1 or deferred? — “multi-tenant from day one” with external clients seeing views materially expands RLS/permission scope. Decide whether external client views are in the 12-week V1 or post-launch. (Owner to decide; recommendation: tenancy/RLS built day one, external-facing client views deferred to post-launch unless core to the spine.)
  • External API readiness — Mojo (Personal Page OQ-01), Insights PDF format (OQ-03), HomeRun integration surface. For each, identify which legacy daily-use workflows hard-depend on it and whether the replacement bar is reachable without it. Flags gate, but cannot fix, a third-party API that isn’t ready.
  • Migration / dual-run posture — default: legacy Laravel intranet goes read-only at V1 go-live for the core spine; long-tail pages stay live on legacy (writable) until migrated post-launch. Owner to confirm; legacy data-migration ownership to be named.
  • First slice definition — which single end-to-end workflow is the first vertical slice through people→clients→org? Needs a concrete named example before week 2.
  • V1 ships in ~10 weeks as a single whole release covering people, clients, and org.
  • Every Must-Have FR in every in-scope spec has a passing, ID-tagged test.
  • Adoption bar (measurable): within [N] weeks of go-live, the core-spine pages show daily-active usage at or above the legacy intranet, and legacy is set read-only for those workflows. (Owner to set N and the metric.)
  • Rollback rule: if the adoption bar isn’t met at go-live, legacy stays primary for the affected workflows; V1 does not force cut-over. Extension/abort is the owner’s call against the metric, not a vibe.
  • A current, human-readable wiki page exists for each built piece of functionality.
  • No personal/HR data is duplicated from HomeRun into Gospl; tenant isolation enforced at the database layer (RLS) with no cross-tenant leakage.

(All items below contingent on the 2026-06-10 stack sign-off.) Web SaaS, multi-tenant. Existing/standard web deployment pipeline (to be set up as part of greenfield repo bootstrap) — CI runs ID-tagged tests on every merge; deploy on merge to the release branch once the whole-release gate is met. Not a binary/package distribution problem.

  • Stack decision (2026-06-10) before repo bootstrap.
  • A design system (owner to provide) before page-level build per FR-23-style gates.
  • External APIs (Mojo, HomeRun, Insights) for the FRs that depend on them — sequence these behind feature flags so the whole-release gate isn’t held hostage to a third-party API slipping.

Before week 1: write the V1 boundary list — one page naming exactly which legacy intranet pages are in V1 (the defined core spine + high-traffic pages) and which are explicitly post-launch. This is the scope contract for Approach B; without it, B quietly drifts back toward A. Pair it with naming the first vertical slice (the one end-to-end workflow that proves the actions→outcomes spine across all three areas).