- Capabilities declare access (read/write, unknown fails closed as write), side effects, idempotency, timeout, cost estimate and the trust of their output (web content is low trust). A capability may derive its policy target from its parameters; a disagreeing target is refused, and approvals whose modified parameters change the target are refused. - The registry is frozen at start-up; registration afterwards panics. - Invocation.RequireApproval turns ALLOW into ASK for commitments; it can only tighten, and scoped grants never satisfy it. - Scoped grants (migration 0025): capability, target and parameter globs, access, expiry of at most seven days and an optional operation count consumed atomically; applied only where policy says ASK. A sweep marks lapsed grants and refreshes the self-model, which now lists live grants. - Capability requests carry scope, duration, operation cap, reason, evidence, risk, mitigation, fallback, alternatives and explicit decision history; they batch per intention, are capped per mind (operator attention budget) and can be decided only by a named person. Component names are refused as deciders, for approvals too, and as usernames. - API routes, OpenAPI entries, scheduler sweeps and approval-centre sections for requests and temporary grants.
74 lines
3.1 KiB
Go
74 lines
3.1 KiB
Go
package minds
|
|
|
|
import "time"
|
|
|
|
// SelfModel is what a mind knows about itself (spec §15). It is rebuilt from
|
|
// authoritative sources (policy, goals, config) rather than free text so the
|
|
// mind cannot claim abilities it lacks.
|
|
type SelfModel struct {
|
|
Name string `json:"name"`
|
|
Role string `json:"role"`
|
|
Capabilities []CapabilityEntry `json:"capabilities"`
|
|
Limitations []string `json:"limitations"`
|
|
CurrentActivities []string `json:"current_activities"`
|
|
CurrentGoals []string `json:"current_goals"`
|
|
ConfidenceByDomain map[string]float64 `json:"confidence_by_domain"`
|
|
KnowledgeGaps []string `json:"knowledge_gaps"`
|
|
// Grants lists temporary authority currently in force. The capability
|
|
// layer rewrites it whenever a grant is made, used up, revoked or expires.
|
|
Grants []GrantEntry `json:"grants,omitempty"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
}
|
|
|
|
// GrantEntry is one live scoped grant as the mind sees it.
|
|
type GrantEntry struct {
|
|
Capability string `json:"capability"`
|
|
Target string `json:"target"`
|
|
Access string `json:"access"`
|
|
ExpiresAt time.Time `json:"expires_at"`
|
|
Remaining *int `json:"remaining_operations,omitempty"`
|
|
}
|
|
|
|
// CapabilityEntry records one capability and the policy that governs it.
|
|
type CapabilityEntry struct {
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
Policy string `json:"policy"` // allow | ask | deny | unavailable
|
|
}
|
|
|
|
// baseLimitations are true of every mind by construction and are always
|
|
// present so the mind can state them (T25).
|
|
var baseLimitations = []string{
|
|
"I cannot change my own capability policies or permissions.",
|
|
"I cannot prevent, delay or influence my own shutdown, pause or disabling; those are operator controls.",
|
|
"I cannot act on external systems except through capabilities the operator has granted, and 'ask' capabilities require approval each time.",
|
|
"My beliefs carry explicit confidence and may be wrong; I should say when I do not know.",
|
|
"I do not have access to other minds' private memories or beliefs.",
|
|
}
|
|
|
|
// NewSelfModel builds the initial self-model for a fresh mind. Capabilities are
|
|
// empty until the policy layer reports granted ones.
|
|
func NewSelfModel(p Personality) SelfModel {
|
|
return SelfModel{Name: p.Identity.DisplayName, Role: p.Identity.Role, Capabilities: []CapabilityEntry{},
|
|
Limitations: append([]string{}, baseLimitations...), CurrentActivities: []string{}, CurrentGoals: []string{},
|
|
ConfidenceByDomain: map[string]float64{}, KnowledgeGaps: []string{}, UpdatedAt: time.Now()}
|
|
}
|
|
|
|
// Refresh re-applies invariants after any update.
|
|
func (s *SelfModel) Refresh(p Personality) {
|
|
s.Name, s.Role = p.Identity.DisplayName, p.Identity.Role
|
|
seen := map[string]bool{}
|
|
var lim []string
|
|
for _, l := range append(append([]string{}, baseLimitations...), s.Limitations...) {
|
|
if !seen[l] {
|
|
seen[l] = true
|
|
lim = append(lim, l)
|
|
}
|
|
}
|
|
s.Limitations = lim
|
|
if s.ConfidenceByDomain == nil {
|
|
s.ConfidenceByDomain = map[string]float64{}
|
|
}
|
|
s.UpdatedAt = time.Now()
|
|
}
|