Skip to content

Polarity Axis Analysis - User Guide

Feature: ADR-070 Polarity Axis Analysis for Bidirectional Semantic Dimensions Status: Implemented (2025-11-30) API: POST /query/polarity-axis CLI: kg polarity analyze MCP: analyze_polarity_axis


Overview

Polarity axis analysis enables you to explore conceptual spectrums in your knowledge graph - implicit semantic dimensions along which concepts naturally organize themselves. Unlike relationship traversal which follows explicit edges, polarity analysis reveals the emergent structure of your knowledge through vector mathematics.

Think of it as asking: "Where does this concept fall on the spectrum between X and Y?"

What It Does

Given two opposing concepts (poles), polarity axis analysis: 1. Projects concepts onto the axis - Positions each concept on a -1 to +1 scale 2. Measures alignment - Determines which pole each concept aligns with 3. Calculates orthogonality - Shows which concepts don't fit this dimension 4. Validates with grounding - Checks if position correlates with reliability

Real-World Example

Question: "Where does 'Agile' fall between Modern and Traditional approaches?"

Modern Ways of Working ●────────────────────────● Traditional Operating Models
                       │         ↑               │
                  +1.0 │    Agile (+0.72)        │ -1.0
                       │                         │
                       ├─ DevOps (+0.58)         │
                       ├─ Waterfall (-0.45) ─────┤
                       │                         │
                       └─────────────────────────┘

The axis reveals semantic positioning that might not be captured by explicit relationship edges.


Quick Start

Using the CLI

# Basic analysis with auto-discovery
kg polarity analyze \
  --positive sha256:0d5be_chunk1_a2ccadba \
  --negative sha256:0f72d_chunk1_9a13bb20

# Limit candidates
kg polarity analyze \
  --positive <modern-id> \
  --negative <traditional-id> \
  --max-candidates 30

# Output JSON for scripting
kg polarity analyze \
  --positive <pole1-id> \
  --negative <pole2-id> \
  --json > analysis.json

Using the MCP Tool

analyze_polarity_axis(
  positive_pole_id="sha256:0d5be_chunk1_a2ccadba",
  negative_pole_id="sha256:0f72d_chunk1_9a13bb20",
  auto_discover=true,
  max_candidates=20
)

Using the API

curl -X POST http://localhost:8000/query/polarity-axis \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "positive_pole_id": "sha256:0d5be_chunk1_a2ccadba",
    "negative_pole_id": "sha256:0f72d_chunk1_9a13bb20",
    "auto_discover": true,
    "max_candidates": 20,
    "max_hops": 2
  }'

Understanding the Output

Axis Metadata

Polarity Axis: Modern Ways of Working ↔ Traditional Operating Models

Positive Pole: Modern Ways of Working
  Grounding: Weak (0.104, 10%)
  ID: sha256:0d5be_chunk1_a2ccadba

Negative Pole: Traditional Operating Models
  Grounding: Negative (-0.040, -4%)
  ID: sha256:0f72d_chunk1_9a13bb20

Axis Magnitude: 0.9735
Axis Quality: ✓ Strong (poles are semantically distinct)

What this tells you: - Axis Magnitude: How semantically distinct the poles are (0.9735 is strong) - Axis Quality: Strong = good axis, Weak = poles may be too similar - Pole Grounding: Reliability of each pole concept

Statistics

Total Concepts: 20
Position Range: [-0.734, 0.266]
Mean Position: -0.079 (balanced)
Mean Axis Distance: 0.923 (orthogonal spread)

Direction Distribution:
- Positive (>0.3): 0 concepts
- Neutral (-0.3 to 0.3): 18 concepts
- Negative (<-0.3): 2 concepts

Interpreting statistics: - Position Range: How spread out concepts are along the axis - Mean Position: Axis balance (near 0 = balanced, ±1 = skewed) - Mean Axis Distance: How orthogonal concepts are (higher = more multi-dimensional) - Direction Distribution: How concepts cluster

Grounding Correlation

Pearson r: -0.258
p-value: 0.2712
Interpretation: Weak negative correlation

→ Weak correlation: Position and grounding are loosely related

What correlation means:

Pearson r Meaning Interpretation
r > 0.7 Strong positive Concepts toward positive pole have higher grounding
0.3 < r < 0.7 Moderate positive Some correlation with positive pole reliability
-0.3 < r < 0.3 Weak/None Position and grounding independent
-0.7 < r < -0.3 Moderate negative Concepts toward negative pole have higher grounding
r < -0.7 Strong negative Strong reliability bias toward negative pole

When to trust correlation: - p-value < 0.05: Statistically significant - p-value > 0.05: May be random chance (typical with small samples)

Concept Projections

Positive Direction (toward Modern Ways of Working)
1. Work Management
   Position: 0.266 | Grounding: Weak (0.000, 0%) | Axis distance: 0.8299
   ID: sha256:f024f_chunk1_563d25ec

Neutral (balanced between poles)
2. Agile Work Item Management Tool
   Position: 0.159 | Grounding: Negative (-0.017, -2%) | Axis distance: 0.9507
   ID: sha256:0d5be_chunk3_e5c473cb

Negative Direction (toward Traditional Operating Models)
3. Enterprise Operating Model
   Position: -0.734 | Grounding: Weak (0.148, 15%) | Axis distance: 0.6672
   ID: sha256:0d5be_chunk1_d22215ed

Reading projections: - Position: Where on the spectrum (-1 = negative pole, +1 = positive pole) - Grounding: Reliability of this concept - Axis Distance: How well this dimension explains the concept - Direction: Categorical alignment (positive/neutral/negative)


Interpreting Results

Position Values

         -1.0                    0.0                   +1.0
Negative Pole ●─────────────────●─────────────────● Positive Pole
              │                 │                 │
         Strong            Balanced           Strong
        Alignment         Position          Alignment

Position ranges: - -1.0 to -0.3: Strong alignment with negative pole - -0.3 to +0.3: Neutral/balanced between poles - +0.3 to +1.0: Strong alignment with positive pole

Axis Distance (Orthogonality)

Low distance (< 0.5): Concept lies close to the axis - This dimension explains the concept well - Concept is "on the spectrum"

High distance (> 0.8): Concept is orthogonal to the axis - Other dimensions are more relevant - Concept introduces third dimension

Example:

Security Concept on Modern ↔ Traditional axis:
  Position: 0.12 (slightly modern)
  Axis Distance: 1.45 (very high!)

→ Interpretation: Security is orthogonal to modernization
  (it's a separate concern, not on this spectrum)

Grounding Correlation Patterns

Strong positive correlation (r > 0.7):

Modern ●────────────────────────────● Traditional
  ↑                                      ↓
High Grounding                    Low Grounding

→ This is a VALUE POLARITY
→ Positive pole represents "good" practices
→ Negative pole represents problems/anti-patterns

Strong negative correlation (r < -0.7):

Centralized ●───────────────────────● Decentralized
     ↓                                       ↑
Low Grounding                        High Grounding

→ Reverse value polarity
→ Negative pole has higher reliability
→ May indicate context preference

Weak correlation (|r| < 0.3):

Empirical ●─────────────────────────● Theoretical
    ↑                                      ↑
Both poles have positive grounding

→ NOT a value polarity
→ Both approaches are valid
→ Represents descriptive dimension, not good/bad


Practical Use Cases

1. Understanding Organizational Transformation

Goal: Map where practices fall on the modernization spectrum

kg search "modern operating model" --limit 1 --json | jq -r '.results[0].concept_id'
# → sha256:abc123...

kg search "traditional hierarchy" --limit 1 --json | jq -r '.results[0].concept_id'
# → sha256:def456...

kg polarity analyze --positive sha256:abc123 --negative sha256:def456

What you discover: - Which practices are genuinely modern vs traditional - Synthesis concepts that balance both (neutral position) - Whether "modern" correlates with better outcomes (grounding)

2. Finding Balanced Solutions

Goal: Identify concepts that synthesize two opposing approaches

kg polarity analyze \
  --positive <centralized-id> \
  --negative <distributed-id> \
  --max-candidates 50

Look for: - Concepts with position near 0.0 (balanced) - Low axis distance (truly on the spectrum) - Positive grounding (reliable synthesis)

Example result:

Federated Architecture
  Position: 0.08 (nearly neutral)
  Grounding: +0.62 (reliable)
  Axis Distance: 0.34 (on spectrum)

→ This is a SYNTHESIS concept
→ Balances centralized control with distributed execution

3. Validating Relationship Types

Goal: Check if PREVENTS relationships create meaningful axes

# Find opposing concepts connected by PREVENTS
kg search "legacy systems" --limit 1  # Get ID
kg search "digital transformation" --limit 1  # Get ID

kg polarity analyze --positive <digital-id> --negative <legacy-id>

Strong axis indicators: - High magnitude (> 0.8) - Strong grounding correlation (|r| > 0.7) - Low p-value (< 0.05)

Weak axis indicators: - Low magnitude (< 0.5) → Concepts aren't really opposites - No correlation (|r| < 0.1) → PREVENTS might be incorrectly applied

4. Exploring Knowledge Dimensions

Goal: Discover implicit dimensions in your knowledge base

Strategy: Try different pole pairs and observe patterns

# Try obvious opposites
kg polarity analyze --positive <simple-id> --negative <complex-id>
kg polarity analyze --positive <fast-id> --negative <slow-id>

# Try conceptual opposites
kg polarity analyze --positive <local-id> --negative <global-id>
kg polarity analyze --positive <top-down-id> --negative <bottom-up-id>

What to look for: - Axes with high magnitude (strong semantic distinction) - Axes where grounding correlation reveals value preferences - Concepts that appear on multiple axes (central ideas)

5. Pedagogical Ordering

Goal: Order concepts along a learning progression

kg polarity analyze \
  --positive <advanced-concept-id> \
  --negative <beginner-concept-id> \
  --max-candidates 100

Use position to create learning path:

-1.0 (Beginner)          0.0 (Intermediate)       +1.0 (Advanced)
     ├─ Basic Concept (-0.89)
     ├─ Foundational Pattern (-0.62)
     ├─ Intermediate Technique (+0.12)
     ├─ Advanced Strategy (+0.71)
     └─ Expert Approach (+0.94)


Choosing Good Pole Pairs

What Makes a Good Axis?

Strong semantic opposition:

✅ Good: Modern ↔ Traditional
✅ Good: Centralized ↔ Distributed
✅ Good: Empirical ↔ Theoretical
❌ Bad: Blue ↔ Red (no semantic opposition)
❌ Bad: Apple ↔ Orange (different, not opposite)

Clear conceptual dimension:

✅ Good: Simple ↔ Complex
✅ Good: Fast ↔ Slow
✅ Good: Local ↔ Global
❌ Bad: Car ↔ Airplane (multi-dimensional differences)

Testing Axis Quality

Check axis magnitude: - > 0.9: Excellent opposition - 0.7 - 0.9: Good opposition - 0.5 - 0.7: Moderate opposition - < 0.5: Weak opposition (consider different poles)

Check grounding correlation: - |r| > 0.7: Strong value polarity (reveals preferences) - 0.3 < |r| < 0.7: Moderate correlation (mixed values) - |r| < 0.3: No value polarity (descriptive dimension)

Pole Selection Strategies

1. Use PREVENTS/CONTRADICTS relationships:

# Find concepts with PREVENTS relationships
kg search "digital transformation" --limit 1
# Look at details, find what it PREVENTS
kg concept details <concept-id> | grep PREVENTS

# Use those as pole pair

2. Use domain knowledge: - Think of natural opposites in your field - Consider dimensions experts care about - Look for trade-offs (speed vs accuracy, etc.)

3. Explore existing axes: - Start with obvious opposites - See what concepts cluster - Try orthogonal dimensions


Advanced Techniques

Multi-Axis Analysis

Strategy: Analyze the same concepts across multiple axes

# Axis 1: Modernization
kg polarity analyze --positive <modern-id> --negative <traditional-id> --json > axis1.json

# Axis 2: Centralization
kg polarity analyze --positive <central-id> --negative <distributed-id> --json > axis2.json

# Axis 3: Complexity
kg polarity analyze --positive <complex-id> --negative <simple-id> --json > axis3.json

Cross-reference positions:

# Find concepts that are:
# - Modern (+0.8 on axis 1)
# - Distributed (+0.7 on axis 2)
# - Complex (+0.6 on axis 3)

import json

axis1 = json.load(open('axis1.json'))
axis2 = json.load(open('axis2.json'))
axis3 = json.load(open('axis3.json'))

# Build position map
concepts = {}
for proj in axis1['projections']:
    cid = proj['concept_id']
    concepts[cid] = {'label': proj['label'], 'modern': proj['position']}

for proj in axis2['projections']:
    cid = proj['concept_id']
    if cid in concepts:
        concepts[cid]['distributed'] = proj['position']

for proj in axis3['projections']:
    cid = proj['concept_id']
    if cid in concepts:
        concepts[cid]['complex'] = proj['position']

# Filter for target profile
for cid, data in concepts.items():
    if (data.get('modern', 0) > 0.8 and
        data.get('distributed', 0) > 0.7 and
        data.get('complex', 0) > 0.6):
        print(f"{data['label']}: modern={data['modern']:.2f}, distributed={data['distributed']:.2f}, complex={data['complex']:.2f}")

Tracking Axis Evolution

Strategy: Re-run analysis as your knowledge base grows

# Initial analysis
kg polarity analyze --positive <p1> --negative <n1> --json > snapshot_2025-01-01.json

# After adding documents (later)
kg polarity analyze --positive <p1> --negative <n1> --json > snapshot_2025-02-01.json

# Compare positions
diff snapshot_2025-01-01.json snapshot_2025-02-01.json

What changes mean: - Position shifts: Concepts accumulate new evidence - New concepts appear: Knowledge base expansion - Correlation changes: Value preferences evolve

Identifying Orthogonal Concepts

Goal: Find concepts that don't fit current axes

kg polarity analyze --positive <p1> --negative <n1> --json | \
  jq '.projections[] | select(.axis_distance > 1.0) | {label, axis_distance, position}'

High axis distance concepts: - May represent new dimensions - Could be entry points for different pole pairs - Might be multi-dimensional (need multiple axes to explain)


Performance & Limitations

Performance Characteristics

Execution time: ~2-3 seconds for 20 concepts - Fast enough for interactive exploration - Suitable for on-demand analysis - No job queue overhead

Scaling: - ~100ms per concept (including grounding calculation) - 50 concepts ≈ 5 seconds - 100 concepts ≈ 10 seconds

Bottlenecks: - Grounding strength calculation (most expensive) - Graph traversal for auto-discovery - 768-dimensional vector operations

Current Limitations

1. No axis persistence - Each analysis is computed fresh - Can't save axes for later reuse - Future: Could add :PolarityAxis nodes (ADR-070 Alternative 3)

2. No auto-discovery of axes - Must specify pole pairs manually - Future: Could add /query/discover-polarity-axes endpoint

3. Single-axis projection only - Projects onto 1D axis - Future: Could extend to 2D projections (two orthogonal axes)

4. Limited to concept embeddings - Can't analyze concepts without embeddings - Requires ADR-045 (Unified Embedding Generation)

Best Practices

Do: - ✅ Start with max_candidates=20 for quick exploration - ✅ Check axis quality (magnitude) before interpreting results - ✅ Use grounding correlation to identify value polarities - ✅ Compare multiple axes to understand multi-dimensional space - ✅ Use axis distance to identify orthogonal concepts

Don't: - ❌ Over-interpret weak axes (magnitude < 0.5) - ❌ Assume correlation implies causation - ❌ Ignore high axis distance (orthogonality matters!) - ❌ Use poles that aren't semantically opposite - ❌ Expect perfect linear relationships (knowledge is messy)


Troubleshooting

"Axis quality: Weak"

Problem: Pole concepts aren't semantically distinct

Solutions: 1. Choose more opposing concepts 2. Check if poles are actually synonyms 3. Try different pole pair entirely

"No grounding correlation"

This is often normal!

Not all axes are value polarities: - Empirical ↔ Theoretical (both valid) - Local ↔ Global (context-dependent) - Fast ↔ Slow (trade-offs exist)

Only concerned if: - You expected a value polarity - AND magnitude is high (> 0.8) - AND sample size is large (> 30 concepts)

"All concepts clustered near one pole"

Possible causes: 1. Your knowledge base has bias toward one pole 2. Poles aren't balanced in representation 3. Pole selection doesn't match domain

Solution: Try different pole pairs or accept the bias as signal

"Very high axis distances"

This means: Concepts are multi-dimensional

It's not a problem! It reveals: - Your knowledge can't be reduced to this single axis - Other dimensions are relevant - These concepts might be good poles for OTHER axes


Further Reading

  • ADR-070: Full architectural decision record
  • ADR-058: Polarity Axis Triangulation for Grounding (related technique)
  • ADR-044: Probabilistic Truth Convergence (grounding calculation)
  • Research: Large Concept Models - Meta AI, Dec 2024

Quick Reference

CLI Commands

# Basic analysis
kg polarity analyze --positive <id1> --negative <id2>

# With options
kg polarity analyze \
  --positive <id1> \
  --negative <id2> \
  --max-candidates 30 \
  --max-hops 2 \
  --json

# Find concept IDs first
kg search "modern" --limit 1 --json | jq -r '.results[0].concept_id'

MCP Tool

analyze_polarity_axis(
  positive_pole_id="<id1>",
  negative_pole_id="<id2>",
  auto_discover=true,
  max_candidates=20,
  max_hops=2
)

API Endpoint

POST /query/polarity-axis
{
  "positive_pole_id": "<id1>",
  "negative_pole_id": "<id2>",
  "candidate_ids": ["<id3>", "<id4>"],  // optional
  "auto_discover": true,
  "max_candidates": 20,
  "max_hops": 2
}

Output Structure

{
  "success": true,
  "axis": {
    "positive_pole": {"concept_id": "...", "label": "...", "grounding": 0.12},
    "negative_pole": {"concept_id": "...", "label": "...", "grounding": -0.04},
    "magnitude": 0.97,
    "axis_quality": "strong"
  },
  "projections": [
    {
      "concept_id": "...",
      "label": "...",
      "position": 0.25,
      "direction": "positive",
      "grounding": 0.15,
      "axis_distance": 0.83,
      "similarity_to_positive": 0.72,
      "similarity_to_negative": 0.45
    }
  ],
  "statistics": {
    "total_concepts": 20,
    "position_range": [-0.73, 0.27],
    "mean_position": -0.08,
    "mean_axis_distance": 0.92,
    "direction_distribution": {"positive": 0, "neutral": 18, "negative": 2}
  },
  "grounding_correlation": {
    "pearson_r": -0.26,
    "p_value": 0.27,
    "interpretation": "Weak negative correlation"
  }
}