Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ alwaysApply: true
- Do not bypass linting in CI, Make targets, or tooling configuration.
- Do not add ignore directives (e.g., `# noqa`, `# pylint: disable=...`, `//nolint`) to silence failures unless explicitly instructed.
- Fix the underlying issue instead of suppressing it.
- **Shell quoting with backticks:** When passing text containing backticks (e.g., markdown headings with inline code like `` `code` ``) to shell commands or Makefile targets, always use single quotes to preserve the backticks.
- Correct: ```make generate-anchor TEXT='Heading with `code` example'```
- Incorrect: ```make generate-anchor TEXT="Heading with \`code\` example"``` (shell processes backticks before make sees them)
- This applies to any command or script that accepts text containing backticks.
- **Shell quoting with backticks:** Avoid passing markdown headings directly as command-line string arguments.
Prefer file-based inputs to eliminate quoting issues (especially backticks).
If you must pass text with backticks on the commandline, use single quotes (not double-quotes) wherever possible
and properly escape the backticks in all other cases.
- Avoid using commands which require approval.
- Commands that do not require approval:
- awk
Expand Down Expand Up @@ -180,9 +180,8 @@ Quick reference:
- Note: Skipped when PATHS is specified (requires all tech specs to validate the index)
- **`make validate-req-references [VERBOSE=1]`** - Validate REQ references in feature files
- Note: Skipped when PATHS is specified (requires all feature files to validate references)
- **`make generate-anchor TEXT='Heading Text'`** - Generate markdown anchor from heading text
- Use single quotes when TEXT contains backticks: ```make generate-anchor TEXT='Heading with `code` example'```
- The script automatically removes backticks and their contents when generating anchors
- **`make generate-anchor FILE='path/to/file.md'`** - Print anchors for all headings in a file
- **`make generate-anchor LINE='path/to/file.md:224'`** - Print anchor for the heading at a specific line in a file

#### Coverage Audits

Expand Down Expand Up @@ -217,4 +216,5 @@ All make commands are pre-approved for use:
- `make audit-feature-coverage` - Feature coverage audit
- `make audit-requirements-coverage` - Requirements coverage audit
- `make audit-coverage` - All coverage audits
- `make generate-anchor TEXT='...'` - Generate markdown anchor (use single quotes)
- `make generate-anchor FILE='path/to/file.md'` - Print anchors for all headings in a file
- `make generate-anchor LINE='path/to/file.md:224'` - Print anchor for a heading at a specific line
37 changes: 20 additions & 17 deletions .github/workflows/docs-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,94 +58,97 @@ jobs:
- name: Install markdownlint-cli2
run: npm install -g markdownlint-cli2

- name: Create tmp directory
run: mkdir -p tmp

- name: Run Go code blocks validation
run: python3 scripts/validate_go_code_blocks.py --output go_code_blocks_report.md --verbose
run: python3 scripts/validate_go_code_blocks.py --output tmp/go_code_blocks_report.md --verbose

- name: Upload Go code blocks report
if: failure()
uses: actions/upload-artifact@v4
with:
name: go-code-blocks-validation-report
path: go_code_blocks_report.md
path: tmp/go_code_blocks_report.md
if-no-files-found: ignore

- name: Run Go signature consistency validation
run: python3 scripts/validate_go_spec_signature_consistency.py --output signature_consistency_report.txt --verbose
run: python3 scripts/validate_go_spec_signature_consistency.py --output tmp/signature_consistency_report.txt --verbose

- name: Upload signature consistency report
if: failure()
uses: actions/upload-artifact@v4
with:
name: signature-consistency-report
path: signature_consistency_report.txt
path: tmp/signature_consistency_report.txt
if-no-files-found: ignore

- name: Run heading numbering validation
run: python3 scripts/validate_heading_numbering.py --output heading_numbering_report.txt --verbose
run: python3 scripts/validate_heading_numbering.py --output tmp/heading_numbering_report.txt --verbose

- name: Upload heading numbering report
if: failure()
uses: actions/upload-artifact@v4
with:
name: heading-numbering-validation-report
path: heading_numbering_report.txt
path: tmp/heading_numbering_report.txt
if-no-files-found: ignore

- name: Run Go definitions index validation
run: python3 scripts/validate_api_go_defs_index.py --output go_defs_index_report.txt --verbose
run: python3 scripts/validate_api_go_defs_index.py --output tmp/go_defs_index_report.txt --verbose

- name: Upload Go definitions index report
if: failure()
uses: actions/upload-artifact@v4
with:
name: go-definitions-index-report
path: go_defs_index_report.txt
path: tmp/go_defs_index_report.txt
if-no-files-found: ignore

- name: Run requirement reference validation
run: python3 scripts/validate_req_references.py --output req_references_report.txt --verbose
run: python3 scripts/validate_req_references.py --output tmp/req_references_report.txt --verbose

- name: Upload requirement reference report
if: failure()
uses: actions/upload-artifact@v4
with:
name: requirement-reference-report
path: req_references_report.txt
path: tmp/req_references_report.txt
if-no-files-found: ignore

- name: Run feature coverage audit
run: python3 scripts/audit_feature_coverage.py --output feature_coverage_report.txt --verbose
run: python3 scripts/audit_feature_coverage.py --output tmp/feature_coverage_report.txt --verbose

- name: Upload feature coverage report
if: failure()
uses: actions/upload-artifact@v4
with:
name: feature-coverage-report
path: feature_coverage_report.txt
path: tmp/feature_coverage_report.txt
if-no-files-found: ignore

- name: Run requirements coverage audit
run: python3 scripts/audit_requirements_coverage.py --output requirements_coverage_report.txt --verbose
run: python3 scripts/audit_requirements_coverage.py --output tmp/requirements_coverage_report.txt --verbose

- name: Upload requirements coverage report
if: failure()
uses: actions/upload-artifact@v4
with:
name: requirements-coverage-report
path: requirements_coverage_report.txt
path: tmp/requirements_coverage_report.txt
if-no-files-found: ignore

- name: Run link validation
run: python3 scripts/validate_links.py --output validation_report.txt --verbose
run: python3 scripts/validate_links.py --output tmp/validation_report.txt --verbose

- name: Upload link validation report
if: failure()
uses: actions/upload-artifact@v4
with:
name: link-validation-report
path: validation_report.txt
path: tmp/validation_report.txt
if-no-files-found: ignore

- name: Run markdown linting
if: always()
run: NODE_OPTIONS="--no-warnings=MODULE_TYPELESS_PACKAGE_JSON" markdownlint-cli2 "**/*.md"
run: NODE_OPTIONS="--no-warnings=MODULE_TYPELESS_PACKAGE_JSON" markdownlint-cli2 "**/*.md" "#tmp/**"
6 changes: 6 additions & 0 deletions .github/workflows/go-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.25'
cache-dependency-path: api/go/go.sum

- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/python-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
python-version: '3.11'

- name: Install Python lint tooling
run: pip install flake8 pylint radon xenon vulture bandit
run: pip install -r scripts/requirements-lint.txt

- name: Run python linting
run: make lint-python
File renamed without changes.
61 changes: 34 additions & 27 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ ci-go: ci-go-v1
ci-go-v1:
/usr/bin/make -C api/go ci

# Python venv for lint tooling - creates .venv and installs requirements-lint.txt
# Run once (or after adding/updating requirements-lint.txt) so make lint-python uses the venv.
# Python venv for lint tooling - creates .venv and installs scripts/requirements-lint.txt
# Run once (or after adding/updating scripts/requirements-lint.txt) so make lint-python uses the venv.
# Usage: make venv
venv:
@command -v python3 >/dev/null 2>&1 || { \
Expand All @@ -50,7 +50,7 @@ venv:
}
@python3 -m venv .venv
@.venv/bin/pip install -q --upgrade pip
@.venv/bin/pip install -q -r requirements-lint.txt
@.venv/bin/pip install -q -r scripts/requirements-lint.txt
@echo "Created .venv with lint tooling. Use 'make lint-python' (it will use .venv when present)."

# Markdown linting - performs same checks as GitHub Actions workflow
Expand Down Expand Up @@ -119,30 +119,28 @@ lint-python:
LINT_PATHS="scripts"; \
fi; \
if [ -d .venv ]; then PATH="$(CURDIR)/.venv/bin:$$PATH"; export PATH; fi; \
export PYTHONPATH="$(CURDIR)/scripts"; \
echo "Running flake8 on Python scripts..."; \
flake8 $$LINT_PATHS --jobs=1; \
flake8 $$LINT_PATHS --jobs=1; FLAKE8_RESULT=$$?; \
echo "Running pylint on Python scripts..."; \
pylint --rcfile=.pylintrc $$LINT_PATHS; \
pylint --rcfile=.pylintrc $$LINT_PATHS; PYLINT_RESULT=$$?; \
echo "Running radon complexity (non-gating)..."; \
radon cc -s -a $$LINT_PATHS || true; \
echo "Running xenon cyclomatic complexity check (fail if any block > C)..."; \
xenon -b C $$LINT_PATHS; \
xenon -b C $$LINT_PATHS; XENON_RESULT=$$?; \
echo "Running radon maintainability metrics (non-gating)..."; \
radon mi -s $$LINT_PATHS || true; \
echo "Running radon maintainability check (fail if any module MI rank C)..."; \
TMP_MI=$$(mktemp); \
radon mi -j $$LINT_PATHS -O $$TMP_MI; \
python3 -c "\
import sys, json; \
d=json.load(open(sys.argv[1])); \
bad=[k for k,v in d.items() if v.get('rank')=='C']; \
[print('MI rank C (low maintainability):', f) for f in bad]; \
sys.exit(1 if bad else 0)" $$TMP_MI; \
MI_RESULT=$$?; rm -f $$TMP_MI; [ $$MI_RESULT -ne 0 ] && exit $$MI_RESULT; \
python3 -c "import sys, json; d=json.load(open(sys.argv[1])); bad=[k for k,v in d.items() if v.get('rank')=='C']; [print('MI rank C (low maintainability):', f) for f in bad]; sys.exit(1 if bad else 0)" $$TMP_MI; \
MI_RESULT=$$?; rm -f $$TMP_MI; \
echo "Running vulture unused code detection (non-gating)..."; \
vulture $$LINT_PATHS --min-confidence 80 || true; \
echo "Running bandit security scan (non-gating)..."; \
bandit -r $$LINT_PATHS --exit-zero
bandit -r $$LINT_PATHS; BANDIT_RESULT=$$?; \
echo ""; echo "Lint exit codes: flake8=$$FLAKE8_RESULT pylint=$$PYLINT_RESULT xenon=$$XENON_RESULT radon_mi=$$MI_RESULT bandit=$$BANDIT_RESULT"; \
[ $$FLAKE8_RESULT -ne 0 ] || [ $$PYLINT_RESULT -ne 0 ] || [ $$XENON_RESULT -ne 0 ] || [ $$MI_RESULT -ne 0 ] || [ $$BANDIT_RESULT -ne 0 ] && exit 1; exit 0

# Link validation - validates all internal markdown links and anchors
# NOTE: This target must be kept in sync with .github/workflows/docs-check.yml.
Expand Down Expand Up @@ -212,29 +210,38 @@ apply-heading-corrections:
if [ -n "$(VERBOSE)" ]; then ARGS="$$ARGS --verbose"; fi; \
eval python3 scripts/apply_heading_corrections.py $$ARGS

# Generate markdown anchor from heading text
# NOTE: This is a utility script for generating markdown anchors from heading text.
# Generate markdown anchors from markdown headings
# NOTE: This is a utility wrapper for scripts/generate_anchor.py.
# Useful for creating links to specific sections in markdown files.
# Requires: Python 3
# Usage: make generate-anchor TEXT="Heading Text"
# - TEXT: Heading text to convert to anchor
# - IMPORTANT: If TEXT contains backticks, you MUST use single quotes:
# make generate-anchor TEXT='Heading with `code` example'
# Using double quotes will cause the shell to process backticks as command
# substitution before make sees them, which will break the heading text.
# Usage: make generate-anchor FILE="path/to/file.md"
# make generate-anchor LINE="path/to/file.md:224"
# - FILE: Print anchors for all headings in the file
# - LINE: Print anchor for the heading at a specific line in the file
generate-anchor:
@command -v python3 >/dev/null 2>&1 || { \
echo "Error: python3 not found. Install Python 3 to generate anchor."; \
exit 1; \
}
@if [ -z "$(TEXT)" ]; then \
echo "Error: TEXT is required."; \
@if [ -z "$(FILE)" ] && [ -z "$(LINE)" ]; then \
echo "Error: FILE or LINE is required."; \
echo ""; \
echo "Usage: make generate-anchor TEXT=\"Heading Text\""; \
echo " make generate-anchor TEXT='Heading with \`code\` example' (use single quotes for backticks)"; \
echo "Usage: make generate-anchor FILE=\"path/to/file.md\""; \
echo " make generate-anchor LINE=\"path/to/file.md:224\""; \
exit 1; \
fi
@python3 scripts/generate_anchor.py --text "$(TEXT)"
@if [ -n "$(FILE)" ] && [ -n "$(LINE)" ]; then \
echo "Error: FILE and LINE are mutually exclusive. Provide only one."; \
echo ""; \
echo "Usage: make generate-anchor FILE=\"path/to/file.md\""; \
echo " make generate-anchor LINE=\"path/to/file.md:224\""; \
exit 1; \
fi
@if [ -n "$(LINE)" ]; then \
python3 scripts/generate_anchor.py --line "$(LINE)"; \
else \
python3 scripts/generate_anchor.py --file "$(FILE)"; \
fi

# Requirement reference validation - validates REQ references in feature files
# NOTE: This target must be kept in sync with .github/workflows/docs-check.yml.
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ This license provides:
- 🛡️ **Defensive termination** - deters frivolous patent litigation.
- 🌍 **Industry standard** - widely recognized and trusted.

For the complete license text, see [LICENSE](LICENSE).
For the complete license text, see [LICENSE](LICENSE.txt).

## Security

Expand All @@ -308,4 +308,4 @@ For detailed security information, see the [Security Architecture](docs/tech_spe
[workflow-go-ci]: https://github.com/novus-engine/novuspack/actions/workflows/go-ci.yml
[workflow-go-bdd]: https://github.com/novus-engine/novuspack/actions/workflows/go-bdd.yml
[workflow-python-lint]: https://github.com/novus-engine/novuspack/actions/workflows/python-lint.yml
[license-file]: LICENSE
[license-file]: LICENSE.txt
21 changes: 9 additions & 12 deletions ai_files/ai_coding_instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,13 @@ The following principles guide all development work on this project.

### 1.5 Shell Quoting with Backticks

- **Critical Rule:** When passing text containing backticks (e.g., markdown headings with inline code like `` `code` ``) to shell commands or Makefile targets, always use single quotes to preserve the backticks.
- **Why:** The shell processes backticks as command substitution before make or scripts see them, which will break the text.
- **Correct Examples:**
- `` make generate-anchor TEXT='Heading with `code` example' ``
- `` python3 scripts/generate_anchor.py --text 'File Management with `Package` type' ``
- **Incorrect Examples:**
- `` make generate-anchor TEXT="Heading with \`code\` example" `` (shell processes backticks before make sees them)
- `` python3 scripts/generate_anchor.py --text "File Management with \`Package\` type" `` (same issue)
- **Applies To:** Any command or script that accepts text containing backticks, including the `generate-anchor` Make target and related scripts.
- **Critical Rule:** Avoid passing markdown headings (especially ones containing backticks like `` `code` ``) as command-line string arguments.
- **Why:** Backticks are command substitution in shells, and quoting/escaping is error-prone for both humans and AI agents.
- **Fallback (when text must be on the command line):** Use single quotes (not double quotes) wherever possible and escape backticks in all other cases.
- **Correct Examples (preferred, file-based):**
- `` make generate-anchor LINE='docs/tech_specs/api_core.md:224' ``
- `` make generate-anchor FILE='docs/tech_specs/api_core.md' ``
- **Applies To:** Any tooling that needs to work with markdown headings containing backticks.

## 2. Development Workflow

Expand Down Expand Up @@ -294,9 +292,8 @@ Quick reference:
- Note: Skipped when PATHS is specified (requires all tech specs)
- **`make validate-req-references [VERBOSE=1]`** - Validate requirement references
- Note: Skipped when PATHS is specified (requires all feature files)
- **`make generate-anchor TEXT='Heading Text'`** - Generate markdown anchor from heading text
- Use single quotes (see example in section 1.5)
- The script automatically removes backticks and their contents when generating anchors
- **`make generate-anchor FILE='path/to/file.md'`** - Print anchors for all headings in a file
- **`make generate-anchor LINE='path/to/file.md:224'`** - Print anchor for the heading at a specific line in a file
- See [Shell Quoting with Backticks](#15-shell-quoting-with-backticks) for details

#### Coverage Audit Targets
Expand Down
13 changes: 9 additions & 4 deletions api/go/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ ifneq ($(MAKE),$(SYSTEM_MAKE))
override MAKE := $(SYSTEM_MAKE)
endif

.PHONY: test bdd bdd-ci bdd-domain ci tidy coverage coverage-html coverage-report validate-go-spec-references apply-go-spec-references
.PHONY: test bdd bdd-ci bdd-domain ci tidy go-fmt coverage coverage-html coverage-report validate-go-spec-references apply-go-spec-references

BDD_TAGS ?= '~@skip && ~@wip'
BDD_DOMAIN ?= ''
BDD_OUTPUT_DIR ?= ../../../tmp
BDD_OUTPUT_DIR ?= ../../tmp
BDD_OUTPUT_FILE ?= $(BDD_OUTPUT_DIR)/bdd_test_output_$(shell date +%Y%m%d_%H%M%S).txt

# Tidy dependencies - must use bdd build tag to preserve BDD dependencies
Expand All @@ -24,6 +24,12 @@ tidy:
@GOFLAGS=-tags=bdd go mod tidy
@echo "Dependencies tidied successfully."

# Format Go source files
go-fmt:
@echo "Running go fmt..."
@go fmt ./...
@echo "Formatting complete."

# Run all unit tests
# Set GOCACHE to a writable location if the default cache is not writable
# Test actual write capability by attempting to create a test file
Expand Down Expand Up @@ -132,8 +138,7 @@ lint:
@go vet ./...
@echo ""
@echo "Running golangci-lint..."
@golangci-lint run --exclude-dir=_bdd ./...
@golangci-lint run --build-tags=bdd ./...
@golangci-lint run ./...

# Go signature validation - validates Go signatures in implementation against tech specs
# NOTE: This target must be kept in sync with .github/workflows/docs-check.yml.
Expand Down
2 changes: 1 addition & 1 deletion api/go/fileformat/file_format_constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// only constant definitions used throughout the fileformat package and re-exported
// by the main novuspack package.
//
// Specification: package_file_format.md: 1 `.nvpk` File Format Overview
// Specification: package_file_format.md: 1 1. .Nvpk File Format Overview

// Package novuspack provides the core NovusPack file format implementation.
//
Expand Down
Loading
Loading