Skip to content

Add static complexity analysis for generated policies - #214

Draft
joshnroy wants to merge 28 commits into
mainfrom
codex/static-policy-complexity
Draft

joshnroy wants to merge 28 commits into
mainfrom
codex/static-policy-complexity

Conversation

@joshnroy

@joshnroy joshnroy commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • add a serial, ZIP-aware analyzer for final AgenticApproach programs
  • calculate deterministic complexity metrics without importing or executing generated code
  • aggregate mean and sample standard deviation across seeds
  • add a reproducible mean/std plotting utility
  • pin numerical libraries to one thread for minimal workstation impact

Metric reference

Size

  • source_loc: physical lines, including blanks, comments, and docstrings
  • nonblank_loc: non-empty physical lines
  • logical_loc: logical Python statements, approximated from tokenizer logical newlines
  • comment_lines: lines containing a Python comment
  • ast_nodes: total abstract-syntax-tree nodes; a largely formatting-insensitive measure of syntactic size
  • class_count / function_count: class and function or method definitions
  • helper_function_count: functions other than __init__, reset, get_action, and update

Branching and control flow

  • branch_count: if, elif, and conditional expressions
  • loop_count: for, async-for, and while loops
  • exception_handler_count: except handlers
  • max_nesting_depth: deepest nesting of conditions, loops, context managers, try, and match
  • cyclomatic_total: file-wide McCabe-style complexity, starting at one and adding contributions for branches, loops, handlers, Boolean alternatives, comprehensions, and match cases
  • cyclomatic_mean_function: mean cyclomatic complexity across functions
  • cyclomatic_max_function: largest complexity of any function
  • get_action_cyclomatic / reset_cyclomatic / update_cyclomatic: complexity of each named policy method

Cyclomatic complexity approximates independent control-flow paths; it is not the number of policy behaviors or runtime paths.

Policy state

  • persistent_state_fields: distinct attributes assigned through self.<name>. This approximates memory retained across calls but includes episodic state and configuration references.

Calls, dependencies, and constants

  • unique_imports: distinct directly imported modules
  • unique_calls: distinct statically recognizable called names
  • unique_numeric_literals: distinct numeric literals excluding booleans; a rough threshold-variety measure

Halstead metrics

  • halstead_vocabulary: distinct operators plus distinct operands
  • halstead_length: total operator and operand occurrences
  • halstead_volume: length × log2(vocabulary)
  • halstead_difficulty: (distinct operators / 2) × (total operands / distinct operands)
  • halstead_effort: volume × difficulty
  • maintainability_index: clamped 0–100 composite of Halstead volume, cyclomatic complexity, and logical LOC; large generated policies may saturate near zero

Parse, provenance, and results

  • syntax_valid / syntax_error: whether ast.parse accepts the source and any error; parsing never executes the policy
  • source, approach, environment, replicate_seed, experiment_id, access, backend: provenance and grouping fields
  • has_results: whether the run contains results.json
  • result_*: fields copied or flattened from results.json, not static metrics

Aggregation

The summary emits <metric>_mean and <metric>_std. Standard deviation is sample SD across replicate seeds (N - 1 denominator) and is undefined for one-program groups.

The recommended headline profile is total cyclomatic complexity, maximum function complexity, get_action complexity, maximum nesting depth, persistent state fields, loop count, and logical LOC. These dimensions should not be collapsed into one universal score.

Validation

  • 4 focused tests pass
  • local serial analysis covered 50 policies in about 1.4 seconds
  • one CPU thread, approximately 84 MB peak RSS, and no network activity during analysis

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant