Skip to content

Commit 290e36b

Browse files
brovattenclaudecodeboarding[bot]
authored
feat: add sync mode — commit a versioned architecture baseline on push (#28)
* feat: accept docs-only baseline drift when validating the committed baseline A docs bot committing generated .codeboarding/ and docs/development/ files to main moves the branch head past the commit the baseline analysis.json was generated for. validate-base now accepts a baseline whose commit_hash is an ancestor of the PR base when the intervening diff touches only generated-docs paths, instead of discarding it and forcing a full base regeneration. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: docs mode — generate architecture docs and commit them to a branch One action, two modes. The new 'mode' input (default 'review', unchanged behavior) adds 'docs': on push/workflow_dispatch/schedule the action analyzes the pushed commit, renders .codeboarding/*.md (+ optional docs/development/architecture.md), and commits the results to target_branch as codeboarding[bot] — absorbing the standalone docs-action so the baseline writer and its reader (review mode) ship at one version. - guard: mode dispatch; docs is explicit opt-in, never event-inferred; tag pushes and pull_request events soft-skip in docs mode; docs inputs validated; baseline_sha from committed JSON must look like a SHA before it reaches GITHUB_OUTPUT/cache keys/git - cb_engine.py: analyze/render/concat subcommands (ported from docs-action's docs_engine.py); CODEBOARDING_SOURCE telemetry is docs_action for them; validate-base gains --expected-depth - depth gates reject only a baseline DEEPER than requested: the engine records the depth reached, not requested, so a strict != would loop full analyses forever on repos that never expand - docs push authenticates the rebase-retry fetch through the same URL as the push (the shared checkout is credential-free; a bare fetch would hard-fail private repos instead of failing open) - engine_ref default v0.12.0 -> v0.12.1 (single pin for both modes) - new inputs: mode, output_dir, output_format, target_branch, write_architecture_md, commit_message; new outputs: analysis_mode, files_written, committed - docs.yml dogfoods docs mode on this repo; shares a concurrency group with refresh-baseline.yml (both commit the baseline to main); README documents the two-thin-workflows consumption pattern and its permission trade-offs - tests: 86 (26 new) covering the ported subcommands, the depth semantics on both validate-base acceptance paths, and the analysis_mode= stdout marker the action greps Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: default depth_level to 2 for both modes Bump the shared depth_level default from 1 to 2. Docs are the artifact people read, so favor analysis quality over cost by default; review mode follows the same value to keep the committed baseline it reuses at a matching depth. Consumers who want cheaper, faster runs set depth_level: 1. The deeper-only baseline gate means existing depth-1 committed baselines still validate under the depth-2 default (no full-regen loop); the cost is that unset @v1 review consumers now analyze one level deeper per run. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor: rename docs mode to sync mode The second mode is a sync engine, not a doc generator: it keeps the committed architecture analysis (analysis.json + rendered markdown) versioned and current on the branch, so the architecture has real git history and review mode diffs against a fresh baseline. 'docs' sold the byproduct (the markdown) and hid the point (the versioned data), so rename the mode identity to 'sync'. - public API: mode: docs -> mode: sync; outputs/inputs unchanged in name - internal: docs_* step ids -> sync_*, cb-docs cache prefix -> cb-sync, CODEBOARDING_SOURCE telemetry docs_action -> sync, commit_message default -> 'chore(codeboarding): sync architecture baseline [skip ci]' - files: docs.yml -> codeboarding-sync.yml (dogfood + README-recommended name), test_docs_subcommands.py -> test_sync_subcommands.py - README reframed around versioning/sync; section + anchor renamed - genuine markdown references kept (docs/development/architecture.md, write_architecture_md, --docs-dir, 'Render docs') Unreleased mode, so renaming the mode value breaks no existing consumer. 86 tests pass; actionlint and black clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore: add .codeboardingignore to scope analysis Curated gitignore-style patterns (venv/build output, test/mock/fixture dirs, generated code, minified bundles) that CodeBoarding analysis loads to exclude non-production paths — keeps the architecture analysis focused on real code. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor: act on the structure/naming review Addresses the high-level review's findings — internal legibility, not behavior (review mode output is unchanged): - rename scripts/cb_engine.py -> scripts/engine_adapter.py (+ test file): it is a thin CLI adapter over the separate CodeBoarding engine, not the engine; the old name implied analysis logic lived here. Docstring now says so up front. - dedupe the incremental-or-full path: review 'head' and sync 'analyze' shared ~90% logic (try incremental, fall back to full on the same two exceptions); both now call one _incremental_or_full helper, so a fallback fix lands once. - move baseline parsing into the adapter: new 'baseline-info' subcommand emits commit_hash= only when present and SHA-shaped, replacing the sync_seed step's inline python heredoc + grep with one tested code path. - add a 'force_full' input (sync mode) that rebuilds the baseline from scratch, and RETIRE refresh-baseline.yml: it was a 198-line hand-rolled copy of the action's own pipeline. Its 'fresh full rebuild' is now codeboarding-sync.yml's workflow_dispatch + force_full, running the tested action instead of a clone. - structure legibility: a top-of-file phase map (guard / shared setup / analysis-with-key / drop-key + output) naming the shared analysis.json baseline as the binding between the two modes; review-only inputs now carry a 'Review mode:' prefix so the Marketplace-rendered view matches the README. - refresh AGENT.md (was review-only) to describe both modes; document force_full. 93 tests pass (both module orders); actionlint, shellcheck, black clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore(codeboarding): update architecture analysis [skip ci] --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: codeboarding[bot] <codeboarding[bot]@users.noreply.github.com>
1 parent 57c0aee commit 290e36b

14 files changed

Lines changed: 2168 additions & 626 deletions

.codeboarding/.codeboardingignore

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# CodeBoarding Ignore File
2+
# Add patterns here for files and directories that should be excluded from CodeBoarding analysis.
3+
# Use the same format as .gitignore (gitignore syntax / gitwildmatch patterns).
4+
#
5+
# To stop ignoring a pattern, prefix it with ! (e.g., !important_file.txt)
6+
#
7+
# NOTE: The following are ALWAYS excluded (not configurable):
8+
# - Hidden directories (starting with .)
9+
# - .git/, .codeboarding/, node_modules/, __pycache__/
10+
# - Build output: build/, dist/, coverage/
11+
#
12+
# This file is automatically loaded by CodeBoarding analysis tools to exclude
13+
# specified paths from code analysis, architecture generation, and other processing.
14+
15+
# ============================================================================
16+
# Ignored directories (customizable — remove lines to include them)
17+
# ============================================================================
18+
19+
# Python virtual environments
20+
venv/
21+
env/
22+
*.egg-info/
23+
24+
# Java (Maven/Gradle) and Rust (Cargo) build output. Both ecosystems
25+
# produce a top-level ``target/`` directory full of compiled artifacts —
26+
# kept here as well as in ``_ALWAYS_IGNORED_DIRS`` so users who customize
27+
# their ``.codeboardingignore`` continue to skip it even after edits.
28+
target/
29+
bin/
30+
out/
31+
32+
# .NET / C# build output
33+
obj/
34+
35+
# Go
36+
vendor/
37+
testdata/
38+
39+
# PHP
40+
cache/
41+
42+
# Custom
43+
temp/
44+
repos/
45+
runs/
46+
47+
# ============================================================================
48+
# Test and infrastructure files
49+
# ============================================================================
50+
51+
# Test directories
52+
**/__tests__/**
53+
**/tests/**
54+
**/test/**
55+
**/__test__/**
56+
**/testing/**
57+
**/testutil/**
58+
59+
# Java/Kotlin test directories (Maven/Gradle structure)
60+
**/src/test/**
61+
**/src/testFixtures/**
62+
**/src/integration-test/**
63+
**/src/jmh/**
64+
**/src/contractTest/**
65+
**/osgi-tests/**
66+
67+
# Test files by naming convention
68+
*.test.*
69+
*.spec.*
70+
*_test.*
71+
*test_*.py
72+
test_*.py
73+
*Test.java
74+
*IT.java
75+
*Test.kt
76+
*IT.kt
77+
*Tests.java
78+
79+
# Mock, fixture, and stub directories
80+
**/__mocks__/**
81+
**/mocks/**
82+
**/fixtures/**
83+
**/fixture/**
84+
**/stubs/**
85+
**/stub/**
86+
**/fakes/**
87+
**/fake/**
88+
89+
# E2E and integration test directories
90+
**/e2e/**
91+
**/integration-tests/**
92+
**/integration_test*/**
93+
94+
# ============================================================================
95+
# Non-production code
96+
# ============================================================================
97+
98+
# Example and documentation code
99+
**/examples/**
100+
**/documentation/examples/**
101+
102+
# Generated code
103+
*.pb.go
104+
**/generated_parser*
105+
106+
# Java/Kotlin metadata files
107+
module-info.java
108+
109+
# ============================================================================
110+
# Build artifacts and minified files
111+
# ============================================================================
112+
113+
*.bundle.js
114+
*.bundle.js.map
115+
*.min.js
116+
*.min.css
117+
*.chunk.js
118+
*.chunk.js.map
119+
120+
# ============================================================================
121+
# Build tool configs and infrastructure
122+
# ============================================================================
123+
124+
esbuild*
125+
webpack*
126+
rollup*
127+
vite.config.*
128+
gulpfile*
129+
gruntfile*
130+
*.config.*

.codeboarding/analysis.json

Lines changed: 60 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,18 @@
1616
},
1717
"description": "The CodeBoarding-action project implements a pipeline that orchestrates static analysis of code branches, performs structural diffing to generate visual Mermaid.js diagrams, and integrates these insights into GitHub Pull Requests via interactive deep links and editor-specific metadata.",
1818
"files": {
19-
"scripts/cb_engine.py": {
19+
"scripts/engine_adapter.py": {
2020
"method_keys": [
21-
"scripts/cb_engine.py|scripts.cb_engine._log_path",
22-
"scripts/cb_engine.py|scripts.cb_engine._clear_dir",
23-
"scripts/cb_engine.py|scripts.cb_engine.validate_base_analysis",
24-
"scripts/cb_engine.py|scripts.cb_engine.run_base",
25-
"scripts/cb_engine.py|scripts.cb_engine.run_seed",
26-
"scripts/cb_engine.py|scripts.cb_engine.run_head",
27-
"scripts/cb_engine.py|scripts.cb_engine._count_report_issues",
28-
"scripts/cb_engine.py|scripts.cb_engine._count_health_report",
29-
"scripts/cb_engine.py|scripts.cb_engine.run_health",
30-
"scripts/cb_engine.py|scripts.cb_engine.main"
21+
"scripts/engine_adapter.py|scripts.engine_adapter._log_path",
22+
"scripts/engine_adapter.py|scripts.engine_adapter._clear_dir",
23+
"scripts/engine_adapter.py|scripts.engine_adapter.validate_base_analysis",
24+
"scripts/engine_adapter.py|scripts.engine_adapter.run_base",
25+
"scripts/engine_adapter.py|scripts.engine_adapter.run_seed",
26+
"scripts/engine_adapter.py|scripts.engine_adapter.run_head",
27+
"scripts/engine_adapter.py|scripts.engine_adapter._count_report_issues",
28+
"scripts/engine_adapter.py|scripts.engine_adapter._count_health_report",
29+
"scripts/engine_adapter.py|scripts.engine_adapter.run_health",
30+
"scripts/engine_adapter.py|scripts.engine_adapter.main"
3131
]
3232
},
3333
"scripts/build_component_files.py": {
@@ -84,72 +84,72 @@
8484
}
8585
},
8686
"methods_index": {
87-
"scripts/cb_engine.py|scripts.cb_engine._log_path": {
88-
"file_path": "scripts/cb_engine.py",
89-
"qualified_name": "scripts.cb_engine._log_path",
87+
"scripts/engine_adapter.py|scripts.engine_adapter._log_path": {
88+
"file_path": "scripts/engine_adapter.py",
89+
"qualified_name": "scripts.engine_adapter._log_path",
9090
"start_line": 32,
9191
"end_line": 33,
9292
"type": "FUNCTION"
9393
},
94-
"scripts/cb_engine.py|scripts.cb_engine._clear_dir": {
95-
"file_path": "scripts/cb_engine.py",
96-
"qualified_name": "scripts.cb_engine._clear_dir",
94+
"scripts/engine_adapter.py|scripts.engine_adapter._clear_dir": {
95+
"file_path": "scripts/engine_adapter.py",
96+
"qualified_name": "scripts.engine_adapter._clear_dir",
9797
"start_line": 36,
9898
"end_line": 42,
9999
"type": "FUNCTION"
100100
},
101-
"scripts/cb_engine.py|scripts.cb_engine.validate_base_analysis": {
102-
"file_path": "scripts/cb_engine.py",
103-
"qualified_name": "scripts.cb_engine.validate_base_analysis",
101+
"scripts/engine_adapter.py|scripts.engine_adapter.validate_base_analysis": {
102+
"file_path": "scripts/engine_adapter.py",
103+
"qualified_name": "scripts.engine_adapter.validate_base_analysis",
104104
"start_line": 45,
105105
"end_line": 76,
106106
"type": "FUNCTION"
107107
},
108-
"scripts/cb_engine.py|scripts.cb_engine.run_base": {
109-
"file_path": "scripts/cb_engine.py",
110-
"qualified_name": "scripts.cb_engine.run_base",
108+
"scripts/engine_adapter.py|scripts.engine_adapter.run_base": {
109+
"file_path": "scripts/engine_adapter.py",
110+
"qualified_name": "scripts.engine_adapter.run_base",
111111
"start_line": 79,
112112
"end_line": 91,
113113
"type": "FUNCTION"
114114
},
115-
"scripts/cb_engine.py|scripts.cb_engine.run_seed": {
116-
"file_path": "scripts/cb_engine.py",
117-
"qualified_name": "scripts.cb_engine.run_seed",
115+
"scripts/engine_adapter.py|scripts.engine_adapter.run_seed": {
116+
"file_path": "scripts/engine_adapter.py",
117+
"qualified_name": "scripts.engine_adapter.run_seed",
118118
"start_line": 94,
119119
"end_line": 121,
120120
"type": "FUNCTION"
121121
},
122-
"scripts/cb_engine.py|scripts.cb_engine.run_head": {
123-
"file_path": "scripts/cb_engine.py",
124-
"qualified_name": "scripts.cb_engine.run_head",
122+
"scripts/engine_adapter.py|scripts.engine_adapter.run_head": {
123+
"file_path": "scripts/engine_adapter.py",
124+
"qualified_name": "scripts.engine_adapter.run_head",
125125
"start_line": 124,
126126
"end_line": 153,
127127
"type": "FUNCTION"
128128
},
129-
"scripts/cb_engine.py|scripts.cb_engine._count_report_issues": {
130-
"file_path": "scripts/cb_engine.py",
131-
"qualified_name": "scripts.cb_engine._count_report_issues",
129+
"scripts/engine_adapter.py|scripts.engine_adapter._count_report_issues": {
130+
"file_path": "scripts/engine_adapter.py",
131+
"qualified_name": "scripts.engine_adapter._count_report_issues",
132132
"start_line": 156,
133133
"end_line": 169,
134134
"type": "FUNCTION"
135135
},
136-
"scripts/cb_engine.py|scripts.cb_engine._count_health_report": {
137-
"file_path": "scripts/cb_engine.py",
138-
"qualified_name": "scripts.cb_engine._count_health_report",
136+
"scripts/engine_adapter.py|scripts.engine_adapter._count_health_report": {
137+
"file_path": "scripts/engine_adapter.py",
138+
"qualified_name": "scripts.engine_adapter._count_health_report",
139139
"start_line": 172,
140140
"end_line": 180,
141141
"type": "FUNCTION"
142142
},
143-
"scripts/cb_engine.py|scripts.cb_engine.run_health": {
144-
"file_path": "scripts/cb_engine.py",
145-
"qualified_name": "scripts.cb_engine.run_health",
143+
"scripts/engine_adapter.py|scripts.engine_adapter.run_health": {
144+
"file_path": "scripts/engine_adapter.py",
145+
"qualified_name": "scripts.engine_adapter.run_health",
146146
"start_line": 183,
147147
"end_line": 212,
148148
"type": "FUNCTION"
149149
},
150-
"scripts/cb_engine.py|scripts.cb_engine.main": {
151-
"file_path": "scripts/cb_engine.py",
152-
"qualified_name": "scripts.cb_engine.main",
150+
"scripts/engine_adapter.py|scripts.engine_adapter.main": {
151+
"file_path": "scripts/engine_adapter.py",
152+
"qualified_name": "scripts.engine_adapter.main",
153153
"start_line": 215,
154154
"end_line": 257,
155155
"type": "FUNCTION"
@@ -441,26 +441,26 @@
441441
"description": "The central controller that manages the GitHub Action lifecycle, coordinating environment setup and triggering static analysis for base and head branches.",
442442
"key_entities": [
443443
{
444-
"qualified_name": "scripts.cb_engine.main",
445-
"reference_file": "scripts/cb_engine.py",
444+
"qualified_name": "scripts.engine_adapter.main",
445+
"reference_file": "scripts/engine_adapter.py",
446446
"reference_start_line": 215,
447447
"reference_end_line": 257
448448
},
449449
{
450-
"qualified_name": "scripts.cb_engine.run_base",
451-
"reference_file": "scripts/cb_engine.py",
450+
"qualified_name": "scripts.engine_adapter.run_base",
451+
"reference_file": "scripts/engine_adapter.py",
452452
"reference_start_line": 79,
453453
"reference_end_line": 91
454454
},
455455
{
456-
"qualified_name": "scripts.cb_engine.run_head",
457-
"reference_file": "scripts/cb_engine.py",
456+
"qualified_name": "scripts.engine_adapter.run_head",
457+
"reference_file": "scripts/engine_adapter.py",
458458
"reference_start_line": 124,
459459
"reference_end_line": 153
460460
},
461461
{
462-
"qualified_name": "scripts.cb_engine.run_health",
463-
"reference_file": "scripts/cb_engine.py",
462+
"qualified_name": "scripts.engine_adapter.run_health",
463+
"reference_file": "scripts/engine_adapter.py",
464464
"reference_start_line": 183,
465465
"reference_end_line": 212
466466
}
@@ -470,18 +470,18 @@
470470
],
471471
"file_methods": [
472472
{
473-
"file_path": "scripts/cb_engine.py",
473+
"file_path": "scripts/engine_adapter.py",
474474
"methods": [
475-
"scripts.cb_engine._log_path",
476-
"scripts.cb_engine._clear_dir",
477-
"scripts.cb_engine.validate_base_analysis",
478-
"scripts.cb_engine.run_base",
479-
"scripts.cb_engine.run_seed",
480-
"scripts.cb_engine.run_head",
481-
"scripts.cb_engine._count_report_issues",
482-
"scripts.cb_engine._count_health_report",
483-
"scripts.cb_engine.run_health",
484-
"scripts.cb_engine.main"
475+
"scripts.engine_adapter._log_path",
476+
"scripts.engine_adapter._clear_dir",
477+
"scripts.engine_adapter.validate_base_analysis",
478+
"scripts.engine_adapter.run_base",
479+
"scripts.engine_adapter.run_seed",
480+
"scripts.engine_adapter.run_head",
481+
"scripts.engine_adapter._count_report_issues",
482+
"scripts.engine_adapter._count_health_report",
483+
"scripts.engine_adapter.run_health",
484+
"scripts.engine_adapter.main"
485485
]
486486
}
487487
],

.codeboarding/health/health_report.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
"entities": [
6060
{
6161
"entity_name": "[unreachable_code] Type analysis indicates code is unreachable",
62-
"file_path": "scripts/cb_engine.py",
62+
"file_path": "scripts/engine_adapter.py",
6363
"line_start": 159,
6464
"line_end": 159,
6565
"metric_value": 0.0
@@ -71,7 +71,7 @@
7171
],
7272
"file_summaries": [
7373
{
74-
"file_path": "scripts/cb_engine.py",
74+
"file_path": "scripts/engine_adapter.py",
7575
"total_findings": 1,
7676
"warning_findings": 0,
7777
"composite_risk_score": 10.0

0 commit comments

Comments
 (0)