Skip to content

Commit 2b39557

Browse files
committed
Update feature capabilities matrix
1 parent 8235f2c commit 2b39557

4 files changed

Lines changed: 68 additions & 25 deletions

File tree

docs/MCP.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,14 @@ Each individual framework capability can be gated in the model's `config` array.
131131
### Resolution Rules
132132

133133
For each feature/capability configuration section:
134-
1. **Omitted (Null):** If a capability config section is omitted from the model configuration, the feature defaults to **enabled** for both REST and MCP.
134+
1. **Omitted (Null):** If a capability config section is omitted from the model configuration, the feature's availability defaults to the master model option:
135+
- For **REST API**: falls back to `show_in_rest` (which itself defaults to `true`).
136+
- For **MCP Tools**: falls back to `mcp_tools` (which itself defaults to `false` if omitted).
137+
- If the respective master option is omitted/false, the feature is **disabled**. If the master option is `true`, the feature is **enabled**.
135138
2. **Boolean Value:** If defined as a simple boolean (e.g., `'meta' => false` or `'features' => ['duplicate' => false]`), it acts as a joint gate. A value of `false` disables both REST and MCP for that capability; a value of `true` enables both.
136139
3. **Array Value:** If defined as an array, REST and MCP gating can be configured independently:
137-
- **REST Route Gating:** Governed by the `show_in_rest` key in the section array. If the key is omitted, REST is **enabled** (`true`). If present, it resolves to its boolean value.
138-
- **MCP Tool Gating:** Governed by the `show_in_mcp` key in the section array. If the key is omitted, MCP is **enabled** (`true`). If present, it resolves to its boolean value.
140+
- **REST Route Gating:** Governed by the `show_in_rest` key in the section array. If present, it resolves to its boolean value. If omitted, it falls back to matching the master model `show_in_rest` option.
141+
- **MCP Tool Gating:** Governed by the `show_in_mcp` key in the section array. If present, it resolves to its boolean value. If omitted, it falls back to matching the master model `mcp_tools` option.
139142

140143
Enable all Saltus REST-backed and MCP capabilities for a model:
141144

@@ -170,12 +173,12 @@ return [
170173
'settings' => false,
171174

172175
'features' => [
173-
// 3. Array style: enabled for REST, and defaults to enabled for MCP
176+
// 3. Array style: enabled for REST, and defaults to matching master options (enabled) for MCP
174177
'duplicate' => [
175178
'show_in_rest' => true,
176179
],
177180
// 4. Omitted config for single_export and drag_and_drop:
178-
// both default to enabled for REST and MCP
181+
// both default to matching the master options (enabled here because show_in_rest & mcp_tools are true)
179182
],
180183
],
181184
];

docs/ROADMAP.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,3 +481,21 @@ AI write -> draft/pending/revision -> human approval -> publish
481481
---
482482

483483
**Exit criteria (Phase 6 overall):** AI governance is configurable per model via `ai_context`. Mutating MCP tools respect context rules and default to review-queue creation. Inside-admin assistants are operational for configured models. All features are tested.
484+
485+
---
486+
487+
### Phase 7: Advanced Dependency Injection & Container Hardening (v2.3+)
488+
489+
**Theme:** Upgrade the framework's dependency injection container to support reflection-based parameter resolution (autowiring) for third-party services, avoiding standard constructor mapping errors.
490+
491+
| Item | Status |
492+
|------|--------|
493+
| `ReflectionInstantiator` class implementing `Instantiator` | ○ Pending |
494+
| Positional constructor parameter resolution and dependency matching | ○ Pending |
495+
| Constructor parameter default value fallbacks | ○ Pending |
496+
| Clean validation and exception flow for unresolved parameters | ○ Pending |
497+
| Remove requirement for `Assembly::make` boilerplate on custom services | ○ Pending |
498+
| Container autowiring unit tests (`tests/Unit/Infrastructure/Container/`) | ○ Pending |
499+
| Developer documentation update for custom service constructors | ○ Pending |
500+
501+
**Exit criteria:** Developers can register custom services in the container with standard typed/positional constructor arguments. The container uses PHP Reflection to map parameter names to container keys, falling back to default arguments or throwing descriptive runtime exceptions when dependencies cannot be resolved.

src/MCP/McpPolicy.php

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,19 +57,28 @@ public function has_capability( string $capability, ?string $model_type = null )
5757
* @return bool
5858
*/
5959
public function is_enabled( Model $model, string $capability ): bool {
60-
$options = $model->get_options();
61-
62-
if ( empty( $options['mcp_tools'] ) ) {
63-
return false;
60+
$options = $model->get_options();
61+
$global_val = null;
62+
if ( array_key_exists( 'mcp_tools', $options ) ) {
63+
$global_val = (bool) $options['mcp_tools'];
6464
}
6565

66-
if ( $capability === ModelRestPolicy::CAPABILITY_HEALTH || $capability === ModelRestPolicy::CAPABILITY_MODELS ) {
66+
if ( $capability === ModelRestPolicy::CAPABILITY_HEALTH ) {
6767
return true;
6868
}
6969

70-
$config = $model->get_config();
70+
if ( $capability === ModelRestPolicy::CAPABILITY_MODELS ) {
71+
return $global_val === true;
72+
}
73+
74+
$config = $model->get_config();
75+
$feature_val = $this->resolve_feature_value( $config, $capability );
76+
77+
if ( $feature_val !== null ) {
78+
return $feature_val;
79+
}
7180

72-
return $this->resolve_show_in_mcp( $config, $capability );
81+
return $global_val === true;
7382
}
7483

7584
/**
@@ -107,13 +116,13 @@ private function get_capability_config( array $config, string $capability ) {
107116
* Resolve whether a capability should be shown in MCP.
108117
*
109118
* @param array<string, mixed> $config
110-
*
111-
* @return bool
119+
* @param string $capability
120+
* @return bool|null
112121
*/
113-
private function resolve_show_in_mcp( array $config, string $capability ): bool {
122+
private function resolve_feature_value( array $config, string $capability ): ?bool {
114123
$section = $this->get_capability_config( $config, $capability );
115124
if ( $section === null ) {
116-
return true;
125+
return null;
117126
}
118127

119128
if ( ! is_array( $section ) ) {

src/Rest/ModelRestPolicy.php

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,28 @@ public function has_capability( string $capability, ?string $model_type = null )
4040
}
4141

4242
public function is_enabled( Model $model, string $capability ): bool {
43-
$options = $this->get_model_options( $model );
44-
45-
if ( array_key_exists( 'show_in_rest', $options ) && $options['show_in_rest'] === false ) {
46-
return false;
43+
$options = $this->get_model_options( $model );
44+
$global_val = null;
45+
if ( array_key_exists( 'show_in_rest', $options ) ) {
46+
$global_val = (bool) $options['show_in_rest'];
4747
}
4848

49-
if ( $capability === self::CAPABILITY_HEALTH || $capability === self::CAPABILITY_MODELS ) {
49+
if ( $capability === self::CAPABILITY_HEALTH ) {
5050
return true;
5151
}
5252

53-
$config = $model->get_config();
53+
if ( $capability === self::CAPABILITY_MODELS ) {
54+
return $global_val !== false;
55+
}
56+
57+
$config = $model->get_config();
58+
$feature_val = $this->resolve_feature_value( $config, $capability );
5459

55-
return $this->resolve_show_in_rest( $config, $capability );
60+
if ( $feature_val !== null ) {
61+
return $feature_val;
62+
}
63+
64+
return $global_val === true;
5665
}
5766

5867
/**
@@ -87,12 +96,16 @@ private function get_capability_config( array $config, string $capability ) {
8796
}
8897

8998
/**
99+
* Resolve the capability value from the feature configuration.
100+
*
90101
* @param array<string, mixed> $config
102+
* @param string $capability
103+
* @return bool|null
91104
*/
92-
private function resolve_show_in_rest( array $config, string $capability ): bool {
105+
private function resolve_feature_value( array $config, string $capability ): ?bool {
93106
$section = $this->get_capability_config( $config, $capability );
94107
if ( $section === null ) {
95-
return true;
108+
return null;
96109
}
97110

98111
if ( ! is_array( $section ) ) {

0 commit comments

Comments
 (0)