lex-cognitive-grammar 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/ci.yml +16 -0
- data/.gitignore +2 -0
- data/.rspec +2 -0
- data/.rubocop.yml +52 -0
- data/CLAUDE.md +116 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +78 -0
- data/README.md +56 -0
- data/lex-cognitive-grammar.gemspec +29 -0
- data/lib/legion/extensions/cognitive_grammar/client.rb +25 -0
- data/lib/legion/extensions/cognitive_grammar/helpers/constants.rb +34 -0
- data/lib/legion/extensions/cognitive_grammar/helpers/construal.rb +64 -0
- data/lib/legion/extensions/cognitive_grammar/helpers/construction.rb +64 -0
- data/lib/legion/extensions/cognitive_grammar/helpers/grammar_engine.rb +115 -0
- data/lib/legion/extensions/cognitive_grammar/runners/cognitive_grammar.rb +96 -0
- data/lib/legion/extensions/cognitive_grammar/version.rb +9 -0
- data/lib/legion/extensions/cognitive_grammar.rb +17 -0
- metadata +78 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 7d1a6033a3d40b2be785361c3c86637af7d504cdfa3389e4501e6634a69f7bf2
|
|
4
|
+
data.tar.gz: d95e46dd8e3846f5dce29a3d7d1c17290a06f8df16ebb747fac388e6ae393999
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: ee8709710023d006ce784491caff43246edf7e69105ae7a88935d5bbb528eb74d62e0990c6f590ee422ba3c885f8b437eed35f44014a644c6a36bd0b4fc38c91
|
|
7
|
+
data.tar.gz: 4eeba781ebdf5d0065e9f18bc4874c1f78c8d8b5a132f8f75675f3e5a223d4fb790a4215b3460db4614d0af66f545047ad4708dbabb8c80374306c20a91417f2
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [main]
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
ci:
|
|
9
|
+
uses: LegionIO/.github/.github/workflows/ci.yml@main
|
|
10
|
+
|
|
11
|
+
release:
|
|
12
|
+
needs: ci
|
|
13
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
14
|
+
uses: LegionIO/.github/.github/workflows/release.yml@main
|
|
15
|
+
secrets:
|
|
16
|
+
rubygems-api-key: ${{ secrets.RUBYGEMS_API_KEY }}
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 3.4
|
|
3
|
+
NewCops: enable
|
|
4
|
+
SuggestExtensions: false
|
|
5
|
+
|
|
6
|
+
Layout/LineLength:
|
|
7
|
+
Max: 160
|
|
8
|
+
|
|
9
|
+
Layout/SpaceAroundEqualsInParameterDefault:
|
|
10
|
+
EnforcedStyle: space
|
|
11
|
+
|
|
12
|
+
Layout/HashAlignment:
|
|
13
|
+
EnforcedHashRocketStyle: table
|
|
14
|
+
EnforcedColonStyle: table
|
|
15
|
+
|
|
16
|
+
Metrics/MethodLength:
|
|
17
|
+
Max: 25
|
|
18
|
+
|
|
19
|
+
Metrics/ClassLength:
|
|
20
|
+
Max: 150
|
|
21
|
+
|
|
22
|
+
Metrics/ModuleLength:
|
|
23
|
+
Max: 150
|
|
24
|
+
|
|
25
|
+
Metrics/BlockLength:
|
|
26
|
+
Max: 40
|
|
27
|
+
Exclude:
|
|
28
|
+
- 'spec/**/*'
|
|
29
|
+
|
|
30
|
+
Metrics/AbcSize:
|
|
31
|
+
Max: 25
|
|
32
|
+
|
|
33
|
+
Metrics/ParameterLists:
|
|
34
|
+
Max: 8
|
|
35
|
+
MaxOptionalParameters: 8
|
|
36
|
+
|
|
37
|
+
Style/Documentation:
|
|
38
|
+
Enabled: false
|
|
39
|
+
|
|
40
|
+
Style/FrozenStringLiteralComment:
|
|
41
|
+
Enabled: true
|
|
42
|
+
EnforcedStyle: always
|
|
43
|
+
|
|
44
|
+
Style/OneClassPerFile:
|
|
45
|
+
Exclude:
|
|
46
|
+
- 'spec/spec_helper.rb'
|
|
47
|
+
|
|
48
|
+
Naming/FileName:
|
|
49
|
+
Enabled: false
|
|
50
|
+
|
|
51
|
+
Naming/PredicateMethod:
|
|
52
|
+
Enabled: false
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# lex-cognitive-grammar
|
|
2
|
+
|
|
3
|
+
**Level 3 Leaf Documentation**
|
|
4
|
+
- **Parent**: `/Users/miverso2/rubymine/legion/extensions-agentic/CLAUDE.md`
|
|
5
|
+
- **Gem**: `lex-cognitive-grammar`
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
Models cognitive grammar — the structured mental constructions through which meaning is assembled. Based on Cognitive Linguistics: constructions are symbolic units (form-meaning pairings) stored in a construction grammar network. Construals represent specific applications of constructions to scenes. Each use of a construction strengthens its activation via Exponential Moving Average. Constructions that exceed the entrenchment threshold (0.8) become automatic. A periodic maintenance actor decays unused constructions over time.
|
|
10
|
+
|
|
11
|
+
## Gem Info
|
|
12
|
+
|
|
13
|
+
| Field | Value |
|
|
14
|
+
|---|---|
|
|
15
|
+
| Gem name | `lex-cognitive-grammar` |
|
|
16
|
+
| Version | `0.1.0` |
|
|
17
|
+
| Namespace | `Legion::Extensions::CognitiveGrammar` |
|
|
18
|
+
| Ruby | `>= 3.4` |
|
|
19
|
+
| License | MIT |
|
|
20
|
+
| GitHub | https://github.com/LegionIO/lex-cognitive-grammar |
|
|
21
|
+
|
|
22
|
+
## File Structure
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
lib/legion/extensions/cognitive_grammar/
|
|
26
|
+
cognitive_grammar.rb # Top-level require
|
|
27
|
+
version.rb # VERSION = '0.1.0'
|
|
28
|
+
client.rb # Client class
|
|
29
|
+
helpers/
|
|
30
|
+
constants.rb # Construal operations, prominence types, activation labels, thresholds
|
|
31
|
+
construction.rb # Construction value object (form-meaning unit)
|
|
32
|
+
construal.rb # Construal value object (specific scene interpretation)
|
|
33
|
+
grammar_engine.rb # Engine: constructions, construals, activation, decay
|
|
34
|
+
runners/
|
|
35
|
+
cognitive_grammar.rb # Runner module
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Key Constants
|
|
39
|
+
|
|
40
|
+
| Constant | Value | Meaning |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| `CONSTRUAL_OPERATIONS` | array | Mental operations: `profiling`, `trajector_landmark`, `figure_ground`, `scope`, `perspective`, `dynamism` |
|
|
43
|
+
| `PROMINENCE_TYPES` | array | `[:trajector, :landmark, :profiled, :active_zone, :reference_point, :base]` |
|
|
44
|
+
| `EXPRESSION_TYPES` | array | `[:nominal, :verbal, :clausal, :prepositional, :adjectival, :constructional]` |
|
|
45
|
+
| `MAX_CONSTRUCTIONS` | 200 | Construction store cap |
|
|
46
|
+
| `MAX_CONSTRUALS` | 500 | Construal history cap |
|
|
47
|
+
| `DEFAULT_ACTIVATION` | 0.3 | Starting activation for new constructions |
|
|
48
|
+
| `ENTRENCHMENT_THRESHOLD` | 0.8 | Activation above this = entrenched (automatic) |
|
|
49
|
+
| `ACTIVATION_LABELS` | hash | `entrenched` (0.8+) through `dormant` |
|
|
50
|
+
|
|
51
|
+
## Helpers
|
|
52
|
+
|
|
53
|
+
### `Construction`
|
|
54
|
+
|
|
55
|
+
A symbolic form-meaning unit in the grammar network.
|
|
56
|
+
|
|
57
|
+
- `initialize(name:, form:, meaning:, domain:, activation: DEFAULT_ACTIVATION, construction_id: nil)`
|
|
58
|
+
- `use!(alpha: 0.2)` — updates activation via EMA; increments use count
|
|
59
|
+
- `decay!(rate: 0.01)` — decreases activation
|
|
60
|
+
- `entrenched?` — activation >= `ENTRENCHMENT_THRESHOLD`
|
|
61
|
+
- `inactive?` — activation below threshold
|
|
62
|
+
- `to_h`
|
|
63
|
+
|
|
64
|
+
### `Construal`
|
|
65
|
+
|
|
66
|
+
A specific application of a construction to a scene.
|
|
67
|
+
|
|
68
|
+
- `initialize(construction_id:, scene:, operation:, prominence:, construal_id: nil)`
|
|
69
|
+
- `to_h`
|
|
70
|
+
|
|
71
|
+
### `GrammarEngine`
|
|
72
|
+
|
|
73
|
+
- `create_construction(name:, form:, meaning:, domain:)` — returns `{ created:, construction_id:, construction: }` or capacity error
|
|
74
|
+
- `create_construal(construction_id:, scene:, operation:, prominence:)` — validates construction exists; appends to construal ring buffer
|
|
75
|
+
- `use_construction(construction_id:)` — fires EMA update; returns before/after activation + entrenchment state
|
|
76
|
+
- `entrenched_constructions(limit: 20)` — sorted by activation descending
|
|
77
|
+
- `decay_all(rate: 0.01)` — decays all constructions
|
|
78
|
+
- `prune_inactive(threshold: 0.05)` — removes constructions below activation floor
|
|
79
|
+
- `constructions_by_domain` — groups by domain
|
|
80
|
+
- `most_used(limit: 10)` — sorted by use_count
|
|
81
|
+
- `grammar_report` — full stats
|
|
82
|
+
|
|
83
|
+
## Runners
|
|
84
|
+
|
|
85
|
+
**Module**: `Legion::Extensions::CognitiveGrammar::Runners::CognitiveGrammar`
|
|
86
|
+
|
|
87
|
+
| Method | Key Args | Returns |
|
|
88
|
+
|---|---|---|
|
|
89
|
+
| `create_grammar_construction` | `name:`, `form:`, `meaning:`, `domain:` | `{ success:, construction_id:, construction: }` |
|
|
90
|
+
| `create_grammar_construal` | `construction_id:`, `scene:`, `operation:`, `prominence:` | `{ success:, construal_id:, construal: }` |
|
|
91
|
+
| `use_grammar_construction` | `construction_id:` | `{ success:, before:, after:, entrenched: }` |
|
|
92
|
+
| `construals_for_scene_report` | `scene:` | `{ success:, construals: }` |
|
|
93
|
+
| `entrenched_constructions_report` | `limit: 20` | `{ success:, constructions: }` |
|
|
94
|
+
| `constructions_by_domain_report` | — | `{ success:, domains: }` |
|
|
95
|
+
| `most_used_constructions` | `limit: 10` | `{ success:, constructions: }` |
|
|
96
|
+
| `update_cognitive_grammar` | — | `{ success:, decayed: }` — runs decay pass |
|
|
97
|
+
| `cognitive_grammar_stats` | — | engine `to_h` |
|
|
98
|
+
|
|
99
|
+
Private: `grammar_engine` — memoized `GrammarEngine`. Logs via `log_debug` helper.
|
|
100
|
+
|
|
101
|
+
## Integration Points
|
|
102
|
+
|
|
103
|
+
- **`lex-tick`**: `update_cognitive_grammar` is the maintenance operation; can be wired into `memory_consolidation` or a dedicated grammar-maintenance phase.
|
|
104
|
+
- **`lex-memory`**: Construction activation mirrors memory trace strength. Entrenched constructions could be co-stored as procedural memory traces in lex-memory for cross-extension retrieval.
|
|
105
|
+
- **`lex-cognitive-flexibility`**: Switching task sets may require activating constructions appropriate to the new domain. Grammar constructions and task-set rules operate at complementary abstraction levels.
|
|
106
|
+
|
|
107
|
+
## Development Notes
|
|
108
|
+
|
|
109
|
+
- `use_construction` updates activation via EMA on each call. Frequent use rapidly entrenches a construction; infrequent use combined with periodic `decay_all` calls keeps the grammar network trimmed.
|
|
110
|
+
- `prune_inactive` is destructive — constructions removed cannot be recovered. Call with a conservative threshold.
|
|
111
|
+
- `construals_for_scene_report` searches the construal buffer for exact scene string matches.
|
|
112
|
+
- In-memory only.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
**Maintained By**: Matthew Iverson (@Esity)
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
lex-cognitive-grammar (0.1.0)
|
|
5
|
+
|
|
6
|
+
GEM
|
|
7
|
+
remote: https://rubygems.org/
|
|
8
|
+
specs:
|
|
9
|
+
addressable (2.8.9)
|
|
10
|
+
public_suffix (>= 2.0.2, < 8.0)
|
|
11
|
+
ast (2.4.3)
|
|
12
|
+
bigdecimal (4.0.1)
|
|
13
|
+
diff-lcs (1.6.2)
|
|
14
|
+
json (2.19.1)
|
|
15
|
+
json-schema (6.2.0)
|
|
16
|
+
addressable (~> 2.8)
|
|
17
|
+
bigdecimal (>= 3.1, < 5)
|
|
18
|
+
language_server-protocol (3.17.0.5)
|
|
19
|
+
lint_roller (1.1.0)
|
|
20
|
+
mcp (0.8.0)
|
|
21
|
+
json-schema (>= 4.1)
|
|
22
|
+
parallel (1.27.0)
|
|
23
|
+
parser (3.3.10.2)
|
|
24
|
+
ast (~> 2.4.1)
|
|
25
|
+
racc
|
|
26
|
+
prism (1.9.0)
|
|
27
|
+
public_suffix (7.0.5)
|
|
28
|
+
racc (1.8.1)
|
|
29
|
+
rainbow (3.1.1)
|
|
30
|
+
regexp_parser (2.11.3)
|
|
31
|
+
rspec (3.13.2)
|
|
32
|
+
rspec-core (~> 3.13.0)
|
|
33
|
+
rspec-expectations (~> 3.13.0)
|
|
34
|
+
rspec-mocks (~> 3.13.0)
|
|
35
|
+
rspec-core (3.13.6)
|
|
36
|
+
rspec-support (~> 3.13.0)
|
|
37
|
+
rspec-expectations (3.13.5)
|
|
38
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
39
|
+
rspec-support (~> 3.13.0)
|
|
40
|
+
rspec-mocks (3.13.8)
|
|
41
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
42
|
+
rspec-support (~> 3.13.0)
|
|
43
|
+
rspec-support (3.13.7)
|
|
44
|
+
rubocop (1.85.1)
|
|
45
|
+
json (~> 2.3)
|
|
46
|
+
language_server-protocol (~> 3.17.0.2)
|
|
47
|
+
lint_roller (~> 1.1.0)
|
|
48
|
+
mcp (~> 0.6)
|
|
49
|
+
parallel (~> 1.10)
|
|
50
|
+
parser (>= 3.3.0.2)
|
|
51
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
52
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
53
|
+
rubocop-ast (>= 1.49.0, < 2.0)
|
|
54
|
+
ruby-progressbar (~> 1.7)
|
|
55
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
56
|
+
rubocop-ast (1.49.1)
|
|
57
|
+
parser (>= 3.3.7.2)
|
|
58
|
+
prism (~> 1.7)
|
|
59
|
+
rubocop-rspec (3.9.0)
|
|
60
|
+
lint_roller (~> 1.1)
|
|
61
|
+
rubocop (~> 1.81)
|
|
62
|
+
ruby-progressbar (1.13.0)
|
|
63
|
+
unicode-display_width (3.2.0)
|
|
64
|
+
unicode-emoji (~> 4.1)
|
|
65
|
+
unicode-emoji (4.2.0)
|
|
66
|
+
|
|
67
|
+
PLATFORMS
|
|
68
|
+
arm64-darwin-25
|
|
69
|
+
ruby
|
|
70
|
+
|
|
71
|
+
DEPENDENCIES
|
|
72
|
+
lex-cognitive-grammar!
|
|
73
|
+
rspec (~> 3.13)
|
|
74
|
+
rubocop (~> 1.75)
|
|
75
|
+
rubocop-rspec
|
|
76
|
+
|
|
77
|
+
BUNDLED WITH
|
|
78
|
+
2.6.9
|
data/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# lex-cognitive-grammar
|
|
2
|
+
|
|
3
|
+
Cognitive grammar construction network for brain-modeled agentic AI in the LegionIO ecosystem.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
Models the mental grammar through which meaning is assembled. Constructions are symbolic form-meaning units that activate with use and decay when dormant. Construals represent specific applications of constructions to scenes using cognitive operations (profiling, figure-ground, scope, perspective). Each use of a construction strengthens its activation via Exponential Moving Average. Once activation crosses the entrenchment threshold (0.8), the construction becomes automatic. A periodic decay pass prunes underused constructions from the network.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
require 'legion/extensions/cognitive_grammar'
|
|
13
|
+
|
|
14
|
+
client = Legion::Extensions::CognitiveGrammar::Client.new
|
|
15
|
+
|
|
16
|
+
# Create a form-meaning construction
|
|
17
|
+
result = client.create_grammar_construction(
|
|
18
|
+
name: 'caused_motion',
|
|
19
|
+
form: '[Agent VERB Theme Path]',
|
|
20
|
+
meaning: 'agent causes theme to move along path',
|
|
21
|
+
domain: :motion
|
|
22
|
+
)
|
|
23
|
+
construction_id = result[:construction_id]
|
|
24
|
+
|
|
25
|
+
# Apply it to a scene (construal)
|
|
26
|
+
client.create_grammar_construal(
|
|
27
|
+
construction_id: construction_id,
|
|
28
|
+
scene: 'pushing the idea forward',
|
|
29
|
+
operation: :figure_ground,
|
|
30
|
+
prominence: :trajector
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# Record a use — updates EMA activation
|
|
34
|
+
client.use_grammar_construction(construction_id: construction_id)
|
|
35
|
+
# => { success: true, before: 0.3, after: 0.37, entrenched: false }
|
|
36
|
+
|
|
37
|
+
# Check which constructions are entrenched
|
|
38
|
+
client.entrenched_constructions_report(limit: 10)
|
|
39
|
+
# => { success: true, constructions: [...] }
|
|
40
|
+
|
|
41
|
+
# Periodic decay maintenance
|
|
42
|
+
client.update_cognitive_grammar
|
|
43
|
+
# => { success: true, decayed: 1 }
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Development
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
bundle install
|
|
50
|
+
bundle exec rspec
|
|
51
|
+
bundle exec rubocop
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## License
|
|
55
|
+
|
|
56
|
+
MIT
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/legion/extensions/cognitive_grammar/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'lex-cognitive-grammar'
|
|
7
|
+
spec.version = Legion::Extensions::CognitiveGrammar::VERSION
|
|
8
|
+
spec.authors = ['Esity']
|
|
9
|
+
spec.email = ['matthewdiverson@gmail.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'LEX Cognitive Grammar'
|
|
12
|
+
spec.description = 'Langacker-inspired cognitive grammar engine for LegionIO — construal operations, construction entrenchment, and meaning as construal'
|
|
13
|
+
spec.homepage = 'https://github.com/LegionIO/lex-cognitive-grammar'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
|
+
spec.required_ruby_version = '>= 3.4'
|
|
16
|
+
|
|
17
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
18
|
+
spec.metadata['source_code_uri'] = 'https://github.com/LegionIO/lex-cognitive-grammar'
|
|
19
|
+
spec.metadata['documentation_uri'] = 'https://github.com/LegionIO/lex-cognitive-grammar'
|
|
20
|
+
spec.metadata['changelog_uri'] = 'https://github.com/LegionIO/lex-cognitive-grammar'
|
|
21
|
+
spec.metadata['bug_tracker_uri'] = 'https://github.com/LegionIO/lex-cognitive-grammar/issues'
|
|
22
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
23
|
+
|
|
24
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
25
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
26
|
+
end
|
|
27
|
+
spec.require_paths = ['lib']
|
|
28
|
+
spec.add_development_dependency 'legion-gaia'
|
|
29
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/cognitive_grammar/helpers/constants'
|
|
4
|
+
require 'legion/extensions/cognitive_grammar/helpers/construction'
|
|
5
|
+
require 'legion/extensions/cognitive_grammar/helpers/construal'
|
|
6
|
+
require 'legion/extensions/cognitive_grammar/helpers/grammar_engine'
|
|
7
|
+
require 'legion/extensions/cognitive_grammar/runners/cognitive_grammar'
|
|
8
|
+
|
|
9
|
+
module Legion
|
|
10
|
+
module Extensions
|
|
11
|
+
module CognitiveGrammar
|
|
12
|
+
class Client
|
|
13
|
+
include Runners::CognitiveGrammar
|
|
14
|
+
|
|
15
|
+
def initialize(**)
|
|
16
|
+
@engine = Helpers::GrammarEngine.new
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
attr_reader :engine
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveGrammar
|
|
6
|
+
module Helpers
|
|
7
|
+
module Constants
|
|
8
|
+
CONSTRUAL_OPERATIONS = %i[perspective prominence specificity scope dynamicity].freeze
|
|
9
|
+
PROMINENCE_TYPES = %i[figure ground].freeze
|
|
10
|
+
SPECIFICITY_LEVELS = %i[schematic intermediate detailed].freeze
|
|
11
|
+
SCOPE_LEVELS = %i[immediate local global].freeze
|
|
12
|
+
EXPRESSION_TYPES = %i[nominal relational clausal].freeze
|
|
13
|
+
|
|
14
|
+
ACTIVATION_LABELS = {
|
|
15
|
+
(0.8..) => :entrenched,
|
|
16
|
+
(0.6...0.8) => :conventional,
|
|
17
|
+
(0.4...0.6) => :familiar,
|
|
18
|
+
(0.2...0.4) => :novel,
|
|
19
|
+
(..0.2) => :ad_hoc
|
|
20
|
+
}.freeze
|
|
21
|
+
|
|
22
|
+
MAX_CONSTRUCTIONS = 200
|
|
23
|
+
MAX_CONSTRUALS = 500
|
|
24
|
+
MAX_HISTORY = 500
|
|
25
|
+
|
|
26
|
+
DEFAULT_ACTIVATION = 0.3
|
|
27
|
+
ACTIVATION_BOOST = 0.1
|
|
28
|
+
ACTIVATION_DECAY = 0.02
|
|
29
|
+
ENTRENCHMENT_THRESHOLD = 0.8
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module CognitiveGrammar
|
|
8
|
+
module Helpers
|
|
9
|
+
class Construal
|
|
10
|
+
include Constants
|
|
11
|
+
|
|
12
|
+
attr_reader :id, :scene, :perspective, :figure, :ground, :specificity,
|
|
13
|
+
:scope, :dynamicity, :construction_id, :created_at
|
|
14
|
+
|
|
15
|
+
def initialize(scene:, perspective:, figure:, ground:,
|
|
16
|
+
specificity: :intermediate, scope: :local,
|
|
17
|
+
dynamicity: 0.5, construction_id: nil)
|
|
18
|
+
@id = SecureRandom.uuid
|
|
19
|
+
@scene = scene
|
|
20
|
+
@perspective = perspective
|
|
21
|
+
@figure = figure
|
|
22
|
+
@ground = ground
|
|
23
|
+
@specificity = specificity.to_sym
|
|
24
|
+
@scope = scope.to_sym
|
|
25
|
+
@dynamicity = dynamicity.clamp(0.0, 1.0)
|
|
26
|
+
@construction_id = construction_id
|
|
27
|
+
@created_at = Time.now.utc
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def prominent_element
|
|
31
|
+
@figure
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def background_element
|
|
35
|
+
@ground
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def detailed?
|
|
39
|
+
@specificity == :detailed
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def global_scope?
|
|
43
|
+
@scope == :global
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def to_h
|
|
47
|
+
{
|
|
48
|
+
id: @id,
|
|
49
|
+
scene: @scene,
|
|
50
|
+
perspective: @perspective,
|
|
51
|
+
figure: @figure,
|
|
52
|
+
ground: @ground,
|
|
53
|
+
specificity: @specificity,
|
|
54
|
+
scope: @scope,
|
|
55
|
+
dynamicity: @dynamicity,
|
|
56
|
+
construction_id: @construction_id,
|
|
57
|
+
created_at: @created_at
|
|
58
|
+
}
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module CognitiveGrammar
|
|
8
|
+
module Helpers
|
|
9
|
+
class Construction
|
|
10
|
+
include Constants
|
|
11
|
+
|
|
12
|
+
attr_reader :id, :form, :meaning, :expression_type, :usage_count, :domain, :created_at
|
|
13
|
+
attr_accessor :activation
|
|
14
|
+
|
|
15
|
+
def initialize(form:, meaning:, expression_type:, domain:, activation: DEFAULT_ACTIVATION)
|
|
16
|
+
@id = SecureRandom.uuid
|
|
17
|
+
@form = form
|
|
18
|
+
@meaning = meaning
|
|
19
|
+
@expression_type = expression_type.to_sym
|
|
20
|
+
@activation = activation.clamp(0.0, 1.0)
|
|
21
|
+
@usage_count = 0
|
|
22
|
+
@domain = domain
|
|
23
|
+
@created_at = Time.now.utc
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def use!
|
|
27
|
+
@usage_count += 1
|
|
28
|
+
@activation = [@activation + ACTIVATION_BOOST, 1.0].min.round(10)
|
|
29
|
+
self
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def decay!
|
|
33
|
+
@activation = [@activation - ACTIVATION_DECAY, 0.0].max
|
|
34
|
+
self
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def entrenched?
|
|
38
|
+
@activation >= ENTRENCHMENT_THRESHOLD
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def activation_label
|
|
42
|
+
match = ACTIVATION_LABELS.find { |range, _| range.cover?(@activation) }
|
|
43
|
+
match ? match.last : :ad_hoc
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def to_h
|
|
47
|
+
{
|
|
48
|
+
id: @id,
|
|
49
|
+
form: @form,
|
|
50
|
+
meaning: @meaning,
|
|
51
|
+
expression_type: @expression_type,
|
|
52
|
+
activation: @activation,
|
|
53
|
+
usage_count: @usage_count,
|
|
54
|
+
domain: @domain,
|
|
55
|
+
entrenched: entrenched?,
|
|
56
|
+
activation_label: activation_label,
|
|
57
|
+
created_at: @created_at
|
|
58
|
+
}
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveGrammar
|
|
6
|
+
module Helpers
|
|
7
|
+
class GrammarEngine
|
|
8
|
+
include Constants
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@constructions = {}
|
|
12
|
+
@construals = {}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def create_construction(form:, meaning:, expression_type:, domain:, activation: DEFAULT_ACTIVATION)
|
|
16
|
+
prune_constructions_if_needed
|
|
17
|
+
construction = Construction.new(
|
|
18
|
+
form: form,
|
|
19
|
+
meaning: meaning,
|
|
20
|
+
expression_type: expression_type,
|
|
21
|
+
domain: domain,
|
|
22
|
+
activation: activation
|
|
23
|
+
)
|
|
24
|
+
@constructions[construction.id] = construction
|
|
25
|
+
construction
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def create_construal(scene:, perspective:, figure:, ground:,
|
|
29
|
+
specificity: :intermediate, scope: :local,
|
|
30
|
+
dynamicity: 0.5, construction_id: nil)
|
|
31
|
+
prune_construals_if_needed
|
|
32
|
+
construal = Construal.new(
|
|
33
|
+
scene: scene,
|
|
34
|
+
perspective: perspective,
|
|
35
|
+
figure: figure,
|
|
36
|
+
ground: ground,
|
|
37
|
+
specificity: specificity,
|
|
38
|
+
scope: scope,
|
|
39
|
+
dynamicity: dynamicity,
|
|
40
|
+
construction_id: construction_id
|
|
41
|
+
)
|
|
42
|
+
@construals[construal.id] = construal
|
|
43
|
+
construal
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def use_construction(construction_id:)
|
|
47
|
+
construction = @constructions[construction_id]
|
|
48
|
+
return nil unless construction
|
|
49
|
+
|
|
50
|
+
construction.use!
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def construals_for_scene(scene:)
|
|
54
|
+
@construals.values.select { |c| c.scene == scene }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def entrenched_constructions
|
|
58
|
+
@constructions.values.select(&:entrenched?)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def constructions_by_domain(domain:)
|
|
62
|
+
@constructions.values.select { |c| c.domain == domain }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def constructions_by_type(expression_type:)
|
|
66
|
+
type = expression_type.to_sym
|
|
67
|
+
@constructions.values.select { |c| c.expression_type == type }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def most_used(limit: 5)
|
|
71
|
+
@constructions.values.sort_by { |c| -c.usage_count }.first(limit)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def most_activated(limit: 5)
|
|
75
|
+
@constructions.values.sort_by { |c| -c.activation }.first(limit)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def decay_all
|
|
79
|
+
@constructions.each_value(&:decay!)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def prune_inactive
|
|
83
|
+
before = @constructions.size
|
|
84
|
+
@constructions.delete_if { |_, c| c.activation <= 0.05 }
|
|
85
|
+
before - @constructions.size
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def to_h
|
|
89
|
+
{
|
|
90
|
+
constructions_count: @constructions.size,
|
|
91
|
+
construals_count: @construals.size,
|
|
92
|
+
entrenched_count: entrenched_constructions.size
|
|
93
|
+
}
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
private
|
|
97
|
+
|
|
98
|
+
def prune_constructions_if_needed
|
|
99
|
+
return if @constructions.size < MAX_CONSTRUCTIONS
|
|
100
|
+
|
|
101
|
+
oldest = @constructions.values.min_by(&:activation)
|
|
102
|
+
@constructions.delete(oldest.id) if oldest
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def prune_construals_if_needed
|
|
106
|
+
return if @construals.size < MAX_CONSTRUALS
|
|
107
|
+
|
|
108
|
+
oldest = @construals.values.min_by(&:created_at)
|
|
109
|
+
@construals.delete(oldest.id) if oldest
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveGrammar
|
|
6
|
+
module Runners
|
|
7
|
+
module CognitiveGrammar
|
|
8
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
9
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
|
|
11
|
+
def create_grammar_construction(form:, meaning:, expression_type:, domain:, **)
|
|
12
|
+
construction = engine.create_construction(
|
|
13
|
+
form: form,
|
|
14
|
+
meaning: meaning,
|
|
15
|
+
expression_type: expression_type,
|
|
16
|
+
domain: domain
|
|
17
|
+
)
|
|
18
|
+
Legion::Logging.debug "[cognitive_grammar] created construction form=#{form} type=#{expression_type} domain=#{domain}"
|
|
19
|
+
construction.to_h
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def create_grammar_construal(scene:, perspective:, figure:, ground:, # rubocop:disable Metrics/ParameterLists
|
|
23
|
+
specificity: :intermediate, scope: :local,
|
|
24
|
+
dynamicity: 0.5, construction_id: nil, **)
|
|
25
|
+
construal = engine.create_construal(
|
|
26
|
+
scene: scene,
|
|
27
|
+
perspective: perspective,
|
|
28
|
+
figure: figure,
|
|
29
|
+
ground: ground,
|
|
30
|
+
specificity: specificity,
|
|
31
|
+
scope: scope,
|
|
32
|
+
dynamicity: dynamicity,
|
|
33
|
+
construction_id: construction_id
|
|
34
|
+
)
|
|
35
|
+
Legion::Logging.debug "[cognitive_grammar] created construal scene=#{scene} figure=#{figure}"
|
|
36
|
+
construal.to_h
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def use_grammar_construction(construction_id:, **)
|
|
40
|
+
construction = engine.use_construction(construction_id: construction_id)
|
|
41
|
+
return { found: false, construction_id: construction_id } unless construction
|
|
42
|
+
|
|
43
|
+
msg = "[cognitive_grammar] used construction id=#{construction_id[0..7]} " \
|
|
44
|
+
"usage_count=#{construction.usage_count} activation=#{construction.activation.round(3)}"
|
|
45
|
+
Legion::Logging.debug msg
|
|
46
|
+
{ found: true, construction: construction.to_h }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def construals_for_scene_report(scene:, **)
|
|
50
|
+
construals = engine.construals_for_scene(scene: scene)
|
|
51
|
+
Legion::Logging.debug "[cognitive_grammar] construals_for_scene scene=#{scene} count=#{construals.size}"
|
|
52
|
+
{ scene: scene, count: construals.size, construals: construals.map(&:to_h) }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def entrenched_constructions_report(**)
|
|
56
|
+
constructions = engine.entrenched_constructions
|
|
57
|
+
Legion::Logging.debug "[cognitive_grammar] entrenched constructions count=#{constructions.size}"
|
|
58
|
+
{ count: constructions.size, constructions: constructions.map(&:to_h) }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def constructions_by_domain_report(domain:, **)
|
|
62
|
+
constructions = engine.constructions_by_domain(domain: domain)
|
|
63
|
+
Legion::Logging.debug "[cognitive_grammar] constructions_by_domain domain=#{domain} count=#{constructions.size}"
|
|
64
|
+
{ domain: domain, count: constructions.size, constructions: constructions.map(&:to_h) }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def most_used_constructions(limit: 5, **)
|
|
68
|
+
constructions = engine.most_used(limit: limit)
|
|
69
|
+
Legion::Logging.debug "[cognitive_grammar] most_used limit=#{limit} count=#{constructions.size}"
|
|
70
|
+
{ limit: limit, count: constructions.size, constructions: constructions.map(&:to_h) }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def update_cognitive_grammar(**)
|
|
74
|
+
engine.decay_all
|
|
75
|
+
pruned = engine.prune_inactive
|
|
76
|
+
stats = engine.to_h
|
|
77
|
+
Legion::Logging.debug "[cognitive_grammar] update: pruned=#{pruned} remaining=#{stats[:constructions_count]}"
|
|
78
|
+
{ pruned: pruned, stats: stats }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def cognitive_grammar_stats(**)
|
|
82
|
+
stats = engine.to_h
|
|
83
|
+
Legion::Logging.debug "[cognitive_grammar] stats constructions=#{stats[:constructions_count]} construals=#{stats[:construals_count]}"
|
|
84
|
+
stats
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private
|
|
88
|
+
|
|
89
|
+
def engine
|
|
90
|
+
@engine ||= Helpers::GrammarEngine.new
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/cognitive_grammar/version'
|
|
4
|
+
require 'legion/extensions/cognitive_grammar/helpers/constants'
|
|
5
|
+
require 'legion/extensions/cognitive_grammar/helpers/construction'
|
|
6
|
+
require 'legion/extensions/cognitive_grammar/helpers/construal'
|
|
7
|
+
require 'legion/extensions/cognitive_grammar/helpers/grammar_engine'
|
|
8
|
+
require 'legion/extensions/cognitive_grammar/runners/cognitive_grammar'
|
|
9
|
+
require 'legion/extensions/cognitive_grammar/client'
|
|
10
|
+
|
|
11
|
+
module Legion
|
|
12
|
+
module Extensions
|
|
13
|
+
module CognitiveGrammar
|
|
14
|
+
extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lex-cognitive-grammar
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Esity
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: legion-gaia
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
description: Langacker-inspired cognitive grammar engine for LegionIO — construal
|
|
27
|
+
operations, construction entrenchment, and meaning as construal
|
|
28
|
+
email:
|
|
29
|
+
- matthewdiverson@gmail.com
|
|
30
|
+
executables: []
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- ".github/workflows/ci.yml"
|
|
35
|
+
- ".gitignore"
|
|
36
|
+
- ".rspec"
|
|
37
|
+
- ".rubocop.yml"
|
|
38
|
+
- CLAUDE.md
|
|
39
|
+
- Gemfile
|
|
40
|
+
- Gemfile.lock
|
|
41
|
+
- README.md
|
|
42
|
+
- lex-cognitive-grammar.gemspec
|
|
43
|
+
- lib/legion/extensions/cognitive_grammar.rb
|
|
44
|
+
- lib/legion/extensions/cognitive_grammar/client.rb
|
|
45
|
+
- lib/legion/extensions/cognitive_grammar/helpers/constants.rb
|
|
46
|
+
- lib/legion/extensions/cognitive_grammar/helpers/construal.rb
|
|
47
|
+
- lib/legion/extensions/cognitive_grammar/helpers/construction.rb
|
|
48
|
+
- lib/legion/extensions/cognitive_grammar/helpers/grammar_engine.rb
|
|
49
|
+
- lib/legion/extensions/cognitive_grammar/runners/cognitive_grammar.rb
|
|
50
|
+
- lib/legion/extensions/cognitive_grammar/version.rb
|
|
51
|
+
homepage: https://github.com/LegionIO/lex-cognitive-grammar
|
|
52
|
+
licenses:
|
|
53
|
+
- MIT
|
|
54
|
+
metadata:
|
|
55
|
+
homepage_uri: https://github.com/LegionIO/lex-cognitive-grammar
|
|
56
|
+
source_code_uri: https://github.com/LegionIO/lex-cognitive-grammar
|
|
57
|
+
documentation_uri: https://github.com/LegionIO/lex-cognitive-grammar
|
|
58
|
+
changelog_uri: https://github.com/LegionIO/lex-cognitive-grammar
|
|
59
|
+
bug_tracker_uri: https://github.com/LegionIO/lex-cognitive-grammar/issues
|
|
60
|
+
rubygems_mfa_required: 'true'
|
|
61
|
+
rdoc_options: []
|
|
62
|
+
require_paths:
|
|
63
|
+
- lib
|
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '3.4'
|
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
70
|
+
requirements:
|
|
71
|
+
- - ">="
|
|
72
|
+
- !ruby/object:Gem::Version
|
|
73
|
+
version: '0'
|
|
74
|
+
requirements: []
|
|
75
|
+
rubygems_version: 3.6.9
|
|
76
|
+
specification_version: 4
|
|
77
|
+
summary: LEX Cognitive Grammar
|
|
78
|
+
test_files: []
|