Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
2f7d164
Phase 1: agent-skills scaffolding and reference corpus
petrsnd Jun 2, 2026
207fe06
added Invoke-PlatformDevLoop.ps1 and associated README
petrsnd Jun 3, 2026
9f07fdf
Minor tweaks based on source code review
petrsnd Jun 3, 2026
82dc3e2
five agent-skill bodies
petrsnd Jun 3, 2026
83ebf39
AGENTS.md: fill routing table, workflows, and debug loop
petrsnd Jun 3, 2026
403e215
AGENTS.md: add PS / API / concept notation convention
petrsnd Jun 3, 2026
b794bf6
learnings from imports and validation
petrsnd Jun 3, 2026
f7646fa
skills: ground function-call signatures in samples, not prose
petrsnd Jun 4, 2026
200b03e
skills: act-then-ask posture — check tools, try secure first, treat s…
petrsnd Jun 4, 2026
42049ef
skills,failure-patterns: capture Phase 5 maiden voyage learnings (no …
petrsnd Jun 4, 2026
dd822f4
skills: codify Phase 5 voyage learnings (sample-grep on signature rep…
petrsnd Jun 4, 2026
7cf414b
skills: normalize .Insecure to [bool] after JSON roundtrip
petrsnd Jun 4, 2026
4b29903
skills,schema: collapse http-api-{basic,bearer,key} into single http-…
petrsnd Jun 4, 2026
8c57b17
Update failure patterns based recent build run
petrsnd Jun 4, 2026
16b448c
Require recent safeguard-ps and handle extended logging in SSH host k…
petrsnd Jun 4, 2026
2a0047d
Trying to be more lean in AGENTS.md
petrsnd Jun 4, 2026
cee38ca
More AGENTS.md trimming
petrsnd Jun 4, 2026
adfdd3e
Incorporating feedback to agent instructions and skills based on my e…
petrsnd Jun 4, 2026
c32cc91
Correct yescrypt misdiagnosis: pass whole shadow line to CompareShado…
petrsnd Jun 4, 2026
4ac6f4e
Mandate DiscoverSshHostKey for SSH platforms in script-authoring
petrsnd Jun 4, 2026
69f2b0b
Add cmdlet quirks: -TaskId guid cast, lexicographic GUIDs, empty SshC…
petrsnd Jun 4, 2026
8654851
Drop historical/phase framing from failure-patterns.md
petrsnd Jun 4, 2026
20726a3
Add operator-correction rule to AGENTS.md iterative debug loop
petrsnd Jun 4, 2026
73ab086
Drop restore-original-password half-promise from AGENTS.md and target…
petrsnd Jun 4, 2026
d33a145
Add Pattern-SshBatchShadowCompare template proven against Ubuntu yesc…
petrsnd Jun 4, 2026
824cae8
learnings from most recent run on OpenBSD
petrsnd Jun 4, 2026
b410de3
target-probing: paramiko as default SSH probe client
petrsnd Jun 4, 2026
7a12cbe
target-probing: separate auth probe from prompt/batch-mode probes
petrsnd Jun 4, 2026
5614afc
operations: hung-cmdlet diagnostic in Cmdlet quirks
petrsnd Jun 4, 2026
88b2f00
sibling cmdlets are not symmetric — strengthen grounding rule
petrsnd Jun 5, 2026
908149f
operations: agent must surface device-code URL and code to operator
petrsnd Jun 5, 2026
6cd4d64
AGENTS: question discipline — fix login bullet, add operator-surfacin…
petrsnd Jun 5, 2026
6515d90
failure-patterns: require reproduction in provenance rule
petrsnd Jun 5, 2026
d05f58d
operations: forward-pointer to discovery setup recipe in failure-patt…
petrsnd Jun 5, 2026
0af15e1
operations: generalize async gate to all Platform Tasks, not just dis…
petrsnd Jun 5, 2026
580b612
docs: cut voyage-narrative framing from skill docs
petrsnd Jun 5, 2026
bfd9a93
docs: drop references to gitignored plan file
petrsnd Jun 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .agents/CONVENTIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Notation conventions

Agent-facing material in this repo distinguishes three shapes so an agent never has to guess whether a token is a cmdlet parameter, an API field, or a transport-agnostic idea.

- **PowerShell** — backtick the literal as it appears in `Get-Help <Cmdlet> -Full`. Switches stand alone; valued parameters use a space before the value.
- `` `-ExtendedLogging` `` (switch), `` `-TaskId <GUID>` `` (valued), `` `Connect-Safeguard -DeviceCode` `` (cmdlet + switch).
- **API / JSON** — backtick a PascalCase field as `Field: value`, mirroring the transfer-object shape SPP emits and accepts.
- `` `ExtendedLogs: true` ``, `` `OperationType: CheckPassword` ``.
- **Concept (transport-agnostic)** — plain English, no backticks. Use this in orchestration prose where the agent should not yet be biased toward PS or API.
- "with extended logging enabled", "trigger the affected operation".

Rule of thumb: `AGENTS.md` speaks **concept**. The skills speak **PowerShell** (e.g., `safeguard-ps-operations`) or **API** with backticks. When a skill bridges them, it shows both forms side by side.
259 changes: 259 additions & 0 deletions .agents/schemas/evidence.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://raw.githubusercontent.com/petrsnd/SafeguardCustomPlatform/main/.agents/schemas/evidence.schema.json",
"title": "Custom Platform Probing Evidence",
"description": "Internal agent contract. The evidence artifact produced by the target-probing skill and consumed by strategy-selection and script-authoring. Distinct from the human-facing platform-script schema in schema/. This is v0 — fields marked TODO require a real probing run to lock down their shape; do not invent values.",
"type": "object",
"required": [
"schemaVersion",
"protocol",
"target",
"serviceAccount",
"probeRun"
],
"additionalProperties": false,
"properties": {
"schemaVersion": {
"type": "string",
"description": "Version of this evidence schema. Bumped when the contract changes.",
"const": "0.1"
},
"protocol": {
"type": "string",
"description": "Transport protocol of the target. SSH and HTTP only — telnet is out of scope for the agent skill system.",
"enum": ["ssh", "http"]
},
"target": {
"type": "object",
"description": "Identification of the target system the probes ran against.",
"required": ["host"],
"additionalProperties": false,
"properties": {
"host": {
"type": "string",
"description": "Hostname or IP of the target. No credentials."
},
"port": {
"type": "integer",
"description": "TCP port. Optional; default depends on protocol."
},
"nonProductionAffirmed": {
"type": "boolean",
"description": "Whether the operator has affirmed the target is non-production. The probe-safety contract requires this to be true before any probe runs."
}
}
},
"serviceAccount": {
"type": "object",
"description": "Service-account identification used by probes to authenticate to the target. Secrets MUST NOT appear here — name and credential kind only.",
"required": ["accountName"],
"additionalProperties": false,
"properties": {
"accountName": {
"type": "string",
"description": "Username/account identifier used for probing. The secret itself is never recorded in evidence."
},
"credentialKind": {
"type": "string",
"description": "What kind of credential the service account uses. Sourced from operator declaration; not inferred.",
"enum": ["password", "ssh-key", "api-key", "bearer-token", "unknown"]
}
}
},
"probeRun": {
"type": "object",
"description": "Metadata about the probing session itself.",
"required": ["startedAt", "probes"],
"additionalProperties": false,
"properties": {
"startedAt": {
"type": "string",
"format": "date-time",
"description": "ISO-8601 UTC timestamp when probing began."
},
"endedAt": {
"type": "string",
"format": "date-time",
"description": "ISO-8601 UTC timestamp when probing concluded. Optional while probing is in progress."
},
"operatorTool": {
"type": "string",
"description": "Identifier of the agent runtime that performed the probes (e.g., 'github-copilot-cli', 'claude-code'). For audit only."
},
"probes": {
"type": "array",
"description": "Ordered record of probes executed. Each entry is a single probe step. Read-only probes record observations; destructive probes additionally record the explicit per-probe consent given by the operator (see the probe-safety contract in target-probing/SKILL.md).",
"items": {
"$ref": "#/definitions/probeRecord"
}
},
"haltedReason": {
"type": "string",
"description": "If probing stopped before completion, why. Examples: 'lockout-signal', 'throttle-signal', 'mfa-challenge', 'operator-stop', 'rate-limit-exceeded'.",
"enum": [
"completed",
"lockout-signal",
"throttle-signal",
"mfa-challenge",
"operator-stop",
"rate-limit-exceeded",
"operator-denied-destructive",
"error"
]
}
}
},
"sshFindings": {
"$ref": "#/definitions/sshFindings",
"description": "Findings produced by SSH probe playbooks. Present only when protocol == 'ssh'."
},
"httpFindings": {
"$ref": "#/definitions/httpFindings",
"description": "Findings produced by HTTP probe playbooks. Present only when protocol == 'http'."
},
"strategyHints": {
"type": "object",
"description": "Optional hints from the probing skill that strategy-selection may consider. Not authoritative — strategy-selection makes the final call.",
"additionalProperties": false,
"properties": {
"preferredPattern": {
"type": "string",
"description": "If probing strongly suggests one of the four authoring patterns, name it here. Otherwise omit.",
"enum": [
"ssh-interactive",
"ssh-batch",
"http-api",
"http-form-fill"
]
},
"rationale": {
"type": "string",
"description": "Short, citation-style reason for the hint. Must reference a specific probe record, not be generic."
}
}
}
},
"definitions": {
"probeRecord": {
"type": "object",
"description": "A single probe step. Field shapes for 'observation' and 'destructiveDetails' are placeholders pending a real probing run; populated structures land in Phase 3 / Phase 5.",
"required": ["id", "kind", "command", "result"],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"description": "Stable ID of the probe within this run. Used for back-references."
},
"kind": {
"type": "string",
"description": "Probe classification. Read-only probes never mutate target state.",
"enum": ["read-only", "destructive"]
},
"category": {
"type": "string",
"description": "What the probe is investigating. SSH categories: prompt, batch-mode, sudo, password-change. HTTP categories: auth-scheme, login-form, cookie, api-discovery.",
"enum": [
"prompt",
"batch-mode",
"sudo",
"password-change",
"auth-scheme",
"login-form",
"cookie",
"api-discovery",
"other"
]
},
"command": {
"type": "string",
"description": "The exact command or HTTP request line that was issued. No secrets — substitute placeholders for credentials."
},
"consent": {
"type": "object",
"description": "Required for destructive probes; absent for read-only probes.",
"additionalProperties": false,
"required": ["grantedAt"],
"properties": {
"grantedAt": {
"type": "string",
"format": "date-time",
"description": "Timestamp the operator granted explicit per-probe consent."
},
"summaryShown": {
"type": "string",
"description": "The one-line 'what this will do, what could go wrong' summary that the operator approved."
}
}
},
"result": {
"type": "string",
"description": "Outcome of the probe.",
"enum": ["ok", "failed", "skipped", "halted"]
},
"observation": {
"description": "TODO: structured observation payload. Shape locked down in Phase 3 once the SSH and HTTP playbooks are authored against real targets. Free-form for now.",
"type": "object",
"additionalProperties": true
},
"errorSignature": {
"type": "string",
"description": "If result is 'failed', a short stable signature suitable for matching against docs/agent-reference/failure-patterns.md. Optional."
}
}
},
"sshFindings": {
"type": "object",
"description": "SSH-specific finding shapes. Fields below are the categories the playbook MUST cover; their internal shape is intentionally permissive in v0 and will be tightened once more SSH targets have been probed.",
"additionalProperties": false,
"properties": {
"shellPrompt": {
"type": "object",
"additionalProperties": true,
"description": "What the shell prompt looks like, banner contents, motd presence, etc."
},
"batchModeSupported": {
"type": "object",
"additionalProperties": true,
"description": "Whether non-interactive ExecuteCommand-style probes succeeded vs needed a PTY."
},
"sudoBehavior": {
"type": "object",
"additionalProperties": true,
"description": "Whether sudo prompts for a password, has NOPASSWD, or is not present."
},
"passwordChangeCommand": {
"type": "object",
"additionalProperties": true,
"description": "Which password-change command path the target supports (passwd, chpasswd, vendor-specific CLI, etc.) — observed, not assumed."
}
}
},
"httpFindings": {
"type": "object",
"description": "HTTP-specific finding shapes. Fields below are the categories the playbook MUST cover; their internal shape is intentionally permissive in v0 and will be tightened once more HTTP targets have been probed.",
"additionalProperties": false,
"properties": {
"authScheme": {
"type": "object",
"additionalProperties": true,
"description": "Which authentication scheme(s) the target accepts (basic, bearer, api-key header, form-fill, cookie). Observed via WWW-Authenticate, login form inspection, etc."
},
"loginForm": {
"type": "object",
"additionalProperties": true,
"description": "If form-fill is in play: form action URL, field names, hidden tokens (CSRF), redirect chain."
},
"cookieBehavior": {
"type": "object",
"additionalProperties": true,
"description": "Session cookie names, flags, lifetimes; whether session cookies suffice for subsequent calls."
},
"apiDiscovery": {
"type": "object",
"additionalProperties": true,
"description": "Discovered API endpoints relevant to the planned operations (e.g., user lookup, password change, key rotation). Sourced from vendor docs or probe responses; never invented."
}
}
}
}
}
Loading
Loading