All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Architecture model artifacts design note documenting how C4 models, architecture tests, and fitness functions are supported as traceable artifacts using existing TraceabilityLink and VerificationResult infrastructure (GC-J002)
- Reverse traceability lookup:
GET /api/v1/requirements/traceability/by-artifactendpoint andgc_get_traceability_by_artifactMCP tool for querying which requirements link to a given artifact (GC-O002) - Self-referential traceability enforcement in
check_live_policy.mjs: automated reverse traceability check that verifies substantive code files are linked to requirements, with baseline regression prevention
- Pack registry, resolution, and trust model (GC-P016, ADR-022 Section 6): registry catalog for discoverable packs, semver-aware version resolution with dependency tracking, configurable trust policy evaluation, and auditable install records
pack_registry_entry,pack_install_record,trust_policytables with Envers audit trails (V053)PackType(CONTROL_PACK, REQUIREMENTS_PACK, CUSTOM),CatalogStatus(AVAILABLE, WITHDRAWN, SUPERSEDED),TrustOutcome(TRUSTED, REJECTED, UNKNOWN),InstallOutcome(INSTALLED, UPGRADED, REJECTED, FAILED),TrustPolicyRuleOperatorenumsPackRegistryServicefor registry catalog CRUD,PackResolverfor semver resolution with caret/tilde/range constraints and dependency resolution,TrustEvaluatorfor declarative rule-based trust policy evaluation,TrustPolicyServicefor trust policy CRUD,PackInstallOrchestratorthat wraps existing ControlPackService with registry lookup, compatibility check, and trust gate- REST API:
POST/GET /api/v1/pack-registry,GET /api/v1/pack-registry/{packId},GET/PUT/DELETE /api/v1/pack-registry/{packId}/{version},PUT /api/v1/pack-registry/{packId}/{version}/withdraw,POST /api/v1/pack-registry/resolve,POST /api/v1/pack-registry/check-compatibility,POST/GET /api/v1/trust-policies,GET/PUT/DELETE /api/v1/trust-policies/{id},POST /api/v1/pack-install-records/install,POST /api/v1/pack-install-records/upgrade,GET /api/v1/pack-install-records,GET /api/v1/pack-install-records/{id} - MCP tools:
gc_register_pack_registry_entry,gc_list_pack_registry_entries,gc_get_pack_registry_entry,gc_list_pack_versions,gc_update_pack_registry_entry,gc_withdraw_pack_registry_entry,gc_delete_pack_registry_entry,gc_resolve_pack,gc_check_pack_compatibility,gc_create_trust_policy,gc_list_trust_policies,gc_get_trust_policy,gc_update_trust_policy,gc_delete_trust_policy,gc_install_pack_from_registry,gc_upgrade_pack_from_registry,gc_list_pack_install_records,gc_get_pack_install_record
- Control pack distribution and installation (GC-P015, ADR-022): versioned control packs as installable content bundles with idempotent installation, version-aware upgrades, source provenance tracking, and field-level local tailoring
control_pack,control_pack_entry,control_pack_overridetables with Envers audit trails (V052)ControlPackLifecycleStateenum (INSTALLED, UPGRADED, DEPRECATED, REMOVED) with validated state transitionsControlPackServicewith install (idempotent, materializesControlrecords andControlLinkMAPS_TO framework mappings), upgrade (applies upstream changes while preserving local overrides), deprecate, and remove operations- REST API:
POST /api/v1/control-packs/install,POST /api/v1/control-packs/upgrade,GET /api/v1/control-packs,GET /api/v1/control-packs/{packId},PUT /api/v1/control-packs/{packId}/deprecate,DELETE /api/v1/control-packs/{packId}, entry and override sub-resource endpoints - MCP tools:
gc_install_control_pack,gc_upgrade_control_pack,gc_list_control_packs,gc_get_control_pack,gc_deprecate_control_pack,gc_remove_control_pack,gc_list_control_pack_entries,gc_get_control_pack_entry,gc_create_control_pack_override,gc_list_control_pack_overrides,gc_delete_control_pack_override
- Plugin architecture with dual-source registry for built-in and dynamic plugins
(GC-P005, ADR-023):
Plugininterface with lifecycle management,PluginDescriptormetadata record,PluginRegistryservice with classpath discovery and DB persistence, typed plugin categories (pack handler, registry backend, validator, policy hook, verifier, embedding provider, graph contributor, custom) registered_plugindatabase table (V051) for dynamic plugin registrations that survive application restarts- REST API:
GET /api/v1/plugins,GET /api/v1/plugins/{name},POST /api/v1/plugins,DELETE /api/v1/plugins/{name}with type/capability filtering - MCP tools:
gc_list_plugins,gc_register_plugin,gc_unregister_plugin StringSetConverterinJacksonTextCollectionConvertersfor JSON-serializedSet<String>JPA columns
- Pluggable verifier adapter interface (
VerifierAdapter,VerificationRequest,VerificationOutcome) enabling integration with OpenJML, TLA+/TLC, OPA/Rego, Frama-C, and manual review processes (GC-F005, ADR-014 §6)
- Zod update broke GC mcp
- Asset-centric traceability target types: ISSUE, CODE, CONFIGURATION added to AssetLinkTargetType for first-class traceability from assets to issues, code files, and configuration artifacts (GC-M017)
- ControlGraphProjectionContributor: projects Control entities as graph nodes and ControlLink edges into the mixed-entity graph
- CONTROL asset links now produce graph edges in AssetGraphProjectionContributor (previously silently dropped)
- CONTROL risk-scenario links now produce graph edges in RiskGraphProjectionContributor (same fix)
- Stale JPA @Column(length=20) annotations on AssetLink.targetType and RiskScenarioLink.targetType corrected to length=40 (matching V043 migration)
- Verification result storage (GC-F001): prover-agnostic schema for storing verification results from any verifier (OpenJML, TLA+, OPA, manual review)
- VerificationResult entity with VerificationStatus and AssuranceLevel enums
- REST API: CRUD endpoints at
/api/v1/verification-resultswith filtering by requirement, prover, and result status - MCP tools:
gc_create_verification_result,gc_list_verification_results,gc_get_verification_result,gc_update_verification_result,gc_delete_verification_result - Flyway migrations V049-V050 for verification_result and audit tables
- Unit tests for VerificationResultController and VerificationResultService
- ADR conformance enforcement via
make policyguardrails shared by Claude and Codex agents - Policy checks: controller naming, migration auditing, MCP tool registration, ADR drift detection, and live policy sync
- Scaffolding scripts for audited entities, controllers, and L2 state
machines (
bin/scaffold-*) - CODEOWNERS file and PR template for GitHub workflow
ControllerPolicyTestArchUnit test enforcing controller conventionsEmbeddingControllerTestunit tests- TLA+ specification for requirement status machine
adr-policy.jsonandpolicy.jsonfor machine-readable policy rulescheck_adr_drift.mjsandcheck_live_policy.mjstooling for continuous ADR/policy validation
- Graph visualization returns empty data when Apache AGE is disabled (the default). The MixedGraphClient now falls back to building the graph projection from JPA entities via GraphProjectionContributors instead of returning empty lists
- Added
buildProjectionForProject(UUID)to GraphProjectionRegistryService for project-scoped JPA-based graph building - SonarCloud bug: bind SpaController path template variables to a @PathVariable parameter to satisfy rule java:S6856
- Set SonarCloud new code period to
previous_versionon main branch so quality gate conditions can be evaluated
- SonarCloud quality gate: reviewed 3 SQL-injection security hotspots in AgeGraphService as SAFE (Apache AGE requires dynamic Cypher-in-SQL; values are sanitized via escapeCypher/validateGraphName)
- SonarCloud quality gate: added 129 unit tests to raise new-code coverage above 80% threshold — covers TreatmentPlanController, RiskRegisterRecordController, JacksonTextCollectionConverters, TreatmentPlanResponse, RiskRegisterRecordResponse, and project-aware service methods in AssetService, ObservationService, and RiskScenarioLinkService
- Frontend build: fix TypeScript errors in graph.tsx — remove unused imports (GraphControls, GraphFilters, GraphStats, cn) and add missing lucide-react icon imports (Filter, Maximize, RotateCcw, X)
- Pull request-requirement linking via new
PULL_REQUESTartifact type in the traceability graph, with three-state PR tracking (OPEN, CLOSED, MERGED) reflecting GitHub PR lifecycle (GC-D002) GitHubPullRequestSyncentity for caching PR state locally, mirroring the existingGitHubIssueSyncpattern for issues- REST endpoint
POST /api/v1/admin/sync/github/prs?owner=X&repo=Yfor on-demand PR state synchronization - MCP tool
gc_sync_github_prsfor agent-initiated PR sync - Database migration V048 creating
github_pr_synctable PullRequestStateenum with OPEN, CLOSED, MERGED values- PR sync updates traceability link titles with state tags (e.g.,
#42 - Add feature [MERGED]) matching the existing issue sync pattern
- First-class Control entity representing security and risk controls with definitions, objectives, control function (preventive, detective, corrective, compensating), ownership, implementation scope, methodology- aware factor mappings (FAIR-CAM strength/coverage, NIST, ISO), and effectiveness data (GC-I001)
- Six-state control lifecycle: DRAFT, PROPOSED, IMPLEMENTED, OPERATIONAL, DEPRECATED, RETIRED with reinstatement from DEPRECATED to OPERATIONAL
- ControlLink entity for outbound linking to assets, risk scenarios, observations, evidence, requirements, code, configuration, operational artifacts, and external references
- Seven link relationship types: PROTECTS, IMPLEMENTS, EVIDENCED_BY, OBSERVED_IN, MITIGATES, MAPS_TO, ASSOCIATED
- REST API endpoints:
POST/GET /api/v1/controls,GET/PUT/DELETE /api/v1/controls/{id},GET /api/v1/controls/uid/{uid},PUT /api/v1/controls/{id}/status,POST/GET /api/v1/controls/{id}/links,DELETE /api/v1/controls/{id}/links/{linkId} - MCP tools:
gc_create_control,gc_list_controls,gc_get_control,gc_update_control,gc_delete_control,gc_transition_control_status,gc_create_control_link,gc_list_control_links,gc_delete_control_link - Database migrations V046-V047 for control and control_link tables with Envers audit
- CONTROL promoted from external string identifier to internal entity in GraphTargetResolverService for both asset links and risk scenario links
- CONTROL added to ArtifactType for traceability linking
- Codex-backed Ground Control MCP workflow tools:
gc_codex_architecture_preflightfor pre-implementation ADR/design guidance andgc_codex_reviewfor exhaustive no-triage production-quality review - Repo-context helper tool
gc_get_repo_ground_control_context, plus a standardizedAGENTS.mdconvention for declaring the repo's Ground Control project before/implementruns - Codex architecture-preflight prompt builder that emphasizes reuse of existing cross-cutting concerns, avoidance of abstraction and concept confusion, and explicit non-goals/gotchas before coding starts
- Codex review prompt builder that explicitly asks for an exhaustive, non-triaged review across maintainability, reliability, security, consistency, validation, logging, exception handling, schema reuse, and reuse of existing infrastructure
- Unit coverage for the new Codex prompt and command builders
/implementnow requires a Codex architecture preflight before plan mode and usesgc_codex_reviewinstead of a raw shell review command/implementnow validates repo-local Ground Control context fromAGENTS.mdand stops instead of guessing a project when the convention is missing or invalid/shipnow includes the same Codex review tool in its review pipeline- Development workflow and MCP server documentation now describe the Codex preflight/review integration explicitly
- Input validation on GitHub owner/repo parameters at every entry point: GitHubCliClient, SyncController, GitHubIssueRequest, MCP tools gc_sync_github and gc_create_github_issue (GC-D001)
- GitHub issue state (OPEN/CLOSED) now reflected in traceability link titles during sync, satisfying bidirectional state visibility (GC-D001)
- Defensive IssueState parsing: unknown states default to OPEN with a warning instead of crashing the sync
- Validation on issue creation inputs: title length (256 chars), body length (65536 chars), and label format/length (50 chars)
- Unit tests for input validation rejection of command injection payloads, malicious owner/repo names, and state reflection in traceability links
- Populated risk assessment methodology profile schemas defining the semantics, factors, scales, units, and output rules for each supported methodology (GC-T002)
- FAIR v3.0 input/output schemas with FAIR-CAM control analytics inputs (control_strength, control_coverage) and FAIR-MAM loss magnitude extensions (productivity_loss, response_cost, replacement_cost, competitive_advantage_loss, fines_and_judgments, reputation_damage)
- NIST SP 800-30 Rev. 1 input/output schemas with five-level likelihood and impact scales, threat source characterization, and 5x5 risk matrix mapping
- ISO 27005:2022 input/output schemas with ISO 27001-compatible risk criteria, organization-defined acceptance thresholds, and consequence- based terminology
- Legacy qualitative profile with open schemas for backwards compatibility with pre-methodology assessments
- Database migration V045 to populate existing methodology profile seed data with proper schemas
- WebMvcTest controller unit test for MethodologyProfileController
- First-class Risk Scenario entity representing scoped statements of potential future loss tied to operational assets within a defined time horizon, supporting FAIR, NIST SP 800-30, and ISO-style risk methods (GC-T009)
- Risk scenario fields: threat source/actor, threat event/method, affected object, vulnerability/exposure/resistance condition, consequence, time horizon, observation references, topology context
- Six-state lifecycle: DRAFT, IDENTIFIED, ASSESSED, TREATED, ACCEPTED, CLOSED with early-close shortcuts from IDENTIFIED/ASSESSED/TREATED
- Risk Scenario Link entity for outbound linking to threat models, vulnerabilities, controls, findings, evidence, audit records, risk registers, observations, assets, requirements, and external artifacts
- Nine link relationship types: MITIGATED_BY, EXPLOITS, AFFECTS, EVIDENCED_BY, GOVERNED_BY, ASSESSED_IN, REGISTERED_IN, OBSERVED_IN, ASSOCIATED
- REST API endpoints:
POST/GET /api/v1/risk-scenarios,GET/PUT/DELETE /api/v1/risk-scenarios/{id},GET /api/v1/risk-scenarios/uid/{uid},PUT /api/v1/risk-scenarios/{id}/status,POST/GET /api/v1/risk-scenarios/{id}/links,DELETE /api/v1/risk-scenarios/{id}/links/{linkId} - MCP tools:
gc_create_risk_scenario,gc_list_risk_scenarios,gc_get_risk_scenario,gc_update_risk_scenario,gc_delete_risk_scenario,gc_transition_risk_scenario_status,gc_create_risk_scenario_link,gc_list_risk_scenario_links,gc_delete_risk_scenario_link - Database migrations V039-V042 for risk scenario and risk scenario link tables with Envers audit
- RISK_SCENARIO added to ArtifactType for traceability linking
- First-class Observation entity for recording time-bounded state facts about operational assets, such as configuration values, exposure status, identity assignments, deployment attributes, patch state, or discovered relationships (GC-M015)
- Observations are distinct from asset definitions and record source, observed-at time, freshness/validity window (expires-at), confidence, and supporting evidence references
- Seven observation categories: CONFIGURATION, EXPOSURE, IDENTITY, DEPLOYMENT, PATCH_STATE, RELATIONSHIP, OTHER
- REST API endpoints:
POST/GET /api/v1/assets/{id}/observations,GET/PUT/DELETE /api/v1/assets/{id}/observations/{obsId},GET /api/v1/assets/{id}/observations/latestfor current-state snapshots - MCP tools:
gc_create_observation,gc_list_observations,gc_get_observation,gc_update_observation,gc_delete_observation,gc_list_latest_observations - Database migrations V035-V036 for observation table with Envers audit
- External identifiers and source provenance for operational assets: assets can now be mapped to their representations in external source systems (AWS ARN, Terraform resource ID, ServiceNow CI, etc.) with collection timestamps and confidence metadata (GC-M014)
- Source provenance on asset relations: topology facts now carry optional source system, external source identifier, collection timestamp, and confidence metadata
- Multiple overlapping sources per asset without assuming a single perfect inventory
- REST API endpoints:
POST/GET /api/v1/assets/{id}/external-ids,PUT/DELETE /api/v1/assets/{id}/external-ids/{extIdId},GET /api/v1/assets/external-ids/by-sourcefor reverse lookup - MCP tools:
gc_create_asset_external_id,gc_list_asset_external_ids,gc_update_asset_external_id,gc_delete_asset_external_id,gc_find_asset_by_external_id - Updated
gc_create_asset_relationandgc_get_asset_relationswith provenance fields - Database migrations V031-V034 for asset_external_id table with Envers audit and provenance columns on asset_relation
- Cross-entity asset linking: operational assets can now be linked to requirements, controls, risk scenarios, threat-model entries, findings, evidence, audits, and external artifacts (GC-M010)
- Seven link types: IMPLEMENTS, MITIGATES, SUBJECT_OF, EVIDENCED_BY, GOVERNED_BY, DEPENDS_ON, ASSOCIATED
- Five new asset types: SYSTEM, WORKLOAD, ENDPOINT, INTEGRATION, THIRD_PARTY
- REST API endpoints:
POST/GET /api/v1/assets/{id}/links,DELETE /api/v1/assets/{id}/links/{linkId},GET /api/v1/assets/links/by-targetfor reverse lookup - MCP tools:
gc_create_asset_link,gc_get_asset_links,gc_delete_asset_link,gc_get_asset_links_by_target - Database migrations V029-V030 for asset_link table with Envers audit
- ADR-020: Asset Cross-Entity Linking
- Operational asset domain with typed topology relationships for multi-hop impact, threat, and control analysis (GC-M013)
- Seven relationship types: CONTAINS, DEPENDS_ON, COMMUNICATES_WITH, TRUST_BOUNDARY, SUPPORTS, ACCESSES, DATA_FLOW
- Graph topology analysis: cycle detection, impact analysis, subgraph extraction reusing existing GraphAlgorithms
- REST API endpoints:
/api/v1/assetswith full CRUD, relations management, and topology analysis - MCP tools:
gc_create_asset,gc_list_assets,gc_get_asset,gc_update_asset,gc_delete_asset,gc_archive_asset,gc_create_asset_relation,gc_get_asset_relations,gc_delete_asset_relation,gc_detect_asset_cycles,gc_asset_impact_analysis,gc_extract_asset_subgraph - Database migrations V025-V028 for operational_asset and asset_relation tables with Envers audit tables
- ADR-019: Asset Topology Model
- Architecture Decision Records as first-class entities with full CRUD, status lifecycle (PROPOSED→ACCEPTED→DEPRECATED/SUPERSEDED), and reverse traceability to linked requirements (GC-J001)
- REST API endpoints:
/api/v1/adrswith create, read, update, delete, status transition, and linked requirements lookup - MCP tools:
gc_create_adr,gc_list_adrs,gc_get_adr,gc_update_adr,gc_delete_adr,gc_transition_adr_status,gc_get_adr_requirements - Database migration V023 for
architecture_decision_recordtable
- Enforce requirement-before-code policy: IMPLEMENTS traceability links can only be created against requirements in ACTIVE status (GC-O005)
- Configurable backup frequency (
backup_cron) and local retention (local_retention_count) via Terraform variables (GC-P009) restore.shscript for automated restore from local dump or S3 with safety backup, confirmation prompt, and post-restore verificationtest-restore.shscript for non-destructive restore validation using a temporary PostgreSQL container; runs weekly via cron- Comprehensive backup/restore documentation with configuration table, point-in-time restore explanation, and restore testing procedures
- Sync
deploy/scripts/backup.shwith the embedded user-data version - Add argument guards to
restore.shfor--from-fileand--from-s3flags; show usage on zero arguments - Graceful
docker stopbeforedocker rm -fintest-restore.shcleanup
- Parameterized tests verifying all 9 artifact types (CODE_FILE, TEST, ADR, CONFIG, POLICY, SPEC, PROOF, DOCUMENTATION, GITHUB_ISSUE) round-trip correctly through model construction, JPA persistence, and REST API (GC-E001)
- Scope document export requirement lookup by project instead of global UID; prevents silently binding the wrong requirement when two projects share a UID (closes #435)
- Remove N+1 query amplification from dashboard stats, impact analysis, and requirements export (#437)
- Batch traceability link coverage queries via new
countByLinkTypeGroupedByRequirementIdrepository method - Improve test coverage on changed code to >98%
- Sync architecture docs, version metadata, and coding standards with running system (#439)
- Remove stale
architecture/CODING_STANDARDS.mdfrom Django/Pydantic era (superseded bydocs/CODING_STANDARDS.md)
- Normalize GitHub issue traceability identifiers to raw integer strings
so created links sync correctly with
GitHubIssueSyncService(#434)
- Align frontend enum values with backend single source of truth (#433)
- Remove hardcoded enum arrays from React components in favor of
centralized
api.tstype definitions - Add enum contract test (
enum-contract.test.ts) to prevent frontend/backend enum drift
- Reject baseline comparisons across different projects with a clear
cross_project_comparisondomain validation error
- Export documents to ReqIF 1.2 XML format for tool interoperability via
GET /api/v1/export/document/{id}?format=reqif(GC-B010) - Round-trip tested: export produces valid XML parseable by
ReqifParser gc_export_documentMCP tool now supportsreqifformat
- Export documents to PDF format for formal distribution via
GET /api/v1/export/document/{id}?format=pdf(GC-B009) gc_export_documentMCP tool now supportspdfformat (returns base64)
- Export documents to HTML format for web publishing via
GET /api/v1/export/document/{id}?format=html(GC-B008) - Self-contained HTML with inline CSS, print-friendly styles, XSS-safe escaping, and responsive layout
gc_export_documentMCP tool now acceptsformatparam (sdocorhtml)
- Export documents to StrictDoc (.sdoc) format via
GET /api/v1/export/document/{documentId}(GC-B007) - Lossless round-trip for sections, requirements, text blocks, and PARENT relations between import and export
- MCP tool
gc_export_documentfor programmatic .sdoc export
- StrictDoc import now creates documents, sections, and text blocks, preserving the source file hierarchy (GC-B006)
- SdocParser returns structured
SdocDocumentwith sections and ordered content items (requirement references and text blocks) - Import response includes
documentsCreated,sectionsCreated, andsectionContentsCreatedcounters - Idempotent document/section creation — re-importing skips existing documents and sections by title match
- Extract duplicate
"bad_request"string literal to constant inGlobalExceptionHandler - Extract duplicate
"relations"string literal to constant inImportService - Replace
Stream.collect(Collectors.toList())withStream.toList()inAnalysisService - Use
Map.computeIfPresent()instead of get-and-check pattern inReqifParser - Add explicit regex grouping for alternation precedence in
AgeGraphService - Reduce loop break/continue count in
ImportServiceby extracting helper methods
- Refactor
EmbeddingService.embedProjectto reduce cognitive complexity by extracting batch processing and embedding classification helpers - Refactor
AnalysisService.getWorkOrderto reduce cognitive complexity by extracting dependency mapping, blocking status computation, topological sorting, and wave item building into private methods - Refactor
GitHubIssueSyncService.syncGitHubIssuesto reduce cognitive complexity by extracting issue upsert and traceability link update phases - Refactor
SdocParser.parseto reduce cognitive complexity by extracting wave range building, block extraction, and field parsing helpers
- Export requirements data to CSV, Excel (.xlsx), and PDF formats via
GET /api/v1/export/requirements?format={csv|xlsx|pdf} - Export sweep analysis results to CSV, Excel, and PDF via
POST /api/v1/export/sweep?format={csv|xlsx|pdf} - MCP tools
gc_export_requirementsandgc_export_sweep_reportfor programmatic export access - Shared
CsvUtilsutility centralizing CSV formula-injection protection - Apache POI (Excel) and OpenPDF (PDF) dependencies for report generation
- Entity type filtering on graph visualization and subgraph extraction
endpoints via
entityTypesquery parameter entityTypefield on graph visualization nodes for client-side type identification
- Requirement-section membership constraint: a requirement can belong to at most one document section, enforced by partial unique index and service validation
gc_create_github_issueMCP tool now uses localghCLI instead of the backend API, fixing "gh not found" errors when the backend Docker container lacksghauthentication
- Per-document grammars defining custom fields, allowed requirement types, and
allowed relation types as JSONB metadata (
PUT /api/v1/documents/{id}/grammar,GET /api/v1/documents/{id}/grammar,DELETE /api/v1/documents/{id}/grammar) custom_fieldsJSONB column on requirements for project-specific field values- MCP tools:
gc_set_document_grammar,gc_get_document_grammar,gc_delete_document_grammar
- Document reading order view rendering sections, text blocks, and
requirements in authored sequence (
GET /api/v1/documents/{id}/reading-order) - MCP tool:
gc_get_document_reading_order BaseEntity@MappedSuperclassfor shared JPA entity boilerplate (id, createdAt, updatedAt, lifecycle callbacks)
- Remove nullable
Optionalfields fromUpdateQualityGateCommandto resolve SonarCloud S2789 reliability bugs on dev branch
- Content ordering within sections via SectionContent entity supporting
requirement references and text blocks with sort order for deterministic
rendering (
POST /api/v1/sections/{id}/content,GET /api/v1/sections/{id}/content) - MCP tools:
gc_add_section_content,gc_list_section_content,gc_update_section_content,gc_delete_section_content
- Hierarchical sections within documents with arbitrary nesting depth,
sibling ordering, and nested tree retrieval
(
POST /api/v1/documents/{id}/sections,GET /api/v1/documents/{id}/sections/tree) - MCP tools:
gc_create_section,gc_list_sections,gc_get_section_tree,gc_get_section,gc_update_section,gc_delete_section
/shipskill: consolidated post-implementation workflow (CI monitor, SonarCloud check, code review, security review) in a single command/implementclause-by-clause verification step (Step 4.5) requiring explicit requirement-to-code mapping before completion- Stop hook with completion verifier agent that blocks session end if CHANGELOG, traceability links, or status transitions are missing
- PostToolUse hook for automatic Java formatting (spotlessApply) after file edits
.claude/rules/with implementation quality and review standards rules- Required status checks on main and dev branches (build, test, integration, verify, sonarcloud)
- SonarCloud CI job is now blocking (removed continue-on-error) and gates Docker image builds
- Simplified
.claude/settings.local.jsonpermissions from 90+ one-off entries to ~20 wildcard patterns
- Document entity as top-level container for organized requirement collections
with project-scoped title uniqueness (
POST /api/v1/documents,GET /api/v1/documents,PUT /api/v1/documents/{id},DELETE /api/v1/documents/{id}) - MCP tools:
gc_create_document,gc_list_documents,gc_get_document,gc_update_document,gc_delete_document
- Configurable quality gates for CI/CD integration (
POST /api/v1/quality-gates,POST /api/v1/quality-gates/evaluate) with per-project pass/fail thresholds for coverage, orphan count, and completeness metrics - Quality gate evaluation integrated into analysis sweep reports
- MCP tools:
gc_create_quality_gate,gc_list_quality_gates,gc_get_quality_gate,gc_update_quality_gate,gc_delete_quality_gate,gc_evaluate_quality_gates
- Structured requirement version diff API (
GET /api/v1/requirements/{id}/diff) returning per-field changes, added/removed/modified relations, and added/removed/modified traceability links between two revision numbers - MCP tool
gc_get_requirement_difffor agent-driven change review workflows
- Split monolithic frontend page components (
requirement-detail,requirements,graph) into focused feature-level modules undercomponents/requirement-detail/,components/requirements/, andcomponents/graph/ - Introduced route-level code splitting via
React.lazy+Suspensefor all major routes; Cytoscape (~537 KB) now loads only when the graph route is visited
- Project-wide audit timeline endpoint (
GET /api/v1/audit/timeline) aggregating changes across all requirements in a project - Actor filtering on requirement and project audit timelines
- CSV export of audit timeline for compliance reporting
(
GET /api/v1/audit/timeline/export) - Optional
reasonfield on status transitions, recorded in the audit trail for governance traceability - Configurable audit data retention with scheduled cleanup
(
GC_AUDIT_RETENTION_DAYS, disabled by default) - MCP tools:
gc_get_project_timeline,gc_export_audit_timeline - MCP tools
gc_transition_statusandgc_bulk_transition_statusnow accept optionalreasonparameter
- Add
latestDocker tag for default branch pushes in CI workflow so EC2 deploy can pullground-control:latestfrom ECR - Capture both stdout and stderr from SSM deploy command on failure for proper diagnostics (previously only stderr was shown, hiding docker logs)
- Increase deploy health check timeout from 60s to 10min, SSM command timeout from 120s to 660s, and CI wait loop to match
- Fix V014 Flyway migration failing on prod data with case-duplicate UIDs
(
OBS-001/obs-001): drop unique constraint before normalizing to uppercase, and deduplicate colliding rows by renaming with-DUP-Nsuffix
- Fix
RequirementService.getRelations()mutating unmodifiable JPA result list by creating a mutable copy before combining outgoing and incoming relations (closes #321)
- Replace
List<Map<String, Object>>error fields in API responses with typed records (GC-A012 tech debt, closes #324):BulkStatusTransitionResponse.failednow usesBulkFailureDetail(id, uid, error)ImportResultResponse.errorsnow usesImportError(phase, uid, error, parent, target, issueRef)SyncResultResponse.errorsnow usesSyncError(phase, issue, artifactIdentifier, error)
- Domain result records
BulkTransitionResult,ImportResult,SyncResultupdated accordingly - Audit JSONB persistence unchanged —
RequirementImport.errorscolumn remains untyped JSON
- Paginate
GitHubCliClient.fetchAllIssues()using GitHub REST API to fetch all issues instead of silently truncating at 500; filters out pull requests and normalizes state values (closes #317)
- Replaced N+1 in-memory filtering in
AnalysisService.findOrphans()andfindCoverageGaps()with single JPQLNOT EXISTSqueries inRequirementRepository(closes #318)
- Added exception handlers for
HttpMessageNotReadableException,MethodArgumentTypeMismatchException,MissingServletRequestParameterException,MissingServletRequestPartException, and genericExceptioncatch-all to ensure all API errors return the consistentErrorResponseenvelope (closes #315)
- JML contract annotations on
TraceabilityLinkdomain model: class invariants, constructor pre/postconditions, and setter contracts forsetSyncStatus,setArtifactUrl, andsetArtifactTitle(closes #327)
- Semantic similarity detection (GC-C016): pairwise cosine similarity analysis across requirement embeddings, returning overlap candidates above a configurable threshold sorted by similarity score
- REST API endpoint:
GET /api/v1/analysis/semantic-similarity?threshold=0.85&project=... - MCP tool:
gc_analyze_similaritywith optional threshold and project parameters - Configurable default threshold via
GC_EMBEDDING_SIMILARITY_THRESHOLD(default 0.85) - Auto-re-embed on requirement text change: updating title, statement, or rationale automatically triggers re-embedding after the transaction commits (fire-and-forget, gracefully skipped when no provider is configured)
- Requirement text embedding infrastructure (GC-C015): pluggable vector embedding of requirement text content (title, statement, rationale) with content-hash-based staleness detection and batch embedding support
EmbeddingProviderdomain interface withNoOpEmbeddingProvider(default, graceful degradation) andOpenAiEmbeddingProvider(conditional onGC_EMBEDDING_PROVIDER=openai)- REST API endpoints:
POST /api/v1/embeddings/{id},GET /api/v1/embeddings/{id}/status,POST /api/v1/embeddings/batch,DELETE /api/v1/embeddings/{id} - MCP tools:
gc_embed_requirement,gc_get_embedding_status,gc_embed_project - Flyway migration V015 creates
requirement_embeddingtable with BYTEA storage, SHA-256 content hash, and model tracking - Configuration via
GC_EMBEDDING_PROVIDER,GC_EMBEDDING_API_KEY,GC_EMBEDDING_MODEL,GC_EMBEDDING_DIMENSIONS,GC_EMBEDDING_BATCH_SIZE
- Requirement UID uniqueness is now case-insensitive per project:
OBS-001andobs-001can no longer coexist as separate requirements - Flyway migration V014 normalizes existing UIDs to uppercase and replaces the
composite unique constraint with a functional index on
LOWER(uid) - Service layer normalizes UIDs to uppercase on create and clone
- All UID lookups (create, clone, import, GitHub sync, getByUid) use case-insensitive matching
- Subgraph extraction endpoint
GET /api/v1/graph/subgraph?roots=UID1,UID2(GC-G003): given a set of root requirements, returns all transitively reachable requirements and their relations as a self-contained graph - MCP tool
gc_extract_subgraphfor API/MCP parity
- Path finding endpoint
GET /api/v1/graph/pathsnow returns structured response with nodes and edges (including relation types) instead of flat UID arrays (GC-G002)
- Unified graph visualization endpoint
GET /api/v1/graph/visualization(GC-G005): returns all requirement nodes and relation edges in a single response - MCP tool
gc_get_graph_visualizationfor API/MCP parity
- Frontend graph page fetches all data in a single API call instead of N+1 separate requests (paginated requirements + per-requirement relation fetches)
- Interactive dependency graph enhancements (GC-Q005): explicit filter controls for status, priority, series, and wave that remove non-matching nodes from the graph layout (distinct from legend click-to-filter visual highlighting)
- Wave-ordered DAG layout modes (
dagre-wave-tb,dagre-wave-lr) that group nodes by wave number while preserving dagre's edge-based ordering - Frontend test infrastructure: vitest with
make frontend-testtarget - Unit tests for graph-constants module (
getSeries,getNodeColor,getColorMap)
- Standalone roadmap-viewer prototype (
tools/roadmap-viewer/) and its nginx service from docker-compose — superseded by the React graph page
- Audit history timeline (GC-Q006): unified timeline endpoint
GET /api/v1/requirements/{id}/timelinethat merges requirement, relation, and traceability link changes into a single chronologically-sorted view with field-level diffs between consecutive revisions - Timeline supports filtering by change category (REQUIREMENT, RELATION, TRACEABILITY_LINK) and date range (from/to)
- MCP tool
gc_get_timelinefor querying the unified audit timeline - Frontend timeline UI on the requirement detail History tab with visual vertical timeline, expandable field-level diff views, and filter controls
- Scheduled analysis sweeps (GC-C013): configurable cron-based execution of the full analysis suite (orphan detection, coverage gaps, cross-wave validation, cycle detection, consistency checks) with GitHub issue and webhook notification support for detected problems
- REST API endpoints:
POST /api/v1/analysis/sweep(single project) andPOST /api/v1/analysis/sweep/all(all projects) for manual sweep triggering - MCP tool
gc_run_sweepfor triggering analysis sweeps via MCP - Configurable notification channels: GitHub issue creation and webhook POST for sweep results with problems
- GitHub CLI (
gh) not found by Java backend: now auto-resolves the binary path from common locations (/usr/bin/gh,/usr/local/bin/gh,/opt/homebrew/bin/gh) and supports explicit override viaGC_GH_PATHenvironment variable
- Slide-out detail panel on the requirements explorer: clicking a table row opens an inline panel showing requirement details, status transitions, and editing — without navigating away from the list
- Reusable
SlidePanelUI component (right-edge drawer with slide animation) - Selected row highlight in requirements table when detail panel is open
- Project switcher now preserves query string (e.g.,
?status=ACTIVE) when switching projects - Unknown routes (
/p/:projectId/bad-page,/random-path) now render a "Page not found" message instead of a blank page
- Move project identity from localStorage into URL path (
/p/:projectId/...), making the URL the single source of truth for project context - Route structure changed: project-scoped pages now live under
/p/:projectId/(e.g.,/p/my-project/requirements);/projectsstays at root level ProjectProvidernow derivesactiveProjectfromuseParams()instead of localStorage;setActiveProjectnavigates to the new project URL- Project switcher preserves the current sub-path when switching projects
- Projects page uses
useProjects()directly instead ofuseProjectContext() - Root
/redirects to/p/<first-project>/; invalid project IDs redirect to/projectswith a toast - All
navigate()andLinkpaths updated to use project-prefixed URLs across dashboard, requirements, requirement detail, and analysis pages
- localStorage-based project persistence (
gc-active-projectkey)
- Refactor
ImportService: extract shared helpers (upsertRequirements,createParentRelations,resolveRequirementId,createExplicitRelations,createTraceabilityLinks,saveAuditAndBuildResult) to reduce cognitive complexity and duplication betweenimportStrictdocandimportReqif - Extract
ParsedRequirementrecord andImportCountersaccumulator as shared types - Extract
ATTR_IDENTIFIERandATTR_LONG_NAMEstring constants inReqifParser
- 7 new tests for uncovered reqif relation paths (DB fallback, missing parent/source/target, creation errors for hierarchy and explicit relations)
@SuppressWarnings("java:S2187")onReqifParserTestto suppress false positive
- Fix SonarCloud S1751 bug in
ReqifParser.extractAttrValueText— unconditionalreturninsideforloop replaced with explicit first-element check
- Remove dead
relationsfield fromReqifRequirementrecord (was never populated) - Remove redundant null check in
extractAttrValueText(getAttributenever returns null) - Make
stripXhtmlmethod private (only used internally) - Add comment clarifying hierarchy + SpecRelation overlap behavior in Phase 2b
- Test: title fallback from
LONG-NAMEtoReqIF.Nameattribute value - Test: hierarchy + explicit SpecRelation overlap correctly skips duplicate
- ReqIF 1.2 import — bulk-import requirements from
.reqiffiles produced by enterprise tools (IBM DOORS, Polarion, Jama) - REST API:
POST /admin/import/reqif(multipart/form-data) - MCP tool:
gc_import_reqifwithfile_pathand optionalprojectparameters - Parses SPEC-OBJECTS (title, statement), SPEC-RELATIONS (explicit relations), and SPECIFICATION hierarchy (parent-child nesting)
- XHTML attribute values stripped to plain text
- XXE prevention: DTDs and external entities disabled
- Relation type mapping from ReqIF type names via naming convention (contains "parent" → PARENT, "depends" → DEPENDS_ON, etc.)
- Deterministic UID truncation for identifiers exceeding 50 characters
- Update integration test migration assertions to include V013 (
create_baseline)
- Baseline management — named point-in-time snapshots of the requirement set for release management, audit trails, and specification evolution tracking
- REST API:
POST/GET /baselines,GET /baselines/{id},GET /baselines/{id}/snapshot,GET /baselines/{id}/compare/{otherId},DELETE /baselines/{id} - MCP tools:
gc_create_baseline,gc_list_baselines,gc_get_baseline,gc_get_baseline_snapshot,gc_compare_baselines,gc_delete_baseline - Baseline snapshots reconstruct requirements via Hibernate Envers
forEntitiesAtRevision(), filtered by project and non-archived status - Baseline comparison diffs two snapshots showing added, removed, and modified requirements with before/after detail
- Move
SATISFIED_STATUSESandPRIORITY_ORDERstatic fields to top ofAnalysisServicealongside other static constants
- Test: cycle participants appended sorted by priority in work order
- Test: cross-wave dependencies excluded from intra-wave topological sort
- Work order API (
GET /api/v1/analysis/work-order) — topologically-sorted, DAG-derived work order grouped by wave, with MoSCoW priority tie-breaking gc_get_work_orderMCP tool with REST/MCP parityGraphAlgorithms.topologicalSort()— Kahn's algorithm with priority tie-breaking for deterministic ordering- Blocking status detection: each requirement classified as UNBLOCKED, BLOCKED, or UNCONSTRAINED based on dependency satisfaction
- AWS EC2 deployment infrastructure — single
t3a.smallinstance running Docker Compose with Tailscale-only access (zero public ingress) (ADR-018) - Terraform
computemodule: EC2 instance, IAM instance profile, EBS data volume with cloud-init bootstrapping (Docker, Tailscale, compose) - Terraform
backupmodule: S3 bucket for pg_dump backups (30-day lifecycle), DLM policy for daily EBS snapshots (7-day retention) - ECR container registry for deployment images — EC2 pulls via IAM role (no tokens needed), CI pushes to both GHCR and ECR
- Production Docker Compose (
deploy/docker/docker-compose.prod.yml) — ECR image, EBS bind mounts, no Redis, JVM memory caps - Automated deployment: CI pushes to
maintrigger deploy to EC2 via SSMSendCommandafter smoke test passes — no manual SSH needed - Operational scripts:
backup.sh(pg_dump + S3),watchdog.sh(health check- auto-restart),
deploy.sh(pull + restart + verify)
- auto-restart),
- Makefile targets:
deploy(SSH deploy to EC2),deploy-infra(terraform apply) - ADR-018: AWS EC2 Deployment — documents architecture, cost, and rationale
- Terraform
networkingmodule rewritten for zero-ingress security group (Tailscale-only, was CIDR-based ingress for RDS) - Terraform
secretsmodule rewritten for Tailscale auth key + DB password (was RDS host/user/pass) - Terraform
environments/devrewritten to wire compute + networking + backup- secrets modules (was RDS + networking + secrets)
- Bootstrap IAM policy updated: replaced RDS permissions with EC2, IAM instance profile, S3 backup bucket, DLM, SSM SendCommand, and ECR permissions
- CI workflow (
ci.yml): addeddeployjob that auto-deploys to EC2 on push tomain, addedid-token: writepermission for OIDC, added ECR push alongside GHCR - Deployment docs updated with AWS deployment section
- TypeScript build errors in
requirements.tsx— added explicit types forBulkStatusTransitionResponsecallback andRequirementResponsemap parameter - Docker build failure:
.gitignorepatternlib/was excludingfrontend/src/lib/(api-client, query-client, utils) from git — changed to/lib/so it only matches the repo-root Python dist directory
- Terraform
rdsmodule (stale — RDS withdrawn per ADR-015)
- Project health dashboard endpoint
GET /api/v1/analysis/dashboard-stats— returns aggregate metrics: requirement counts by status and wave, traceability coverage percentages per link type, and recent changes (GC-Q004) gc_dashboard_statsMCP tool for dashboard stats retrieval- Enriched frontend dashboard with wave progress bars, traceability coverage percentages, recent changes feed, and clickable stat cards linking to detail views
- CI Docker build and smoke test used
context: backend/but the Dockerfile references repo-root paths (backend/,frontend/) — changed tocontext: .withfile: backend/Dockerfileto match docker-compose.yml
- Completeness analysis backend endpoint
GET /api/v1/analysis/completeness— returns total count, status distribution, and missing-field issues (GC-C008) gc_analyze_completenessMCP tool now calls the backend API instead of doing client-side computation, achieving full REST/MCP parity for all 7 analysis operations- Completeness tab on the frontend analysis page
- Coverage-gaps integration test
- Consistency violation detection analysis — detects ACTIVE requirements linked
by
CONFLICTS_WITHrelations andSUPERSEDESrelations where both sides are ACTIVE (GC-C007) - REST endpoint
GET /api/v1/analysis/consistency-violations gc_analyze_consistencyMCP tool- Consistency tab on the frontend analysis page
sortparameter ongc_list_requirementsMCP tool, achieving parity with the REST API'ssortquery parameter (e.g.sort: "uid,asc")
- Graph view zoom/scroll speed was too slow (wheelSensitivity 0.3 → 1)
- Cross-wave validation logic was inverted — flagged valid "later depends on earlier" relationships instead of invalid "earlier depends on later" ones
- All analysis endpoints (cycles, orphans, coverage gaps, cross-wave) now exclude archived requirements
- Full-parity frontend — every REST API capability is now accessible via the UI, covering all 34 endpoints across 7 controllers
- Requirements list page — paginated table with filtering (status, type, priority, wave, free-text search), column sorting, bulk status transitions via checkbox selection, per-row status dropdown for quick transitions, and create modal
- Requirement detail page with tabbed interface:
- Details tab: view/edit all fields, status transitions, clone, archive
- Relations tab: list, add, delete relations with search-based target picker
- Traceability tab: list, add, delete traceability links to external artifacts
- History tab: audit timeline showing all revisions with snapshots
- Impact tab: transitive impact analysis for the requirement
- Dashboard rewrite — project health overview with requirement counts by status and clickable analysis alert cards (cycles, orphans, coverage gaps, cross-wave violations)
- Analysis page — tabbed view for dependency cycles, orphan requirements, coverage gaps (by link type), and cross-wave violations
- Projects page — list, create, edit, and switch projects
- Admin page — StrictDoc import (file upload), GitHub sync, GitHub issue creation, and graph materialization
- Shared type definitions (
src/types/api.ts) for all API request/response types apiDelete()andapiUpload()utilities in the API client- React Query hooks:
use-requirements,use-relations,use-traceability,use-analysis,use-history - Reusable UI components: Modal, Badge (status/priority/type), FormField, ConfirmDialog, Toast notifications, StatusBadgeDropdown, RequirementForm, RelationForm, TraceabilityForm
- Navigation expanded: Dashboard, Requirements, Graph, Analysis, Projects, Admin
- Radix UI dependencies: dialog, tabs, dropdown-menu, toast, checkbox
- Web application shell (GC-Q008): Bootstrap React 19 frontend with Vite 6, TanStack Query 5, React Router 7, and Tailwind CSS 4
- Project switcher in app header — persistent project selection via localStorage, auto-selects when only one project exists, hidden when single-project
- Interactive graph view — full port of the roadmap viewer into the React app with Cytoscape.js, dagre layout, color-by (series/priority/status/wave), legend filtering, node click highlighting, tooltips, fit/reset controls
- Dashboard page showing active project details
- Requirements page with project-scoped requirement listing
SpaController— Spring Boot controller forwarding non-API routes toindex.htmlfor client-side routing- Typed
apiFetch<T>()wrapper with automatic?project=injection from context - Multi-stage Docker build: Node frontend stage → Spring Boot backend stage
- Makefile targets:
frontend-install,frontend-dev,frontend-build,frontend-lint,frontend-format - Biome for frontend formatting and linting
- Docker build context changed from
backend/to project root (.) with explicitdockerfile: backend/Dockerfile docker-buildMake target updated for new build context
- Project scoping (GC-A013): Ground Control now supports multiple independent projects within a single instance. All requirements, relations, and analysis are scoped to a project.
POST /api/v1/projects— create a new projectGET /api/v1/projects— list all projectsGET /api/v1/projects/{identifier}— get project by identifierPUT /api/v1/projects/{identifier}— update project name/description- Optional
projectquery parameter on requirement, analysis, graph, import, and GitHub issue endpoints. When omitted and only one project exists, auto-resolves to that project. When multiple projects exist and param is missing, returns 422. gc_list_projectsandgc_create_projectMCP tools- Optional
projectparameter on 17 existing MCP tools for project-scoped operations project_identifierfield in all requirement API responses- Same-project validation: relations can only be created between requirements in the same project
- Flyway migration V012: creates
projecttable, inserts default "ground-control" project, addsproject_idto requirements with composite unique constraint(project_id, uid) - Composite indexes on
(project_id),(project_id, status),(project_id, uid) gc_analyze_completenessMCP tool for requirement completeness analysis
- Breaking:
PUT /api/v1/requirements/{id}now usesUpdateRequirementRequestDTO — all fields are optional for partial updates,uidremoved from request body
- Interactive graph screenshot in README showing DAG layout and requirement details
- Omitting
wavein a requirement update request no longer resets it to null gc_update_requirementMCP tool no longer acceptsuidparameter (UID updates were silently ignored); partial updates now work correctly without 422 errors
- Breaking:
GET /api/v1/analysis/cyclesnow returns objects withmembersandedgesfields instead of plain UID arrays. Each edge includessourceUid,targetUid, andrelationType, fulfilling GC-C001 requirement to report which relation types form each cycle (GC-C001)
- 9 new MCP tools for full REST/MCP feature parity (GC-A012):
gc_get_requirement_history,gc_get_relation_history,gc_get_traceability_link_history,gc_delete_relation,gc_delete_traceability_link,gc_materialize_graph,gc_get_ancestors,gc_get_descendants,gc_find_paths - REST endpoint
POST /api/v1/admin/github/issuesto create GitHub issues from requirements, with automatic traceability link creation GitHubClient.createIssue()domain interface method andGitHubCliClientimplementation usinggh issue createCLICreateGitHubIssueCommandandCreateGitHubIssueResultdomain recordsGitHubIssueSyncService.createIssueFromRequirement()orchestrates issue creation, body formatting from requirement metadata, and traceability link creation with graceful degradation on link failureGitHubIssueController,GitHubIssueRequest, andGitHubIssueResponseAPI layer types- Unit tests for controller and service; URL parsing test for
GitHubCliClient
gc_create_github_issueMCP tool now delegates to the backend REST API instead of shelling out toghCLI directly
- Actor identity population via
X-ActorHTTP header on every request (ActorFilter); defaults to "anonymous" when header is absent (GC-P002) - Audit history API for relations:
GET /api/v1/requirements/{id}/relations/{relationId}/history - Audit history API for traceability links:
GET /api/v1/requirements/{id}/traceability/{linkId}/history - MCP server now sends
X-Actor: mcp-serverheader on all API requests - Unit tests for
ActorFilter, relation history endpoint, and traceability link history endpoint - Integration tests for actor identity recording, relation history, and traceability link history
- JaCoCo line coverage threshold raised from 30% to 80% to match SonarCloud quality gate
- Audit history REST endpoint:
GET /api/v1/requirements/{id}/historyreturns chronological list of all revisions with revision type, timestamp, actor, and full entity snapshot at each point in time (GC-A006) - Custom Envers revision entity (
GroundControlRevisionEntity) withactorcolumn for tracking who made each change (nullable until auth is added) ActorHolderthread-local utility for propagating actor identity to EnversAuditServicefor querying Hibernate Envers revision history- Flyway migration V011: adds
actorcolumn torevinfotable - Integration test for audit history endpoint (create + update + verify history)
- Integration tests for
RequirementSpecifications: all 6 spec methods andfromFilter()branches tested against real PostgreSQL (19 tests) - Unit tests for
RequirementServiceuncovered branches: create with null optional fields, update with all-null fields, update rationale (3 tests) - JaCoCo report now merges unit + integration test coverage data
RequirementSpecifications.javacoverage: 54.2% line / 55.0% branch -> 100% / 100%RequirementService.javacoverage: 99.0% line / 77.8% branch -> 100% / 100%- Overall project coverage: 89.7% line / 78.3% branch -> 94.2% / 86.8%
- Priority filtering for requirements list endpoint:
GET /api/v1/requirements?priority=MUSTsupports MoSCoW values (MUST, SHOULD, COULD, WONT). Completes GC-A009 priorityparameter ingc_list_requirementsMCP tool
- Docker roadmap viewer 403 Forbidden when files change: mount stable parent
directory (
tools/roadmap-viewer) at/srv/roadmapinstead of mounting subdirectories whose inodes change on git operations
- Cypher injection bug in
escapeCypher(): backslash escaping now runs before quote escaping, preventing malformed output likeO\\'Malley(unescaped quote) Requirement.archive()no longer double-setsarchivedAt— the assignment intransitionStatus(ARCHIVED)is the single canonical sourceImportController.importStrictdoc()wrapsIOExceptioninGroundControlExceptioninstead of leaking it outside the error envelope
- Narrowed
catch(Exception)blocks to specific exception types inImportService(3 blocks →ConflictException | NotFoundException | DomainValidationException) andGitHubIssueSyncService(2 blocks →RuntimeException) - Standardized 8 log messages across
ImportService,GitHubIssueSyncService,GitHubCliClient, andAgeGraphServiceto semantic event names (e.g.import_requirement_failed:,graph_materialized:) - Added
@SuppressWarnings("java:S125")toStatus.javafor block JML annotations - Removed redundant
@TransactionalfromRequirementService.bulkTransitionStatus()(already covered by class-level annotation)
- Requirement cloning:
POST /api/v1/requirements/{id}/clonecreates a new requirement by copying content fields (title, statement, rationale, type, priority, wave) with a new UID in DRAFT status, optionally copying outgoing relations. Implements GC-A007 gc_clone_requirementMCP tool for cloning requirements by UID
- Bulk status transitions:
POST /api/v1/requirements/bulk/transitionaccepts a list of requirement IDs and a target status, applies the same state machine rules to each independently (best-effort semantics — valid transitions succeed, invalid ones collected as failures). Implements GC-A008 BulkTransitionResultdomain record,BulkStatusTransitionRequestandBulkStatusTransitionResponseAPI DTOsgc_bulk_transition_statusMCP tool: accepts UIDs, resolves to UUIDs, calls the bulk endpoint, merges UID-resolution errors into the failure list- Unit tests for
RequirementService.bulkTransitionStatus()(3 tests) andRequirementController.bulkTransitionStatus()(2 tests)
- ADR-017: Split graph visualization into two libraries — React Flow for
structured local neighborhood views (requirement detail page), Sigma.js +
Graphology for force-directed whole-graph exploration (
/graphroute). Replaces single React Flow approach that was wrong for organic exploration of 50–500 node graphs
- Interactive roadmap viewer — Cytoscape.js + dagre DAG visualization of the full requirement graph, served as a containerized nginx static site (implements GC-Q005)
- Color coding switchable between series, priority, status, and wave dimensions
- Node selection with neighborhood highlighting and click-to-deselect
- Edge legend showing actual line styles (solid/dashed/dotted) for relation types
- CORS configuration for dev profile (
CorsConfig,@Profile("dev")) - Backend and roadmap services added to
docker-compose.yml - ADR-017 updated with Cytoscape.js prototype implementation notes
- Duplicate relation pre-check in
RequirementService.createRelation()— returns a cleanConflictExceptioninstead of letting the DB unique constraint produce an unhandled SQL exception (completes GC-A004 service-layer enforcement) - Unit test for duplicate relation rejection (
throwsConflictForDuplicateRelation) - Integration test for duplicate relation rejection end-to-end
(
duplicateRelationThrowsConflict)
SUPERSEDESandRELATEDrelation types, completing all 6 typed DAG relations specified by GC-A003 (PARENT, DEPENDS_ON, CONFLICTS_WITH, REFINES, SUPERSEDES, RELATED). Both are non-DAG types — they do not participate in cycle detection or impact analysis- Unit tests for SUPERSEDES and RELATED relation creation
gc_create_github_issueMCP tool: creates a GitHub issue from a requirement (viaghCLI), formats the issue body with requirement metadata, and auto-creates an IMPLEMENTS traceability link — single command replaces the manual copy-fields →gh issue create→gc_create_traceability_linkworkflowformatIssueBodyandcreateGitHubIssuelibrary functions in MCP serverGH_REPOenv var in.mcp.jsonfor default GitHub repository target
README.mdrewritten for current implemented state: features, getting started, tech stack, architecture, documentation index, project status
- GC-Q001–Q006: new User Interface domain (6 requirements) — Interactive Web Application, Requirements Explorer, Traceability Matrix, Project Health Dashboard, Interactive Dependency Graph, Audit History Timeline
- ADR-016: Project Scoping — architectural decisions for multi-project support (Project entity, same-project relation constraint, project-scoped operations, UID uniqueness scope change)
- ADR-017: Interactive Web Application — technology decisions (React 19 + TypeScript + Vite SPA, embedded in Spring Boot, TanStack Query/Table, React Flow for dependency graph, shadcn/ui components)
- GC-A013 (Project Scoping) — new wave 1 requirement for multi-project support via a Project entity with single-project scoped operations
- GC-A002 (Status State Machine) activated with full traceability: 7 IMPLEMENTS, 4 TESTS, 1 DOCUMENTS links
- Fixed
gc_transition_statusMCP tool description to include missing ACTIVE->ARCHIVED transition
gc_get_relationsMCP tool for inspecting a requirement's incoming and outgoing relations through the MCP interface
- GC-E004 (Link Health Tracking) promoted from wave 3 to wave 2 — staleness detection must ship alongside the features that create traceability links
- GC-E005 (Artifact Change Detection) promoted from wave 3 to wave 2 — same rationale; without change detection, every refactor silently degrades link quality
- Wired 9 orphaned requirements into the dependency graph: GC-C002→GC-A001, GC-D003→GC-D001, GC-D004→GC-D001, GC-I004→GC-I003, GC-M002→GC-M001, GC-N001→GC-A006 (REFINES), GC-N002→GC-N001, GC-P005→GC-F005, GC-P007→GC-B001. Orphan count reduced from 13 to 4 (the remaining 4 are accepted cross-cutting concerns: Authentication, Full-Text Search, Notification System, Multi-Tenancy)
mcp/ground-control/README.md: MCP server usage documentation — setup, workflow order of operations, tool reference table, enum values, error formatdocs/API.md: REST API reference — endpoint tables, filtering, pagination, error envelope, interactive docs pointers
- Requirement listing excludes archived requirements by default (
archivedAt IS NULL); filtering bystatus=ARCHIVEDstill returns them explicitly RequirementService.list()always uses specification path (no more bypass for null filter)- Removed stale
docs/requirements/infrastructure.sdoc(described withdrawn RDS/Terraform infrastructure) docker-compose.yml: database password read from.envinstead of hardcoded; ports bound to127.0.0.1(not0.0.0.0)Makefile:devtarget sources.envbefore running Spring Boot
docs/deployment/DEPLOYMENT.md: rewrote from stale Python 3.12/Django/uv/gunicorn content to actual Java 21/Spring Boot 3.4/Gradle stack.github/PULL_REQUEST_TEMPLATE.md: replacedmypy --strict/tsc/ruff check/biomereferences withmake check(Spotless, SpotBugs, Error Prone, JaCoCo); removed non-existent tenant isolation checklist item.github/ISSUE_TEMPLATE/bug_report.md: removed Kubernetes deployment option and browser field (no frontend exists)README.md: replaced aspirational "verification-aware lifecycle orchestrator" tagline with accurate "requirements management system with traceability and graph analysis"; rewrote "What is Ground Control?" to describe actual current functionality; removed Redis from Quick Start commentdocs/architecture/ARCHITECTURE.md: restructured "What Exists" into categorized sections (entities, services, API, tooling); expanded "Does not exist yet" to include frontend, Redis integration, production deployment, auth, multi-tenancy, AGE optional degradation caveat
archivedAttimestamp now set when transitioning to ARCHIVED via/transitionendpoint (previously only set via/archiveendpoint)LazyInitializationExceptiononGET /api/v1/requirements/{id}/relations— relation queries now use fetch joins to eagerly load source/target requirement entities
make smoke: local smoke test — builds Docker image, runs against fresh PostgreSQL 16, verifies Flyway migrations and health endpoint
- RDS infrastructure destroyed — ADR-015 withdrawn because RDS does not support Apache AGE, violating ADR-005's single-database commitment
- Cloud DB Makefile targets (
cloud-db-env,dev-cloud,cloud-db-ip) - CI terraform job, path detection job, OIDC permissions, workflow_dispatch terraform inputs
- ADR-015 status changed from Accepted to Withdrawn
- CI pipeline simplified:
build → test → integration/verify → docker → smoke(no terraform dependency) - Development defaults to local Docker Compose with
apache/ageimage; named volumegc-postgres-dataprovides data durability across rebuilds
- CI:
docker/build-push-actionSHA had a single-character typo (d→e) causing the docker job to fail; updated to v6.19.2
- Terraform dev environment wiring (
deploy/terraform/environments/dev/): S3 backend configuration, provider setup, module composition (networking → RDS → secrets), and developer-facing outputs (RDS endpoint, SSM paths) terraform.tfvars.exampledocumenting required variables for dev environment- CI smoke test job: builds Docker image, runs against fresh PostgreSQL 16, verifies Flyway migrations apply and health endpoint returns UP
- Unified CI/CD pipeline: all jobs flow through a single dependency chain
(
build → test → integration → docker → smoke) - Docker images now built on
devbranch pushes (in addition tomain/tags) - SonarCloud is now non-blocking (
continue-on-error: true); reports quality metrics without gating merges
- CI race conditions: concurrency group prevents parallel runs on the same branch, cancels in-progress PR runs on new pushes
- CI waste: integration tests now depend on unit tests passing (
needs: [build, test]) - Bootstrap S3 lifecycle rule missing required
filter {}block (future provider error) - RDS module: removed
manage_master_user_password = false(conflicts withpasswordin AWS provider ~>5.0) .gitignore: addedtfplanpattern for extensionless Terraform plan files; removed accidentally committed binary plan file
- Terraform networking module (
deploy/terraform/modules/networking/): security group with configurable ingress CIDR for database access, default VPC lookup - Terraform RDS module (
deploy/terraform/modules/rds/): PostgreSQL 16 on db.t4g.micro, gp3 storage, forced SSL via parameter group, encryption at rest, deletion protection, 7-day backup retention, random password generation - Terraform secrets module (
deploy/terraform/modules/secrets/): SSM Parameter Store entries for database host, username, and password (SecureString)
- Bootstrap IAM role policy expanded with EC2, RDS, and SSM permissions for Terraform CI to plan and apply infrastructure modules
- Terraform bootstrap (
deploy/terraform/bootstrap/): S3 state bucket with versioning, encryption, and public access blocking; DynamoDB lock table for state locking; GitHub Actions OIDC identity provider and IAM role - Terraform CI workflow (
.github/workflows/terraform.yml):terraform fmt,validate, andplanon PRs todeploy/terraform/**; manualapplyviaworkflow_dispatch; AWS authentication via OIDC federation - ADR-015 updated with Terraform CI/CD sub-decision
- Pre-commit hooks for Terraform:
terraform_fmt,terraform_validate(antonbabenko/pre-commit-terraform), and Checkov IaC security scanning
- Infrastructure requirements (
docs/requirements/infrastructure.sdoc): 10 requirements across cloud database, infrastructure as code, and developer workflow sections - ADR-015: Cloud Database Deployment — RDS PostgreSQL 16 in catalyst-dev (us-east-2), SSM for credentials, Terraform for IaC, accepts AGE unavailability per ADR-005
- Phase 2 design notes (
architecture/notes/phase2-cloud-database-design.md): topology, RDS configuration, security model, Terraform structure, cost estimate, migration paths - 6 GitHub issues for cloud database implementation (Terraform bootstrap, modules, environment wiring, Makefile targets, data migration, .gitignore)
- Ground Control MCP server (
mcp/ground-control/): 18 tools wrapping the REST API for native Claude Code integration — requirements CRUD, analysis, StrictDoc import, GitHub sync, and traceability link management
RequirementsE2EIntegrationTest: end-to-end integration test verifying all Phase 1 components — migration, StrictDoc import, GitHub sync, CRUD API, analysis, and Envers audit trail (6 ordered test steps)RequirementsE2EAgeIntegrationTest: optional AGE E2E test verifying graph materialization and Cypher queries match JPA analysis (@Tag("age"))- Test fixture
test-requirements.sdoc(5 requirements, 2 parent relations, 5 GitHub issue references, 2 waves)
- Phase 1 complete: all acceptance criteria verified end-to-end
GraphAlgorithmspure utility class withfindCycles()(DFS three-color) andfindReachable()(BFS) — JML contracts, no Spring dependencies (L2)AnalysisServiceread-only service: cycle detection, orphan detection, coverage gap analysis, transitive impact analysis, cross-wave validationGraphClientdomain port interface for graph traversal operations (ancestors, descendants, path finding)AgeGraphServiceinfrastructure adapter (@Component): Apache AGE graph materialization and Cypher queries, optional viagroundcontrol.age.enabledAgeConfig+AgePropertiesconfiguration for AGE integrationAnalysisControllerREST endpoints:GET /api/v1/analysis/{cycles,orphans,coverage-gaps,impact/{id},cross-wave}GraphControllerREST endpoints:POST /api/v1/admin/graph/materialize,GET /api/v1/graph/{ancestors,descendants,paths}RequirementSummaryResponseandRelationValidationResponseAPI DTOs- V010 Flyway migration: Apache AGE graph setup with graceful fallback on plain PostgreSQL
- Unit tests:
AnalysisServiceTest(14 tests),AgeGraphServiceTest(4 tests),AnalysisControllerTest(6 tests),GraphControllerTest(4 tests) - Property tests (L2):
CycleDetectionPropertyTest(4 properties),ImpactAnalysisPropertyTest(3 properties) — jqwik - Integration tests:
AnalysisIntegrationTest(4 tests) - AGE integration tests:
BaseAgeIntegrationTest,AgeGraphServiceIntegrationTest(3 tests) —@Tag("age"), separateageTestGradle task
RequirementRelationRepository: addedfindAllWithSourceAndTargetByRelationTypeIn()andfindAllWithSourceAndTarget()with JOIN FETCH for N+1 preventionTraceabilityLinkRepository: addedexistsByRequirementId()andexistsByRequirementIdAndLinkType()for analysis queriesbuild.gradle.kts: addedageTesttask, excluded@Tag("age")fromtestandintegrationTesttasksapplication.yml: addedgroundcontrol.age.*configuration propertiesMigrationSmokeTest: updated expected migration count to include V010
GitHubIssueDatadomain record for fetched GitHub issue dataGitHubClientdomain port interface for GitHub issue fetchingSyncResultrecord for sync operation results with statisticsGitHubIssueSyncServicewithsyncGitHubIssues()method: fetches issues viaGitHubClient, upsertsGitHubIssueSyncrecords with parsed labels/phase/priority/cross-references, updatesTraceabilityLinkrecords with synced metadata, saves audit recordsGitHubCliClientinfrastructure adapter (@Component): executesgh issue listCLI, parses JSON output intoGitHubIssueDatarecords (first class ininfrastructure/package)SyncControllerREST endpoint:POST /api/v1/admin/sync/github?owner=X&repo=YSyncResultResponseAPI DTO withstatic from()factory- Unit tests:
GitHubIssueSyncServiceTest(9 tests),GitHubCliClientTest(3 tests),SyncControllerTest(3 tests) - Integration tests:
SyncIntegrationTest(idempotent sync, creates issue sync records, updates traceability links)
TraceabilityLinkRepository: addedfindByArtifactType()for bulk traceability link updates during sync- SpotBugs exclusions: added
EI_EXPOSE_REP2exclusion forinfrastructurepackage
SdocParserpure Java utility for parsing StrictDoc (.sdoc) requirement files, ported from Python reference implementationSdocRequirementrecord for parsed requirement data (UID, title, statement, comment, issue refs, parent UIDs, wave)ImportResultrecord for import operation results with full statisticsImportServicewith idempotentimportStrictdoc()method: upserts requirements, creates relations, creates traceability links, saves audit recordsImportControllerREST endpoint:POST /api/v1/admin/import/strictdoc(multipart file upload)ImportResultResponseAPI DTO withstatic from()factory- Unit tests:
SdocParserTest(8 tests),ImportServiceTest(8 tests),ImportControllerTest(2 tests) - Integration tests:
ImportIntegrationTest(idempotent import, creates requirements/relations/links)
RequirementRelationRepository: addedexistsBySourceIdAndTargetIdAndRelationType()for idempotent relation creationTraceabilityLinkRepository: addedexistsByRequirementIdAndArtifactTypeAndArtifactIdentifierAndLinkType()for idempotent link creation
TraceabilityServicewithcreateLink,getLinksForRequirement,deleteLinkmethodsTraceabilityLinkRequestandTraceabilityLinkResponseAPI DTOsCreateTraceabilityLinkCommandandRequirementFilterdomain recordsRequirementSpecificationsutility for dynamic JPA Criteria filtering- REST endpoints:
POST/GET/DELETE /{id}/traceabilityfor traceability link CRUD - REST endpoint:
DELETE /{id}/relations/{relationId}for relation deletion (204) - Filtered requirement listing via
GET /api/v1/requirements?status=X&type=X&wave=N&search=text TraceabilityServiceTestunit tests (create, get, delete links)TraceabilityLinkControllerIntegrationTestintegration tests (CRUD + 404)- Unit and integration tests for filtered listing and relation deletion
RequirementRepositorynow extendsJpaSpecificationExecutor<Requirement>for dynamic filteringRequirementService.list()acceptsRequirementFilterparameter for filtered/searchable listingRequirementControlleracceptsTraceabilityServiceas second constructor dependency
TraceabilityLinkJPA entity with@Audited,@ManyToOneFK toRequirement, unique constraint on(requirement_id, artifact_type, artifact_identifier, link_type), and sync status trackingGitHubIssueSyncJPA entity with JSONB fields (issueLabels,crossReferences) for GitHub issue cachingRequirementImportJPA entity with JSONB fields (stats,errors) for import audit trailsArtifactType,LinkType,SyncStatus,IssueState,ImportSourceTypedomain enumsTraceabilityLinkRepository,GitHubIssueSyncRepository,RequirementImportRepositorySpring Data repositories- Flyway migrations V006-V009:
traceability_link,github_issue_sync,requirement_importtables andtraceability_link_auditEnvers table - Unit tests for all three new entities (defaults, construction, accessors)
- Integration tests for FK persistence, JSONB round-trip, Envers audit trail verification, and migration smoke test coverage through V009
- ADR-011 Section 5: clarified Envers auditing applies to business entities only, not cache tables or self-auditing records
- Removed JML contracts from 6 L0 CRUD methods in RequirementService per ADR-012 pre-alpha policy (L0 = working code + tests, no contracts). L1 contracts retained on transitionStatus, archive, createRelation
- Removed
VERIFIESfromRelationTypeenum — "verifies" is an artifact-to-requirement relationship belonging onTraceabilityLink.LinkType(Phase 1C, ADR-014), not a requirement-to-requirement edge - Rewrote
CONTRIBUTING.mdfor Java 21 / Spring Boot 3.4 / Gradle (was Python/Django) - Rewrote
docs/architecture/ARCHITECTURE.mdfor current stack and mission (was Python/Django) - Updated
README.mdmission statement to reflect verification orchestration + graph traceability
RequirementControllerTest:@WebMvcTestunit tests covering all 9 controller endpoints, exception handler (404/409/422/401/403/500), and DTO mappingRequestLoggingFilterTest: unit tests for MDC request_id bindingExceptionHierarchyTest: unit tests for AuthenticationException, AuthorizationException, GroundControlException cause constructor- Entity accessor coverage for Requirement and RequirementRelation (toString, getDescription, setDescription, getWave, getCreatedAt, getUpdatedAt)
- CI:
gradle-wrapper.jarwas excluded by*.jargitignore rule overriding the earlier negation — reordered rules so the negation comes after*.jarand uses**/glob to matchbackend/path - All JML annotations converted from
// @(invalid, never parsed by OpenJML) to/*@ ... @*/block comment syntax (valid JML). Added@SuppressWarnings("java:S125")to out-of-ESC-scope classes with JML contracts - Status.java: replaced
EnumMaptransition table withswitchexpression for OpenJML ESC compatibility (EnumMap specs incomplete in OpenJML). Added/*@ pure @*/on both methods,/*@ ensures \result != null @*/onvalidTargets(),/*@ requires target != null @*/oncanTransitionTo(). All contracts verified by Z3 - CODING_STANDARDS.md: updated JML section to document
/*@ @*/block syntax, inline modifiers (pure,spec_public), and SonarQube S125 suppression; updated Git & CI section to document pre-commit ESC hook - Pre-commit: added
openjml-eschook to run OpenJML ESC verification ondomain/requirements/state/files at commit time - SonarQube S1948:
DomainValidationException.detailfield changed fromMap<String, Object>toMap<String, Serializable>(exception is Serializable) - SonarQube S2187: suppressed false positive on
RequirementTest(tests are in@Nestedinner classes) - SpotBugs EI_EXPOSE_REP:
DomainValidationException.getDetail()now returns defensive copy viaMap.copyOf()
- Inner dev loop optimized:
make rapid(format + compile, ~1s warm) for edit-compile cycles - Added
-PquickGradle property to disable Error Prone, SpotBugs, and Checkstyle for fast iteration - Added
rapidGradle task (format + compile, no tests or static analysis) - Pre-commit: switched
spotlessCheck --no-daemontospotlessApply(auto-fix), upgraded test hook to full./gradlew check(CI-equivalent), dropped--no-daemonto keep daemon warm - Makefile: added
rapid,check,integration,verifytargets;build/testuse-Pquick - CLAUDE.md:
make rapidis now the primary inner loop command - CODING_STANDARDS.md: pre-alpha workflow step 4 uses
make rapid; Git & CI section documents pre-commit runs full check
- ADR-014: Pluggable Verification Architecture — separates internal dogfooding (JML/OpenJML) from platform verification capabilities (polyglot, multi-prover). Introduces VerificationResult domain entity, TLA+ for design-level verification, and verifier adapter pattern
- TLA+ adopted for design-level verification of state machines, DAG invariants, and materialization consistency
- ADR-011: Updated from Django to Java/Spring Boot implementation details (per ADR-013). Core decisions unchanged. TraceabilityLink artifact types now include TLA+ specs and verification results
- ADR-002: Updated from Django ORM/psycopg/django-tenants to Hibernate/Spring Data JPA/Flyway
- ADR-012: Reframed assurance levels as universal methodology (not JML-specific). Added TLA+ at L2. Added ADR-014 reference. Default assurance level lowered to L0 for pre-alpha — contracts only on state transitions and security boundaries, one test per behavior, no two-tests-per-contract requirement. Full L1-default SDD workflow deferred to beta
- Phase 1 design notes rewritten for Java: JPA entities, Spring services, JML contracts, EnumMap state machine, Envers auditing, command records
- CODING_STANDARDS.md: Pre-alpha workflow (implementation-first, contracts where they prevent silent corruption, one test per behavior). Coverage threshold stays at 30%. Post-alpha targets documented
- CLAUDE.md: Added pre-alpha development philosophy
- Flyway migrations V003-V005: Envers audit tables (
revinfo,requirement_audit,requirement_relation_audit) RequirementServicewith 9 methods: create, getById, getByUid, update, transitionStatus, archive, createRelation, getRelations, list. JML contracts on state-transition methods (L1: transitionStatus, archive, createRelation); retained as documentation on CRUD methods (L0)CreateRequirementCommandandUpdateRequirementCommandrecordsRequirementControllerREST controller with 9 endpoints under/api/v1/requirements- API DTOs:
RequirementRequest,RequirementResponse,StatusTransitionRequest,RelationRequest,RelationResponse MethodArgumentNotValidExceptionhandler inGlobalExceptionHandlerfor Jakarta Bean Validation errors (422)- OpenJML ESC integration:
gradle/openjml.gradle.ktswithdownloadOpenJml,openjmlEsc,openjmlRactasks — verifies state machine contracts via Z3 solver - SpotBugs static analysis with exclusions for JPA entities, test code, and constructor-throw patterns
- Error Prone compiler plugin for additional compile-time bug detection
- Checkstyle for naming conventions and coding patterns (complements Spotless formatting)
- JaCoCo coverage verification thresholds wired into
checktask - Testcontainers base class (
BaseIntegrationTest) with singleton PostgreSQL 16 container MigrationSmokeTest: verifies Flyway V001-V005 ran, audit tables exist, Hibernate validatesRequirementServiceIntegrationTest: 7 tests covering CRUD, Envers audit trail, conflict/validation errorsRequirementControllerIntegrationTest: 13 MockMvc tests covering all endpoints, error envelopes (404/409/422)RequirementServiceTest: 20 Mockito unit tests (happy-path + violation for all 9 service contracts)- ArchUnit rules: controllers must not access repositories, controllers must not import entities, services must reside in
..service..packages - OpenJML ESC Scoping section in CODING_STANDARDS.md with design guidelines for ESC-verifiable code
- CI:
integrationjob (Testcontainers, no external DB service),verifyjob (OpenJML ESC) - SonarCloud workflow updated to run both unit and integration tests for combined coverage
- Exception hierarchy moved from
domain/requirements/exception/todomain/exception/(shared across all domain areas) - CI workflow: removed standalone
architecturejob (ArchUnit runs as part ofcheck), removed external Postgres service (Testcontainers manages its own) - Testcontainers upgraded from 1.20.4 to 1.21.1 (Docker 29+ API version compatibility)
- ADR-012 "Tool Integration" section updated with actual OpenJML commands, scope limitations, and known issues
- ADR-013: Java/Spring Boot Backend Rewrite — documents pivot from Python 3.12/Django to Java 21/Spring Boot 3.4 with JML/OpenJML contracts, jqwik property testing, and KeY formal proofs
- ADR-012: Formal Methods Development Process — Specification-Driven Development (SDD) methodology with assurance levels L0-L3, updated for Java toolchain
- Java 21 / Spring Boot 3.4 / Gradle (Kotlin DSL) project scaffold in
backend/ RequirementandRequirementRelationJPA entities with JML contract annotations and Hibernate Envers auditingStatusenum with hand-rolledEnumMaptransition table (DRAFT -> ACTIVE -> DEPRECATED -> ARCHIVED)RequirementType,Priority,RelationTypedomain enums- Exception hierarchy:
GroundControlExceptionbase withNotFoundException,DomainValidationException,AuthenticationException,AuthorizationException,ConflictException GlobalExceptionHandler(@RestControllerAdvice) mapping exceptions to{"error": {...}}JSON envelopeRequestLoggingFilterfor MDCrequest_idbinding- Spring Data JPA repositories for
RequirementandRequirementRelation - Flyway migrations V001 (requirement table) and V002 (requirement_relation table)
logback-spring.xmlwith console (dev) and JSON/Logstash (prod) output- 22 tests: JUnit 5 unit tests (13), jqwik property tests (3), ArchUnit architecture rules (4), structural transition table tests (5), smoke test (1)
- ArchUnit rules enforcing
api/ -> domain/ <- infrastructure/dependency rule - Spotless + Palantir Java Format for code formatting
- JaCoCo for test coverage reporting
- Springdoc-OpenAPI for API documentation generation
- Backend rewritten from Python 3.12/Django to Java 21/Spring Boot 3.4 with Gradle (Kotlin DSL)
- ADR-001 (Django backend), ADR-003 (icontract), ADR-004 (Python toolchain) marked as superseded by ADR-013
- ADR-012 tool references updated: icontract → JML, CrossHair → OpenJML ESC, Hypothesis → jqwik, Rocq/Coq → KeY
- CI workflow rewritten for Gradle (build, test, architecture jobs)
- Makefile updated for Gradle commands
- Dockerfile rewritten as multi-stage JDK 21 build
- CODING_STANDARDS.md rewritten for Java conventions
- CLAUDE.md updated with Java build commands
- Python backend code (pyproject.toml, Django settings, manage.py, all Python source)
- ADR-011: Requirements data model — documents UUID PKs, DAG relations, AGE-as-query-layer strategy, service-layer write ownership, no new library dependencies
- Phase 1 design notes (
architecture/notes/phase1-requirements-design.md) with data model, app structure, service layer architecture, and key patterns - Design documentation index (
architecture/design/README.md)
backend/Dockerfilemulti-stage build with non-root user (closes #161)backend/.dockerignoreexcluding tests, dev files, .venvmake docker-buildtarget for local image builds- GitHub Actions
docker.ymlworkflow for GHCR publishing on push to main/tags gunicornproduction dependencySTATIC_ROOTsetting for collectstatic support
BaseSchemabase class for all project schemas (closes #164)GroundControlPaginationwithPageMetafor consistent paginated responses- Nested error response format:
{"error": {"code": ..., "message": ..., "detail": ...}} - Schemas & Response Format section in CODING_STANDARDS.md
- Error responses now use nested
{"error": {...}}format (breaking API change, no consumers) - Replaced
ErrorResponseschema withErrorDetail+ErrorEnvelope
- Shared exception hierarchy in
ground_control.exceptions(closes #163) GroundControlErrorbase withNotFoundError,DomainValidationError,AuthenticationError,AuthorizationError,ConflictError- django-ninja exception handler mapping domain exceptions to HTTP status codes
ErrorResponsePydantic schema for structured API error responses
- Moved
NinjaAPIinstance fromurls.pytoground_control.apifor cleaner separation
- Structured logging with structlog and django-structlog (closes #162)
- JSON log output in production, colored console in development (based on DEBUG)
- Automatic request context binding (request_id, ip, user_id) via django-structlog middleware
- Service identity fields (service.name, service.version) in all log entries
- Standard library logging routed through structlog for unified output
- Custom
RequestIdMiddleware(replaced by django-structlog'sRequestMiddleware)
- CI pipeline (
.github/workflows/ci.yml): lint, typecheck, and test jobs run in parallel on push/PR tomain/dev
- Mypy override for
settings.base—# type: ignore[misc]needed for pre-commit per-file check but flagged as unused in full-project check
- Docker Compose dev environment with PostgreSQL 16 (Apache AGE 1.6.0) and Redis 7
.env.exampledocumenting allGC_environment variables- Makefile
upanddowntargets for managing Docker Compose services - ADR-005: Apache AGE for graph database capabilities (chose over Neo4j for operational simplicity)
- Parse
GC_DATABASE_URLdynamically into DjangoDATABASESsetting (was hardcoded) - Rewrite all operational docs to reflect actual codebase state (remove aspirational content)
- Rewrite DEPLOYMENT.md as dev environment setup guide
- Rewrite ARCHITECTURE.md to document current stack and project structure
- Trim CODING_STANDARDS.md to enforceable rules only
- Rewrite README.md: accurate structure, status section, links to correct paths
- Update CONTRIBUTING.md with local dev setup instructions
- Fresh ADR framework with template (
architecture/adrs/000-template.md) and clean index - ADR-001: Python 3.12+ with Django and django-ninja for Backend
- ADR-002: PostgreSQL as Primary Database
- ADR-003: Design by Contract with icontract
- ADR-004: Code Quality Toolchain
- Restored
docs/CODING_STANDARDS.mdfrom archive - 7 new phase-0 bootstrap issues (#158–#164) for getting Django deployment-ready
- Project pivot: Ground Control reframed from ITRM platform to neurosymbolic constraint infrastructure, dogfooded on itself
- Archived pre-pivot work into
archive/(docs, tools, architecture ADRs) - ADR numbering reset — old ADRs (001–010) archived, new series starts at 001
- Django settings: removed references to
django_tenantsandoauth2_provider(not in dependencies, causedModuleNotFoundErroron startup) - Django settings: switched database engine from
django_tenants.postgresql_backendtodjango.db.backends.postgresql manage.py checknow passes
- All 131 GitHub issues from old roadmap (historical record preserved in
archive/tools/issue-graph/.issue_cache.json) docs/moved toarchive/docs/(personas, glossary, requirements, roadmap, coding standards, user stories, API/deployment docs)tools/moved toarchive/tools/(issue-graph, strictdoc)architecture/moved toarchive/architecture/(ADRs, C4 diagrams, policies)django_tenantsconfig from settings (SHARED_APPS/TENANT_APPS pattern, TenantMainMiddleware, TenantSyncRouter, TENANT_MODEL/TENANT_DOMAIN_MODEL)oauth2_providerfrom INSTALLED_APPS
tools/issue-graph/— standalone NetworkX-based GitHub issue dependency graph analyzer- Own pyproject.toml, venv, and Makefile (
make setup && make run) - Fetches issues via
ghCLI, builds directed dependency graph - Validates for cycles, cross-phase backward deps, orphans, stale tech references
- Computes critical path and top blocking issues
--sdoc-gaps: checks sdoc ↔ GitHub issue traceability (both directions)--cross-check: validates sdoc Parent relations against issue dependencies, detects self-referencing parents, backward wave deps- Exports graph as JSON for further analysis
- Own pyproject.toml, venv, and Makefile (
docs/roadmap/RATIONALIZATION.md— issue rationalization plan- Reorganizes 124 open issues from 12 phases into 10 waves with validated dependency ordering
- Identifies 8 issues to close, 26 to defer, 36 to rewrite for Django
- Wave ordering validated against dependency graph (no backward deps)
tools/strictdoc/— StrictDoc requirements management setup- Own venv and Makefile (
make setup && make server) - Web UI for browsing and editing requirements
- Own venv and Makefile (
docs/requirements/project.sdoc— product requirements (replaces PRD.md)- 80 requirements organized into 10 waves with parent-child traceability
- All 131 open GitHub issues mapped to requirements via COMMENT field
- Validated by StrictDoc (no broken links, no cycles)
- sdoc ↔ issue dependency graph fully synced (125 edges)
docs/personas/— one file per persona (7 personas extracted from PRD)docs/glossary.md— terminology reference- 7 new GitHub issues created for PRD requirements that had no issue (#151-#157)
- Makefile: Replace uvicorn command with
manage.py runserver(last FastAPI remnant) - Rewrite issue #33 for django-ninja context (was FastAPI Pydantic/DI)
- Rewrite issue #39 to use Django permissions/groups (was premature ABAC/OPA)
- Issue #44: rewritten for Django ORM, added control effectiveness acceptance criteria
- Issue #49: rewritten for Django ORM + django-storages, added 500MB artifact size limit
- Issue #133: added encryption-at-rest (AES-256), TLS 1.3, and HA acceptance criteria
- 81 issues updated with
## Dependenciessection synced from sdoc Parent relations
docs/PRD.md— superseded bydocs/requirements/project.sdocdjango-tenantsfrom production deps — premature for on-prem single-tenant v0.1django-oauth-toolkitfrom production deps — OAuth2 is v0.4 scope, Django auth sufficient for v0.1dealfrom dev deps — redundant with icontractrespxfrom dev deps — HTTPX mock library not needed with Django test clientpytest-asynciofrom dev deps — Django tests are sync-firstasyncio_mode = "auto"from pytest config- Closed issues #55 (FastAPI scaffold), #34 (SQLAlchemy engine), #35 (Alembic migrations) as not_planned
- Switch backend framework from FastAPI to Django + django-ninja (ADR-010 supersedes ADR-001)
- Replace SQLAlchemy + Alembic with Django ORM and built-in migrations
- Replace manual auth stack (python-jose, passlib) with Django auth + django-oauth-toolkit
- Update
backend/pyproject.tomldependencies for Django ecosystem - Update CODING_STANDARDS.md, ARCHITECTURE.md, CONTRIBUTING.md for Django references
- ADR-010: Evaluate Django framework — documents rationale for switching
- Django project structure: settings (base, test), urls.py, asgi.py, wsgi.py, manage.py
- django-tenants for multi-tenancy, django-auditlog for audit trail, django-storages for S3
- django-q2 for background task processing
- pytest-django and django-stubs in dev dependencies
backend/tests/unit/test_package.pypackage importability and version test- CI: Python 3.12 setup, uv install, and pytest coverage in SonarCloud workflow
- SonarCloud quality gate failure: configured
sonar.sources,sonar.tests, and coverage report path - SonarCloud now receives coverage XML from pytest-cov
backend/pyproject.tomlwith full dependency declarations (FastAPI, SQLAlchemy, Pydantic, structlog, etc.) and optional dependency groups (dev, test, docs)backend/src/ground_control/__init__.pywith__version__backend/src/ground_control/py.typedPEP 561 marker for typed packagebackend/tests/conftest.pyshared test fixtures stub- Root
Makefilewith common commands (install, lint, format, test, dev, clean) uvsupport withpipfallback in Makefile
backend/pyproject.tomlwith ruff (line length 100, Python 3.12, security/typing/style rules) and mypy strict configCONTRIBUTING.mddocumenting coding standards, architecture rules, branch strategy, and testing conventions- ADR-009: Coding Standards and Tooling
- Line length updated from 99 to 100 in CODING_STANDARDS.md, .editorconfig, and CLAUDE.md
- ADR framework with MADR template (
architecture/adrs/000-template.md) - ADR index (
architecture/adrs/README.md) - Initial ADRs for foundational decisions:
- ADR-001: Python 3.12+ with FastAPI for backend
- ADR-002: PostgreSQL 16+ as primary database
- ADR-003: API-first design (REST)
- ADR-004: Plugin architecture for extensibility
- ADR-005: Event-driven architecture with domain events
- ADR-006: Multi-tenancy strategy (shared schema default)
- ADR-007: Agent-first design (AI agents as first-class actors)
- ADR-008: Clean architecture (API / Domain / Infrastructure layers)
- Monorepo directory structure: backend, frontend, sdks, plugins, deploy, architecture
CLAUDE.mdwith AI-assisted development conventions.editorconfigfor consistent whitespace across Python, TypeScript, YAML, Markdown- GitHub issue templates (bug report, feature request)
- GitHub pull request template with coding standards checklist
- Placeholder
__init__.pyand.gitkeepfiles for all directories - Repository structure overview in README.md
- Node.js / frontend entries in
.gitignore
- Complete ITRM platform design documentation:
- Product Requirements Document (PRD)
- System Architecture (Clean Architecture, shared-schema multi-tenancy)
- Data Model (entity-relationship model, typed foreign keys, audit log)
- API Specification (REST, flat JSON responses, PATCH via RFC 7396)
- Deployment Guide (Docker Compose, Kubernetes Helm, SSO)
- User Stories with MVP markers and Use Cases (UML)
- Coding Standards document with cross-cutting concerns (exceptions, logging, audit, schemas, tenant context)
- Formal methods infrastructure (Coq/Rocq proof targets for audit log, RBAC, state machines, tenant isolation)
- 129 implementation issues across 12 phases (phase-0 through phase-11)
- Issue creation script (
scripts/create-github-issues.sh) with label management and rate limiting - Pre-commit hooks (ruff, mypy, gitleaks, pytest)
- SonarCloud integration (GitHub Actions workflow, sonar-project.properties)
- MCP development tooling issue (rocq-mcp, AWS MCP)
- License changed from Apache-2.0 to MIT
- Initial repository structure
- GitHub Actions workflows for quality and security checks
- Pre-commit configuration
- Project documentation (README, LICENSE)