Maybe you have solved that already, but just for clarification:

If keywords are just constants (like integers), but
procedure application recognizes these keywords to
supply keyword-arguments, then how do I pass a keyword
value to a procedure?

Is there any syntactic difference at the call site, i.e.
can I determine from (paint color: "red") whether paint has
one (named color:) or two arguments (a keyword and a string)?

As an alternative, the ambiguity would go away if the
syntax extension requires parentheses for the keyword-
arguments. This might even allow simple implementations
as 'implicitly defined procedures', i.e. each identifier
ending in ':', say <keyword>:, is defined as

  (lambda args (apply make-option '<keyword> args)),

where <keyword> is a lexical variable. The only modification
to procedure calls is that they collect all the optional
arguments in a special variable available to the procedure.
It boils down to syntax like (paint (color: "red") (button: 'push)).

[I am in favor of your mechanism for named arguments but
would like to explore the implications and alternatives.]