Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
102 commits
Select commit Hold shift + click to select a range
5d1afc1
Add solution skeleton: projects, central package management, and root…
ImanEstiri Oct 24, 2026
6f509eb
Add core enums for AgentScript commands, statuses, and agent events
ImanEstiri Oct 24, 2026
c3ca610
Add AgentScript v1 parser, validator, and format guard with tests
ImanEstiri Oct 24, 2026
6cda371
Add workspace execution layer: git service, guards, executors, and ba…
ImanEstiri Oct 24, 2026
fb7832f
Add phase 3 tests and harden sandbox, slug builder, and policy
ImanEstiri Oct 24, 2026
62b9b59
.
ImanEstiri Oct 24, 2026
30c9dfa
Add snapshot service (bat runner, filter, chunking) and result formatter
ImanEstiri Oct 25, 2026
1653457
Add chat provider layer: Playwright driver, selectors catalog, reply …
ImanEstiri Oct 25, 2026
6d2e79f
Add agent loop, session store, configuration, and system prompt
ImanEstiri Oct 25, 2026
39c5ee2
Add the keyless CLI: commands, Spectre UI implementation, and tool pa…
ImanEstiri Oct 25, 2026
0938497
Add documentation and finish the final checklist review
ImanEstiri Oct 25, 2026
534b921
Make the workspace path the first input instead of assuming the curre…
ImanEstiri Oct 25, 2026
1f4b411
Fix CLI crash: never run prompts under a live display; make turns non…
ImanEstiri Oct 25, 2026
ecacb42
Fix reply-identity bug: never return the previous assistant reply
ImanEstiri Oct 25, 2026
2cf1aff
.
ImanEstiri Oct 26, 2026
ef24294
Handle line endings: workspace CRLF files survive model LF text
ImanEstiri Oct 26, 2026
2564b58
Make approval behavior consistent and safer
ImanEstiri Oct 26, 2026
9067199
Harden CLI console handling and make failures diagnosable
ImanEstiri Oct 26, 2026
65a4dce
Harden send-button and toggle selectors against the real DOM sample
ImanEstiri Oct 26, 2026
964022b
Add /workspace and /help slash commands to the interactive session
ImanEstiri Oct 26, 2026
af2528b
Fix send-logic risks: no duplicate sends, no duplicate attachments
ImanEstiri Oct 26, 2026
7f2a681
Add keyless doctor: live selector check without changing the chat
ImanEstiri Oct 26, 2026
a2f5278
Make IChatPage async with cancellation and improve failure diagnostics
ImanEstiri Oct 27, 2026
c7956b9
Sanitize doctor captures: mask all personal text and identifying attr…
ImanEstiri Oct 27, 2026
20fe134
Treat file-input listing as 'selected', not 'uploaded': wait for send…
ImanEstiri Oct 27, 2026
f4473ca
Remove remaining sync-over-async; enforce with a source-scan test
ImanEstiri Oct 27, 2026
a2bfb6b
Redesign browser connection: dedicated profile, probe/launch/attach, …
ImanEstiri Oct 27, 2026
e7ff40e
Git workflow UX: numbered menus, auto init, no-origin push skip
ImanEstiri Oct 27, 2026
ade53d3
Reply reading via the message Copy button (ReplySource) with DOM fall…
ImanEstiri Oct 27, 2026
0e8cee8
Docs written once: README + docs/* rewrite, consistency tests, DOCS-T…
ImanEstiri Oct 27, 2026
2b97c70
Fix phantom cancel; native C# snapshot analyzer replaces the workspac…
ImanEstiri Oct 27, 2026
d905f5d
Fix paperclip click (OS file dialog) and Enter-only send retry
ImanEstiri Oct 27, 2026
376d55d
docs: send-button selector row and Enter-only retry note
ImanEstiri Oct 27, 2026
40de88e
Remove DOCS-TODO (follow-up fixes documented)
ImanEstiri Oct 27, 2026
3e0ec18
Clean up dead exception filters and a nullable warning from the captu…
ImanEstiri Oct 27, 2026
13566ec
First message = AgentScript rules alone; visible reply trail; hidden …
ImanEstiri Oct 27, 2026
881d907
Prompt lessons from the live run; keep the chat open across turns; au…
ImanEstiri Oct 27, 2026
fe7efca
Workspace capabilities, no-git mode, change tracking, dirty-menu rules
ImanEstiri Oct 27, 2026
134aa88
Command risk classifier and failure-reason model (Task 2 part 1)
ImanEstiri Oct 28, 2026
b8ff945
Command execution model: risk classifier wiring, failure modes, @@nex…
ImanEstiri Oct 28, 2026
36fd7d1
Format reliability: lenient one-line payloads, per-message reminder, …
ImanEstiri Oct 28, 2026
a18ebf7
Browser window behavior: never un-minimize during normal operation
ImanEstiri Oct 28, 2026
35ce80e
Reply panel policy: raw reply shown only when invalid or with -v; com…
ImanEstiri Oct 28, 2026
d2cbb1b
Chat lifecycle: MaxTurnsPerChat, auto new chat, ChatLimitNotice selector
ImanEstiri Oct 28, 2026
c61a718
Task 7: docs written once — README + docs/* + CLI README + consistenc…
ImanEstiri Oct 28, 2026
5431e25
Fix window un-minimize: remove focus from normal operation; add ITimi…
ImanEstiri Oct 28, 2026
c4c87cb
Turn summary with changed files; reply panel policy (invalid-only or -v)
ImanEstiri Oct 28, 2026
44f816c
Docs: browser window config, no-git mode, chat lifecycle; DOCS-TODO r…
ImanEstiri Oct 28, 2026
5da4d26
Add /newchat slash command; chat lifecycle; classifier 108 tests
ImanEstiri Oct 28, 2026
69bc184
Fix dry-run sending to chat: guard request-send with if (!dryRun)
ImanEstiri Oct 28, 2026
513ab2c
Enforce strict batch failure precedence inside the command loop
ImanEstiri Oct 28, 2026
cead72d
Report a missing program as KA_COMMAND_NOT_FOUND, not KA_INTERNAL
ImanEstiri Oct 28, 2026
9a2e998
Validate control directives on parse-valid replies too
ImanEstiri Oct 28, 2026
193bb88
Fix MaxTurnsPerChat ordering, TurnsInChat counting, AgentChangedPaths…
ImanEstiri Oct 28, 2026
f2ce27c
Reset the copy-capture buffer before each capture attempt
ImanEstiri Oct 28, 2026
abc9d2f
Report the send button as disabled when aria-disabled is set
ImanEstiri Oct 28, 2026
6f14f6d
List @@movefile and @@next in the system prompt and format correction
ImanEstiri Oct 28, 2026
5e13a08
Include only known extensions in the code dump
ImanEstiri Oct 28, 2026
b1834b8
Populate AgentTurnResult.ChangeSet so the CLI can show changed files
ImanEstiri Oct 28, 2026
3e86195
Compare the dirty-menu skip against freshly read porcelain
ImanEstiri Oct 28, 2026
58eee01
Log reply-received once and show TurnFinished once per turn
ImanEstiri Oct 28, 2026
243cae6
Correct the raw-reply comment: no -v path exists
ImanEstiri Oct 28, 2026
017a92a
Time every chat phase and add a --timing flag
ImanEstiri Oct 28, 2026
8c26e63
Add approval counts and diff stat to the turn summary
ImanEstiri Oct 28, 2026
94f4669
Set the DeepThink and Search toggles on the first message of a new chat
ImanEstiri Oct 28, 2026
8020069
Apply Browser.WindowMode when auto-launching Chrome
ImanEstiri Oct 28, 2026
b140eab
Honor Snapshot.RefreshAfterEachBatch between batches
ImanEstiri Oct 28, 2026
b88918a
Produce a ChangedFiles attachment in TreeAndChanged mode
ImanEstiri Oct 28, 2026
fa503ce
Detect and recover from chat length exhaustion
ImanEstiri Oct 28, 2026
85473d0
Prove /newchat's clear leads to a new chat on the next turn
ImanEstiri Oct 28, 2026
6a5cc32
Treat shell machinery and Unix paths as Risky in the risk classifier
ImanEstiri Oct 28, 2026
488748b
Split policy segments with quote awareness
ImanEstiri Oct 28, 2026
b665c42
Reject ADS, UNC and device paths in the path sandbox
ImanEstiri Oct 28, 2026
1b6d201
Refuse link escapes in backup and undo
ImanEstiri Oct 28, 2026
86afdcc
Prove file contents are data, never AgentScript commands
ImanEstiri Oct 28, 2026
9e27027
Validate movefile paths in the format guard
ImanEstiri Oct 28, 2026
9114374
Confirm file moves in Ask mode and show the diff
ImanEstiri Oct 28, 2026
35a33fb
Make keyless undo reverse newfile and movefile
ImanEstiri Oct 28, 2026
680592e
Parallel selector waits, instant checks, positive-first login probe
ImanEstiri Oct 29, 2026
e08d828
Fake-page round-trip tests for the wait fixes
ImanEstiri Oct 29, 2026
b932e04
Graceful Ctrl+C in the interactive session
ImanEstiri Oct 29, 2026
ef63a99
Consistent step renderer for progress output
ImanEstiri Oct 29, 2026
753ec0d
Document the responsiveness, control and timing behavior
ImanEstiri Oct 29, 2026
81ad797
Pin the per-phase session timings through the fake page
ImanEstiri Oct 29, 2026
29ea43a
Parallel-wait the remaining sequential selector waits
ImanEstiri Oct 29, 2026
bb4b9d4
Visibility-aware combined wait: a hidden first match cannot mask a la…
ImanEstiri Oct 29, 2026
7d1674f
Time the tab-open phase of the browser connection
ImanEstiri Oct 29, 2026
b84317e
Round-trip tests prove absent fallback lists cost one wait
ImanEstiri Oct 29, 2026
4117f69
Docs must match the real KeylessOptions defaults, verified by test
ImanEstiri Oct 29, 2026
2255729
Never send secrets to the chat through snapshot attachments
ImanEstiri Oct 29, 2026
e5783f2
Stop when the debugging port answers but CDP attach fails
ImanEstiri Oct 29, 2026
c38a18e
A turn that stops early exits with code 2
ImanEstiri Oct 29, 2026
3f20dd6
Corrupt session.json and failing log writes never crash a turn
ImanEstiri Oct 29, 2026
f02cece
Commands after @@done are skipped, not executed
ImanEstiri Oct 29, 2026
9911c2a
Redact secrets from command output in the turn log
ImanEstiri Oct 29, 2026
ed484e5
Use the catalog selectors for the input editability check
ImanEstiri Oct 29, 2026
403ee45
Defect sweep: 4 confirmed fixes, 2 invariants, 2 already covered
ImanEstiri Oct 29, 2026
f0e8bce
The application version comes from one place: Directory.Build.props
ImanEstiri Oct 29, 2026
0a2cee4
Make publish.ps1 safe: SkipPush without a key, exact package name
ImanEstiri Oct 29, 2026
859599f
Document the queued-fix behaviors (DOCS-TODO applied and deleted)
ImanEstiri Oct 29, 2026
ee5ac77
Copy-capture click loop: one combined wait, not 3s per fallback
ImanEstiri Oct 29, 2026
9bcbf3b
Four small verified fixes
ImanEstiri Oct 29, 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
39 changes: 39 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
root = true

[*]
charset = utf-8
end_of_line = crlf
insert_final_newline = true
trim_trailing_whitespace = true

[*.cs]
indent_style = space
indent_size = 4
csharp_style_namespace_declarations = file_scoped:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
csharp_style_var_elsewhere = true:suggestion
csharp_prefer_braces = true:suggestion
csharp_style_expression_bodied_methods = when_on_single_line:suggestion
dotnet_style_qualification_for_field = false:suggestion
dotnet_style_qualification_for_property = false:suggestion
dotnet_style_qualification_for_method = false:suggestion
dotnet_naming_rule.private_fields_underscore.severity = suggestion
dotnet_naming_rule.private_fields_underscore.symbols = private_fields
dotnet_naming_rule.private_fields_underscore.style = underscore_prefix
dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
dotnet_naming_style.underscore_prefix.capitalization = camel_case
dotnet_naming_style.underscore_prefix.required_prefix = _
dotnet_separate_import_directive_groups = false:suggestion
dotnet_sort_system_directives_first = true:suggestion

[*.{xml,csproj,props,targets,slnx,json,yml,yaml,md}]
indent_style = space
indent_size = 2

[*.ps1]
indent_style = space
indent_size = 4

[*.bat]
end_of_line = crlf
12 changes: 12 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
* text=auto
*.cs text
*.csproj text
*.slnx text
*.props text
*.targets text
*.json text
*.md text
*.bat text CRLF
*.ps1 text CRLF
*.png binary
*.gif binary
29 changes: 29 additions & 0 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: build-and-test

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build-and-test:
runs-on: windows-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x

- name: Restore
run: dotnet restore

- name: Build
run: dotnet build --no-restore -c Release

- name: Test
run: dotnet test --no-build -c Release
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
bin/
obj/
artifacts/
.agent/
tree-view-result.txt
code-dump-result.md
*.user
*.suo
.vs/
.idea/
TestResults/
*.nupkg
*.snupkg
50 changes: 50 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<Project>

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<AnalysisLevel>latest</AnalysisLevel>
<AnalysisMode>All</AnalysisMode>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<CodeAnalysisTreatWarningsAsErrors>false</CodeAnalysisTreatWarningsAsErrors>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<InvariantGlobalization>false</InvariantGlobalization>
<NuGetAudit>false</NuGetAudit>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup>
<!-- CA1031: boundary methods intentionally convert any exception into an Outcome failure.
CA1040: IService is a deliberate marker interface (DepLens convention).
CA1303: the CLI is not a localized application.
CA1307/CA1308: StringComparison overload suggestions on char comparisons are noise here.
CA1822: stateless runners stay instance methods for injection symmetry.
S3267: "simplify loop" suggestions fight legitimate async loops with early returns.
CA1707, S1135, CA1861: style choices mirrored from the reference repository. -->
<NoWarn>$(NoWarn);CA1873;CA2007;CA1031;CA1040;CA1303;CA1307;CA1308;CA1822;S3267;CA1707;S1135;CA1861;CA1056;CA1054;CA2000;CA5394;S1075;S2245</NoWarn>
</PropertyGroup>
<ItemGroup Condition="'$(MSBuildProjectExtension)' != '.dcproj' and '$(MSBuildProjectName)' != 'ImanSoftware.KeylessAgent.Tests'">
<PackageReference Include="SonarAnalyzer.CSharp">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<PropertyGroup>
<!-- The single source of the application version: Program.cs reads it from the
assembly and publish.ps1 bumps it here. -->
<Version>1.0.0</Version>
<Authors>Iman Estiri</Authors>
<Company>ImanSoftware</Company>
<Copyright>Copyright (c) $([System.DateTime]::Now.Year) ImanSoftware</Copyright>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/ImanEstiri/KeylessAgent</PackageProjectUrl>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<RepositoryUrl>https://github.com/ImanEstiri/KeylessAgent</RepositoryUrl>
<PackageReadmeFile Condition="Exists('README.md')">README.md</PackageReadmeFile>

</PropertyGroup>
</Project>
32 changes: 32 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="AngleSharp" Version="1.4.0" />
<PackageVersion Include="coverlet.collector" Version="10.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageVersion>
<PackageVersion Include="FluentAssertions" Version="7.2.2" />
<PackageVersion Include="ImanSoftware.DateTimeProvider" Version="1.0.1" />
<PackageVersion Include="ImanSoftware.Extensions" Version="1.0.5" />
<PackageVersion Include="ImanSoftware.FileStorage" Version="2.1.3" />
<PackageVersion Include="ImanSoftware.Logging" Version="1.0.2" />
<PackageVersion Include="ImanSoftware.Outcome" Version="1.0.4" />
<PackageVersion Include="ImanSoftware.Serialization" Version="1.0.3" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.13" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.11.0" />
<PackageVersion Include="Microsoft.Playwright" Version="1.64.1" />
<PackageVersion Include="SonarAnalyzer.CSharp" Version="10.35.0.4138" />
<PackageVersion Include="Spectre.Console" Version="0.57.2" />
<PackageVersion Include="Spectre.Console.Cli" Version="0.57.2" />
<PackageVersion Include="Spectre.Console.Testing" Version="0.57.2" />
<PackageVersion Include="NSubstitute" Version="5.3.0" />
<PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="4.0.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageVersion>
</ItemGroup>
</Project>
7 changes: 7 additions & 0 deletions KeylessAgent.slnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Solution>
<Project Path="src\Core\ImanSoftware.KeylessAgent.Abstractions\ImanSoftware.KeylessAgent.Abstractions.csproj" />
<Project Path="src\Core\ImanSoftware.KeylessAgent.Core\ImanSoftware.KeylessAgent.Core.csproj" />
<Project Path="src\UI\ImanSoftware.KeylessAgent.Cli\ImanSoftware.KeylessAgent.Cli.csproj" />
<Project Path="src\Playground\ImanSoftware.KeylessAgent.Playground\ImanSoftware.KeylessAgent.Playground.csproj" />
<Project Path="src\tests\ImanSoftware.KeylessAgent.Tests\ImanSoftware.KeylessAgent.Tests.csproj" />
</Solution>
21 changes: 21 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Iman Estiri

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Loading
Loading