Skip to content

docs(openspec): OpenSpec pass batch 1, landscape and connections changes with the gap decisions - #1094

Merged
rubenvdlinde merged 15 commits into
developmentfrom
parity/openspec-pass-1
Sep 27, 2026
Merged

rubenvdlinde merged 15 commits into
developmentfrom
parity/openspec-pass-1

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

OpenSpec pass for stackiq, batch 1 of 3: the gap rows of stackiq's parity matrix turned into OpenSpec changes, the decisions recorded in openspec/parity/gap-decisions.json, and the matrix states set to match. Specs only, nothing is implemented.

Decisions

All 125 rows decided on 2026-09-27: the 122 gap rows owned by ConductionNL/stackiq, the two rows in this matrix owed to nextcloud/server, and conn-integration-registry (owned by integriq, recorded as instructed). Totals over the whole pass: build 65 rows in 37 changes, defer 40, decided-no 16, existing 4.

This batch carries the 13 core-area changes (landscape and connections, 24 rows) and every defer, decided-no and existing decision. Batches 2 (architecture and lifecycle, 11 changes) and 3 (contracts, insight, operations, organisations, security, sharing, 13 changes) add their build rows to the same file.

Changes in this batch

  • connections-catalogue-pages: conn-list-page, conn-type-filter, conn-per-application, conn-external-provision
  • connections-diagram-and-graph-export: conn-diagram, conn-export-graph
  • connections-api-catalogue: conn-api-catalogue
  • connections-derived-dependencies: conn-auto-populate-dependencies, land-version-carry-connections
  • landscape-application-page: land-detail-page, ctr-per-application, mkt-contacts-per-product
  • landscape-usage-registration: land-register-application, life-version-in-use, land-application-owner
  • landscape-application-components: land-application-modules
  • landscape-change-entry-type: land-change-entry-type
  • landscape-dependent-field-options: land-dependent-fields
  • landscape-completeness-score: land-completeness-score, comp-health-scoring
  • landscape-owner-attestation: land-data-quality-survey
  • landscape-move-between-organisations: land-move-between-workspaces
  • landscape-ai-system-inventory: land-ai-agent-inventory, comp-ai-act-classification

Not built, and why

Decided no (16):

  • land-sectors: Recorded non-goal: aanvullende-informatie.md:511 lists VNG issue [Changelog CI] Add Changelog for Version 0.1.7 #4 (classify packages on the reference architectures of the relevant sectors, so buyers from several sectors find them) with the analysis "Classificeren op meerdere sectorale referentiearchitecturen, buiten scope", and issues/4.md carries the label "Buiten scope oplevering" and is closed. Tagging applications with sectors is the entry to that out-of-scope classification. The unused sector schema (lib/Settings/softwarecatalogus_register.json:1036) is what the specified state pointed at; no change directory existed.
  • mkt-tender-product-info: Recorded design: README.md:266 says stackiq runs "with a separate React-based public frontend", and README.md:273 names it (ConductionNL/tilburg-woo-ui) as the public search and detail pages. The missing half is the public page a buyer opens, which that frontend serves; stackiq publishes the data (module read rule for group public after publicationDate).
  • ops-agent-inventory: Recorded non-goal: openspec/parity/capabilities.json category: "It is not a discovery agent, a service desk or a developer portal, and the operations area exists to record that on purpose." Agent-based discovery of installed software is a discovery agent.
  • ops-change: Recorded non-goal: openspec/parity/capabilities.json category: "It is not a discovery agent, a service desk or a developer portal, and the operations area exists to record that on purpose." Change approval workflows are service desk change management.
  • ops-change-risk-score: Recorded non-goal: openspec/parity/capabilities.json category: "It is not a discovery agent, a service desk or a developer portal, and the operations area exists to record that on purpose." A risk score for a planned change belongs to service desk change management, which stackiq does not run.
  • ops-network-discovery: Recorded non-goal: openspec/parity/capabilities.json category: "It is not a discovery agent, a service desk or a developer portal, and the operations area exists to record that on purpose." Network device discovery is a discovery agent.
  • ops-saas-discovery: Recorded non-goal: openspec/parity/capabilities.json category: "It is not a discovery agent, a service desk or a developer portal, and the operations area exists to record that on purpose." Discovering unregistered SaaS use is a discovery agent.
  • ops-self-service: Recorded non-goal: openspec/parity/capabilities.json category: "It is not a discovery agent, a service desk or a developer portal, and the operations area exists to record that on purpose." A self-service portal where end users request software is a service desk.
  • ops-sla: Recorded non-goal: openspec/parity/capabilities.json category: "It is not a discovery agent, a service desk or a developer portal, and the operations area exists to record that on purpose." The competitor evidence tracks service desk response and resolution targets on calls and tickets.
  • ops-tickets: Recorded non-goal: openspec/parity/capabilities.json category: "It is not a discovery agent, a service desk or a developer portal, and the operations area exists to record that on purpose." Logging incidents and requests is a service desk. Exchange with the organisation's service desk is specified under share-itsm-integration.
  • org-act-as-user: Platform capability: the Nextcloud Impersonate app lets an administrator sign in as another account, and stackiq relies on Nextcloud users. built.owner corrected to nextcloud/server, provider nextcloud.
  • org-directory-sync: Platform capability: Nextcloud user_ldap keeps users and groups in step with a directory for every app, and stackiq users and groups are Nextcloud users and groups. built.owner corrected to nextcloud/server.
  • org-password-change: Platform capability: Nextcloud personal settings let every user change their password and see their account details. The stackiq half (change password from your own contact row) stays as built evidence. built.owner corrected to nextcloud/server, provider nextcloud.
  • org-sso: Platform capability: Nextcloud signs users in through its identity provider apps (user_oidc, user_saml) for every app, and stackiq users are Nextcloud users. built.owner corrected to nextcloud/server.
  • sec-multi-factor-sign-in: Owed to nextcloud/server: Nextcloud two-factor apps require a second factor at sign-in for every app, and stackiq users are Nextcloud users.
  • sec-password-policy: Owed to nextcloud/server: the Nextcloud password_policy app enforces password rules for every local account, including the ones stackiq creates.

Existing (4):

  • ins-ai-action-audit: mcp-full-action-surface. Open change mcp-full-action-surface, spec mcp-tool-surface, requires every agent tool invocation on stackiq to land in Hermiq's audit trail, which lists what an assistant did, when and on which record.
  • ins-natural-language-query: stackiq-mcp-adoption. Open change stackiq-mcp-adoption declares read-only search and get MCP tools on nine catalogue schemas so Hermiq answers questions about the landscape from the entries it read; mcp-full-action-surface design section 6 grounds the chat scenario. The chat, the answer and its citations are Hermiq's (ADR-034).
  • share-lifecycle-conditional-sync: no change. matrix corrected: stackiq's Flows page (src/manifest.json:1057, OpenRegister's flow store scoped to stackiq) composes an object trigger on object.updated (openregister lib/Service/Flow/Nodes/TriggerObjectNode.php:82), a per-item Filter on the lifecycle status (FilterNode.php:10, :186) and integriq's source call node (integriq lib/Flow/SourceCallNode.php on development). Rating set to yes, built.owner ConductionNL/openregister.
  • conn-integration-registry: connection-registry (ConductionNL/integriq). Owned by ConductionNL/integriq. Its open change connection-registry covers the integrations overview; stackiq's half is the open change adopt-connection-registry (19 of 20 tasks). Recorded as instructed by the coordinator; the matrix row is the integriq lane's to set.

Deferred (40): 17 rows are partial and built with no demand and fewer than two competitors rating yes (arch-definitions, arch-export-amef, arch-export-org, arch-import-amef, comp-bio-assessment, comp-bio-measures, comp-bulk-sync-standards, comp-verified-vs-claimed, ctr-saas-spend, ins-cost-report, land-bulk-edit, land-guided-wizard, org-activation-mail, org-merge, sec-affected-versions, share-federation-peers, share-publish); 23 rows have one competitor or none and no tender, feature request or roadmap demand with a competitor, outside the core areas (comp-audit-questionnaire, comp-common-ground-fit, comp-forum-standaardisatie, comp-processing-register-generate, comp-retention-cleanup, comp-security-officer-signoff, ctr-budget, ctr-collective-agreements, ctr-depreciation, ctr-effective-licence-position, ctr-linked-contracts, ins-concept-orgs-widget, ins-scheduled-report, ins-usage-analytics, life-dates-follow-status, life-strategy-link, life-version-tolerance, mkt-contact-peers, mkt-side-by-side-compare, ops-mobile, org-assigned-only-rights, sec-patch-status, sec-risk-score). Each row's reason is in the decisions file.

How the rule was read

  • Core area is the areas of the matrix's first 30 rows: landscape (18), connections (9) and architecture (3).
  • A row rated partial with built.state built is a gap only when a tender, feature request or roadmap row, or two competitors rating yes, say the missing half matters; then the change builds that missing half and names it. A changelog-only row counts as the competitor it names, not as demand.
  • Rides with: a row below the bar is built only when its whole missing half is the same screen or service a build row's change specifies, and its reason names the carrying row (8 rows over the pass; in this batch conn-external-provision, mkt-contacts-per-product and comp-ai-act-classification).
  • The matrix category ("It is not a discovery agent, a service desk or a developer portal, and the operations area exists to record that on purpose") is read as a recorded non-goal for the discovery and service desk rows.
  • Rows whose capability Nextcloud provides for every app (org-sso, org-directory-sync, org-act-as-user, org-password-change) are decided no with built.owner corrected to nextcloud/server.
  • Rows owned by siblings are untouched here: conn-impact-analysis, land-custom-fields, life-new-version-notice (openregister), share-federation-announce, share-federation-pull (opencatalogi), land-copy-entry (nextcloud-vue). conn-integration-registry is recorded as existing (integriq's connection-registry, with stackiq's open adopt-connection-registry) and its matrix row is left to the integriq lane.

Matrix edits in this batch

  • 24 rows set to specified, each note naming its change directory.
  • 16 rows set to decided-no with the source in the note (13 gap rows, the two nextcloud/server rows, and land-sectors, which was marked specified with no change directory).
  • ins-natural-language-query and ins-ai-action-audit set to specified, naming the open changes stackiq-mcp-adoption and mcp-full-action-surface.
  • Corrections after re-reading the code: share-lifecycle-conditional-sync is yes and built (a flow on stackiq's Flows page gates on the status before integriq sends the entry; owner openregister), and land-dependent-fields is partial, not no (relation pickers already follow another field; the change builds dependent option lists).

Defects found while reading the code

Not fixed here, each is written into the change that touches it:

  • Four schemas declare x-openregister-lifecycle on Dutch states their enums and rows no longer hold: usage, catalogContract, connection and moduleVersion (lib/Settings/softwarecatalogus_register.json:3211, :3531, :3926, :7887). No transition matches a row. The register changelog 2.4.4 records the same bug fixed for organization. connections-catalogue-pages and landscape-usage-registration fix two; batch 2 and 3 carry the others.
  • The connection's national provision picker filters on the misspelled GEMMA type "Buitengemeentenlijke voorziening" (register.json:3720), so it finds nothing; its display name names renamed keys.
  • The Applications list (src/views/FacetedCatalogIndexView.vue:108) binds no row click, so no application opens from it; ModuleDetail and SuiteDetail list stale field keys, so descriptions and contact persons do not render.
  • The usage phase-out notification subject names renamed keys (register.json:2662).

Checks

  • openspec validate --changes: 29 passed, 3 failed. The 13 changes of this batch are valid with --strict; the three failures are pre-existing changes (adopt-apphost, beta-surface-alignment, rename-app-id-to-stackiq) that fail the same way on development.
  • parity_verify.py --strict: only the unknown-cells census (469 cells, 470 on development: share-lifecycle-conditional-sync moved from unknown to yes), no other finding, no schema error (jsonschema ran). The script exits 1 whenever the census is non-empty, on development as well.
  • composer check:strict (private HOME and TMPDIR): exit 0 (lint, phpcs, phpmd, psalm and phpstan pass; test:all prints SKIPPED because it needs a Nextcloud server tree, so PHPUnit did not run here). The native PHP 8.3 lacks ext-bcmath, ext-soap and ext-intl, so composer install ran with --ignore-platform-req for those three.
  • npm run lint: exit 0 (217 warnings, 0 errors, all in files this PR does not touch).
  • No em-dash, en-dash or double dash in any file of this batch (grep -rnP '\x{2014}|\x{2013}| -- ' returns nothing).
  • The PR touches only openspec/: 13 change directories, openspec/parity/capabilities.json and openspec/parity/gap-decisions.json. No PHP, JavaScript or register file changes, so neither gate can move.

🤖 Generated with Claude Code

…, list diagram and connections in the ArchiMate export
@rubenvdlinde
rubenvdlinde merged commit 9a5ece6 into development Sep 27, 2026
36 of 37 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/stackiq @ d17fe2b

Check PHP Vue Security License Tests
lint ✅
phpcs ✅
phpmd ✅
psalm ✅
phpstan ✅
phpmetrics ✅
eslint ✅
stylelint ✅
build ✅
check-manifest ✅
check-vue-demi ✅
test-l10n ✅
format ✅
check-schema-l10n ✅
check-l10n-js ✅
composer ✅ ✅ 130/130
npm ✅ ✅ 807/807
app:check-code ⏭️
info.xml ✅
REUSE ❌
lockfile sync ✅
PHPUnit ⏭️ not run for this diff — no file in this diff matches the code globs, and none carries a source extension — the heavy tier has nothing to decide about it.
Newman ⏭️
Playwright ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it on any branch from the Actions tab, or locally with npx playwright test.
Hydra gates ❌

Quality workflow — 2026-09-27 18:19 UTC

Download the full PDF report from the workflow artifacts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant